Why aren't the first and last peaks detected using findpeaks()?

29 vues (au cours des 30 derniers jours)
FsC
FsC le 30 Oct 2022
Commenté : FsC le 8 Déc 2022
I am using the findpeaks() function to detect any peaks in a vector that are greater than a defined threshold (>10% max peak).
I use the following find peaks code but find that the first or last peaks tend to be missed.
% find peaks in vec1 data using find peaks
thresh = .1 * max(dt);
[pks,vec1locs] = findpeaks(vec1, 'MinPeakProminence',thresh);
%plot vector and detected peaks
plot(vec1)
hold on
plot(vec1locs,pks,'or')
Below is the plot of the detected peaks and it didn't detect the last peak.
If I apply the same code with a different vector (vec2), it does not detect the first peak.
I've attached the data vectors if anyone would like to try. Are you seeing the same issue? Why is this happening and how can this be fixed?
Thank you!

Réponse acceptée

Mike Croucher
Mike Croucher le 30 Oct 2022
For vec1, the reason is that the peak is also the last data point and so is intentionally exlcuded. The findpeaks documentation says "Non-Inf signal endpoints are excluded."
For vec2, the issue is thresholding. Your threshold is expressed in terms of dt but you haven't mentioned how this is defined. So, I guessed and put
thresh = 0.1*max(vec2)
which gives around 0.0021, reproducing your second plot including the fact that the first peak is not detected.
Let's compare a peak that is detected (at element 39) with the one that is not (at element 11). The peak at element 39 'sticks out more' compared to its neighbours.
disp('peak at 11')
fprintf("the 10th element is %f\n",vec2(10))
fprintf("the 11th element is %f\n",vec2(11))
fprintf("the 12th element is %f\n",vec2(12))
disp('Peak at 39')
fprintf("the 38th element is %f\n",vec2(38))
fprintf("the 39th element is %f\n",vec2(39))
fprintf("the 40th element is %f\n",vec2(40))
gives
peak at 11
the 10th element is 0.016000
the 11th element is 0.018000
the 12th element is 0.016000
Peak at 39
the 38th element is 0.015000
the 39th element is 0.018000
the 40th element is 0.015000
The threshold I used was 0.0021. Lowering it a little to 0.0020 unfortunately detects too many peaks
I'm not an expert in how to best use findpeaks but one way of getting what you want is to lower the threshold a little and set a minimum peak height. Like this:
load vec2.mat
%thresh = 0.1*max(vec2);
thresh = 0.0019
[pks,vec2locs] = findpeaks(vec2, 'MinPeakProminence',thresh,'MinPeakHeight',0.0175);
%plot vector and detected peaks
plot(vec2)
hold on
plot(vec2locs,pks,'or')
hold off
This gives
  1 commentaire
FsC
FsC le 8 Déc 2022
Thank you for your response! It was very helpful

Connectez-vous pour commenter.

Plus de réponses (1)

Image Analyst
Image Analyst le 30 Oct 2022
Maybe because you don't have a point on the other side so it doesn't know if it's a peak or just a point on the side of a larger, missing peak.
  1 commentaire
FsC
FsC le 30 Oct 2022
That could make sense for vec1 but why is it not detecting the first peak for vec 2?

Connectez-vous pour commenter.

Produits


Version

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by