0

I have a function to detect the peak of real-time data. The algorithm is mentioned in this thread. which looks like this:

std::vector<int> smoothedZScore(std::vector<float> input)
{
    //lag 5 for the smoothing functions
    int lag = 5;
    //3.5 standard deviations for signal
    float threshold = 3.5;
    //between 0 and 1, where 1 is normal influence, 0.5 is half
    float influence = .5;

    if (input.size() <= lag + 2)
    {
        std::vector<int> emptyVec;
        return emptyVec;
    }

    //Initialise variables

    std::vector<int> signal(input.size(), 0.0);
    std::vector<float> filteredY(input.size(), 0.0);
    std::vector<float> avgFilter(input.size(), 0.0);
    std::vector<float> stdFilter(input.size(), 0.0);
    std::vector<float> subVecStart(input.begin(), input.begin() + lag);

    double sum = std::accumulate(std::begin(subVecStart), std::end(subVecStart), 0.0);
    double mean =  sum / subVecStart.size();

    double accum = 0.0;
    std::for_each (std::begin(subVecStart), std::end(subVecStart), [&](const double d) {
        accum += (d - mean) * (d - mean);
    });

    double stdev = sqrt(accum / (subVecStart.size()-1));
    //avgFilter[lag] = mean(subVecStart);
    avgFilter[lag] = mean;
    //stdFilter[lag] = stdDev(subVecStart);
    stdFilter[lag] = stdev;

    for (size_t i = lag + 1; i < input.size(); i++)
    {
        if (std::abs(input[i] - avgFilter[i - 1]) > threshold * stdFilter[i - 1])
        {
            if (input[i] > avgFilter[i - 1])
            {
                signal[i] = 1; //# Positive signal
            }
            else
            {
                signal[i] = -1; //# Negative signal
            }
            //Make influence lower
            filteredY[i] = influence* input[i] + (1 - influence) * filteredY[i - 1];
        }
        else
        {
            signal[i] = 0; //# No signal
            filteredY[i] = input[i];
        }
        //Adjust the filters
        std::vector<float> subVec(filteredY.begin() + i - lag, filteredY.begin() + i);
//        avgFilter[i] = mean(subVec);
//        stdFilter[i] = stdDev(subVec);
    }
    return signal;
}

In my code, I'm reading real-time 3 axis accelerometer values from IMU sensor and displaying it as a graph. I need to detect the peak of the signal using the above algorithm. I added the function to my code. Let's say the realtime valuees are following:

  double x = sample->acceleration_g[0];
  double y = sample->acceleration_g[1];
  double z = sample->acceleration_g[2];

How do I pass this value to the above function and detect the peak.

I tried calling this: smoothedZScore(x)

but gives me an error:

settings.cpp:230:40: error: no matching function for call to 'smoothedZScore'
settings.cpp:92:18: note: candidate function not viable: no known conversion from 'double' to 'std::vector<float>' for 1st argument

EDIT

The algorithm needs a minimum of 7 samples to feed in. So I guess I may need to store my realtime data in a buffer.

But I've difficulty understanding how to store samples in a buffer and apply to the peak detection algorithm.

can you show me a possible solution to this?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • 1
    How are you planning to detect peaks from one value? As stated in the answer you linked, the algorithm needs at least `lag + 2` inputs. – molbdnilo May 05 '20 at 11:02
  • 1
    _I tried calling this: `smoothedZScore(x)`_ What type has `x`? From your exposed error message, I deduce it is `double x;`. You cannot pass type `double` where the only expected is `std::vector`. You could do instead `smoothedZScore({ x })` (or more explicitly `smoothedZScore(std::vector(1, x));`. However, are you sure it makes sense to call your function with 1 value only? – Scheff's Cat May 05 '20 at 11:05
  • Hi all, Thanks a lot for your feedback. I just edited the OP. can someone help how to store realtime data into a buffer and apply to the algorithm? –  May 05 '20 at 11:18

1 Answers1

1

You will need to rewrite the algorithm. Your problem isn't just a realtime problem, you also need a causal solution. The function you have is not causal.

Practically speaking, you will need a class, and that class will need to incrementally calculate the standard deviation.

MSalters
  • 173,980
  • 10
  • 155
  • 350