Searching for specific maxima
10 views (last 30 days)
Show older comments
Hello Everyone,
I have a specific question. Let us say I have some random data set that looks like this:
1 2 1 2 3 2 3 4 122 3 4 5 3 51 4 2
I am expecting two "maxima" or peaks (not necessarily 122 or 51). I want to be able to autonomously detect the two largest maxima, save the two maxima values and the index where they occur. Is there an easy way to do this?
Thanks for your help.
1 Comment
Walter Roberson
on 17 Jan 2012
What if more than one location has the same maximum (or second highest) value?
Answers (5)
the cyclist
on 18 Jan 2012
x = [1 2 1 2 3 2 3 4 122 3 4 5 3 51 4 2];
[sorted_x indexToSortedValues] = sort(x,'descend');
This will sort the values from high-to-low, and tell you the indices of the sorted values. Be wary of the potential uncertainty that Walter mentions in his comment.
5 Comments
the cyclist
on 18 Jan 2012
I have to admit I totally missed the fact that you seem to be looking for localized peaks, as opposed to just the two largest values (i.e. maxima). There was an FEX "Pick of the Week" for finding local extrema, as discussed here: http://blogs.mathworks.com/pick/2008/05/09/finding-local-extrema/
Andrei Bobrov
on 18 Jan 2012
A = [1 2 1 2 3 2 3 4 122 120 3 4 5 3 51 4 2]
[pks,locs] = findpeaks(A)
[ix,ix] = sort(pks,'descend')
outpks = pks(ix(1:2))
outidx = locs(ix(1:2))
3 Comments
Andrei Bobrov
on 18 Jan 2012
Hi cyclist! Variant without 'findpeaks'.
i1 = diff(A(:).')>0;
ix = strfind(i1,[1 0]);
[c i2] = sort(A(ix),'descend')
outpks = c(1:2)
outidx = ix(i2(1:2))
Dr. Seis
on 18 Jan 2012
Similar to andrei:
A = [1 2 1 2 3 2 3 4 122 120 3 4 5 3 51 4 2]
[pks,locs] = findpeaks(A)
maxpks = max(pks);
threshold = 0.4; % 40% threshold
outpks = pks(pks>threshold*maxpks);
outidx = locs(pks>threshold*maxpks);
Set the threshold so that it will only pick up either: 1) the biggest two picks or 2) one peak
3 Comments
Dr. Seis
on 18 Jan 2012
The threshold value is data dependent. It was just a random value that I picked that would yield the largest of the two peaks and would yield only one peak should those two transition together (since if they joined together there would be no other individual peak greater than 40% of 122+51). If, in reality, the peaks are going to be a lot closer in amplitude than the difference between 122 and 51, then you can make that threshold larger (like 80%). However, if you are expecting a larger range of differences between the largest peak and the second largest peak (before they transition into one peak) then you will need to set that threshold lower (like 20-30%).
Dr. Seis
on 22 Jan 2012
Next idea, instead of envelope of Freq we replace any negative (or really small) frequencies with linear interpolation of positive ones:
tempFreq = Freq(1,:);
maxFreq = max(tempFreq);
for i = 2 : length(tempFreq)-1
if tempFreq(i) <= 0.01*maxFreq
tempFreq(i) = mean(tempFreq([i-1,i+1]));
end
end
[Peaks,Index] = findpeaks(tempFreq);
[MaxPeak,IndPeak] = max(Peaks);
IndRange = abs(Index(IndPeak)-Index);
IndThres = 500; % Set this value to the number of indices
% associated with your pulse width * 1.1
OutPks = Peaks( IndRange <= IndThres );
OutPks = Index( IndRange <= IndThres );
[OutRow,OutColumn] = size(OutPks);
You will still need to define IndThres to be the about 1.1 times your pulse width above.
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!