Forum Rule: Always post complete source code & details to reproduce any issue!

1. ## Peak tracking problem.

Hello!

I'm working on a project where I'm tracking peaks in amplitude and timing and I'm wondering if there is a good way to more accurately track the time occurrence of a peak.

I have filtered out the signal as much as I can and I can track the peaks pretty accurately when they are low to high in amplitude but the outliers that are barely over the threshold are more noisy.

Here is an example of how one of those peaks might look like:

https://www.dropbox.com/s/xzzneso560ap24v/peak.jpg?dl=0

I've filtered out the signal as much as I can and right now I'm tracking when a value goes from ascending to decending and store the time it occurred.

Any way I could maybe make a smooth curve from those samples and use some kind of interpolation to track the exact occurence of the peak?

I'm thinking I should store the last 10 samples before the peak and the 10 samples after in a buffer and then do something with it. Maybe average out the slopes between the last few samples and see where the slope is closest to zero.

Any ideas?

2. What I would do is to
first detect the peak (find a max and this max is greater than threshold)
take, as you say, some samples before and after the peak, take the difference, and estimate zero crossing using linear fit.
Obviously, you can do a quadratic fit over the 21 values, to get best peak estimation (value and location)

3. Originally Posted by WMXZ
What I would do is to
first detect the peak (find a max and this max is greater than threshold)
take, as you say, some samples before and after the peak, take the difference, and estimate zero crossing using linear fit.
Obviously, you can do a quadratic fit over the 21 values, to get best peak estimation (value and location)
Can you explain more in detail how these two examples are done? Or maybe a link to an explanation or some keywords to google?

4. Hi,
Fitting a straight line to the slope of your curve is similar to fitting a quadratic to the data - they will give very slightly different results but the difference will be negligible.
Fitting a straight line is more straightforward. Look up how to get a least-squares best-fit line of the form y = ax+b to a set of data points.
As an example, consider the following data where the first column is a count and the second is the measured values. There's a peak at point 10. If you use a window of 11 points, then you'll fit to the 11 points centred on that point, highlighted below.
Get the 10 differences between each pair of consecutive values - in the fourth column below. Note that they correspond to the mid-points (i.e. to the horizontal values given in the third column).
If you fit a straight line to those 10 data points, you get y = -1.9617x + 19.533. That's a formula for the slope, so the slope is zero (i.e. the peak occurs at) x = 19.533/1.9617 = 9.96.

Choosing the length of the window is a matter of compromise.
Hope that helps you,
All the best,
Alan

 0 -97.47 1 -76.54 2 -60.74 3 -46.45 4 -32.09 5 -21.11 6 -12.95 5.5 8.16 7 -5.21 6.5 7.74 8 -0.63 7.5 4.58 9 0.67 8.5 1.3 10 2.9 9.5 2.23 11 1.97 10.5 -0.93 12 -1.34 11.5 -3.31 13 -5.91 12.5 -4.57 14 -11.43 13.5 -5.52 15 -21.95 14.5 -10.52 16 -31.73 17 -46.57 18 -61.84 19 -78.5

5. If you need help with the math's
https://www.varsitytutors.com/hotmat...ne-of-best-fit

Edit: as an exercise: the procedure can be simplified if you reference the x values to x(max(y)), then result is offset for x(max(y))

6. Originally Posted by AlanK
Hi,
Fitting a straight line to the slope of your curve is similar to fitting a quadratic to the data - they will give very slightly different results but the difference will be negligible.
Fitting a straight line is more straightforward. Look up how to get a least-squares best-fit line of the form y = ax+b to a set of data points.
As an example, consider the following data where the first column is a count and the second is the measured values. There's a peak at point 10. If you use a window of 11 points, then you'll fit to the 11 points centred on that point, highlighted below.
Get the 10 differences between each pair of consecutive values - in the fourth column below. Note that they correspond to the mid-points (i.e. to the horizontal values given in the third column).
If you fit a straight line to those 10 data points, you get y = -1.9617x + 19.533. That's a formula for the slope, so the slope is zero (i.e. the peak occurs at) x = 19.533/1.9617 = 9.96.

Choosing the length of the window is a matter of compromise.
Hope that helps you,
All the best,
Alan

 0 -97.47 1 -76.54 2 -60.74 3 -46.45 4 -32.09 5 -21.11 6 -12.95 5.5 8.16 7 -5.21 6.5 7.74 8 -0.63 7.5 4.58 9 0.67 8.5 1.3 10 2.9 9.5 2.23 11 1.97 10.5 -0.93 12 -1.34 11.5 -3.31 13 -5.91 12.5 -4.57 14 -11.43 13.5 -5.52 15 -21.95 14.5 -10.52 16 -31.73 17 -46.57 18 -61.84 19 -78.5
This is really helpful, thanks I will do it this way.

7. Originally Posted by WMXZ
If you need help with the math's
https://www.varsitytutors.com/hotmat...ne-of-best-fit

Edit: as an exercise: the procedure can be simplified if you reference the x values to x(max(y)), then result is offset for x(max(y))
Thanks, yeah I need to look into the math. However it seems pretty simple.

8. Why can't I just save the 5 last differences between consecutive samples and add them together. When a new sample comes in I store the previous pool of last 5 and update the current one. When the current pool of differences go from positive to negative I have a peak that has occurred somewhere between the average of the 5 midpoints of the 5 latest x values that were positive and the 5 that were negative. I can then use the two y and the two x values to make two points. One will have a positive y and the other negative meaning the curve will have a negative slope crossing zero somewhere on the x axis between the two x values. I then calculate at what x value the line crosses zero using linear interpolation.

Is this wrong? It can be done on the fly as new samples come in.

Please forgive my lack of math lingo.

9. Originally Posted by frankzappa
Why can't I just save the 5 last differences between consecutive samples and add them together. When a new sample comes in I store the previous pool of last 5 and update the current one. When the current pool of differences go from positive to negative I have a peak that has occurred somewhere between the average of the 5 midpoints of the 5 latest x values that were positive and the 5 that were negative. I can then use the two y and the two x values to make two points. One will have a positive y and the other negative meaning the curve will have a negative slope crossing zero somewhere on the x axis between the two x values. I then calculate at what x value the line crosses zero using linear interpolation.

Is this wrong? It can be done on the fly as new samples come in.

Please forgive my lack of math lingo.
I have not reverse engineered your algorithm, but the best estimate of peak is when data are symmetric around max (at least for noisy data)
you can easily do the calculation over the last N samples. It is only a question on how you define your data and the zero crossing is in the middle of your dataset.

10. Originally Posted by WMXZ
I have not reverse engineered your algorithm, but the best estimate of peak is when data are symmetric around max (at least for noisy data)
you can easily do the calculation over the last N samples. It is only a question on how you define your data.
It would be pretty symmetrical, the first 5 values will be one sample offset behind the peak and the other 5 values will be one sample offset before the peak but 4 of the values in each sample pool of 5 would be the same samples. Obviously it could be more than 5.

I also have to say I'm doing time difference of arrival calculation so it's not important to get the exact time, as long as it's consistent so the time difference between peaks is accurate.

11. Hi,

That does seem to be a fairly robust way of doing it - well done!

So, if for sample n, you compare the sign of the sum of d(n-9) to d(n-5) with the sign of the sum of d(n-4) to d(n), where the d values are differences between consecutive samples - d(n) = y(n)-y(n-1), you will get five samples in a row where the signs of those sums are different. If the first sample where the sign is different is sample n, then the peak is roughly at n-3.
You could interpolate using the two sums of differences where they first have different signs to get better accuracy.
All the best,
Alan

12. Originally Posted by frankzappa
I also have to say I'm doing time difference of arrival calculation so it's not important to get the exact time, as long as it's consistent so the time difference between peaks is accurate.
I usually do only a 3point parabolic approximation (it is a simple formula) around the peak of interest

13. Originally Posted by AlanK
Hi,

That does seem to be a fairly robust way of doing it - well done!

So, if for sample n, you compare the sign of the sum of d(n-9) to d(n-5) with the sign of the sum of d(n-4) to d(n), where the d values are differences between consecutive samples - d(n) = y(n)-y(n-1), you will get five samples in a row where the signs of those sums are different. If the first sample where the sign is different is sample n, then the peak is roughly at n-3.
You could interpolate using the two sums of differences where they first have different signs to get better accuracy.
All the best,
Alan
Yes pretty much although I compare the sign of sums of d(n-6) to d(n-1) with the sign of the sums of d(n-5) to d(n). I also average the midpoint of n for each sample pair of the 5 values. The peak would be halfway between the two averaged n. I then use the two n values and the two sums of differences as x and y values and interpolate where exactly the peak occurred.

I think either way works.

The two sets of 5 differences d(n-6) to d(n-1) would be for example: 3, 2, 1, -1, -3 so sum is 2.

D(n-5) to d(n) could be 2, 1, -1, -3, - 3 so sum is -4.

The average n of the first set of five is for example 1.5+2.5+3.5+4.5+5.5/5 = 3.5 and the next is 2.5+3.5+4.5+5.5+6.5/5 = 4.5. I then use the sums as y1 and y2 and the average n as x1 and x2 as coordinates and calculate where the resulting line crosses zero.

14. Anyhow here is a algorithm to estimate a quadratic peak from 3 points (in matlab notation)
Code:
io=find(z==max(z),1);

zm=z(io)-z(io-1);
zp=z(io+1)-z(io);
b=1/2*(zp-zm);
dxo=-1/2*(zp+zm)/(zp-zm);
a=z(io)-b*dxo.^2;

xo=x(io)+dxo;
yo=a;
I'm using for all my time delay estimation

15. Originally Posted by WMXZ
Anyhow here is a algorithm to estimate a quadratic peak from 3 points (in matlab notation)
Code:
io=find(z==max(z),1);

zm=z(io)-z(io-1);
zp=z(io+1)-z(io);
b=1/2*(zp-zm);
dxo=-1/2*(zp+zm)/(zp-zm);
a=z(io)-b*dxo.^2;

xo=x(io)+dxo;
yo=a;
I'm using for all my time delay estimation
Thank you

16. Only to be complete
here is the algorithm (matlab) for 2N+1 points
Code:
N=3;
io=find(z==max(z),1); % locate peak
zm=mean(diff(z(io-N:io)));  % average negative differences (i=i0-N to io)
zp=mean(diff(z(io:io+N)));  % average positive differences (i=io to io+N)
b=1/(2*N)*(zp-zm);
dxo=-N/2*(zp+zm)/(zp-zm);
a=z(io)-b*dxo.^2;

xo=x(io)+dxo;
yo=a;
Having more than 3 points for fitting a quadratic function, i.e. N>1, is useful if data are noisy.

The formula is partially as done by @frankzappa. it only includes the linear interpolation and estimates also the modelled peak of the quadratic.

Edit:
obviously
Code:
zm=mean(diff(z(io-N:io)));  % average negative differences (i=i0-N to io)
zp=mean(diff(z(io:io+N)));  % average positive differences (i=io to io+N)
is equivalent to
Code:
zm=(z(io)-z(io-N))/N;
zp=(z(io+N)-z(io))/N;
which proves that averaging does not help with noise (in fact it only undoes the differentiation noise)

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•