Searching for specific maxima
이전 댓글 표시
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
Walter Roberson
2012년 1월 17일
What if more than one location has the same maximum (or second highest) value?
답변 (5개)
the cyclist
2012년 1월 18일
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
Sarah
2012년 1월 18일
Walter Roberson
2012년 1월 18일
There are a number of peak-picking routines in the MATLAB File Exchange; they should work better than looking at the maxima.
Image Analyst
2012년 1월 18일
I agree with Walter. The cyclist's code will do what he says but it won't necessarily find peaks or help you locate them, unless your second peak is the second highest value. For example if you still have two peaks but your data looks like x = [1 2 1 2 3 2 3 4 122 120 4 5 3 51 4 2] your second value will be 120, which was part of the first peak, and your second peak is now located as the third value of the sorted array - probably not where you expected to find it. (This is a different watchout than Walter's warning of multiple elements with the same value.)
the cyclist
2012년 1월 18일
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/
Sarah
2012년 1월 18일
Andrei Bobrov
2012년 1월 18일
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
the cyclist
2012년 1월 18일
Note that the findpeaks() function is part of the Signal Processing Toolbox, so you may not have access to it.
Sarah
2012년 1월 18일
Andrei Bobrov
2012년 1월 18일
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
2012년 1월 18일
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
Sarah
2012년 1월 18일
Dr. Seis
2012년 1월 18일
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%).
Sarah
2012년 1월 22일
Sarah
2012년 1월 22일
0 개 추천
댓글 수: 12
Dr. Seis
2012년 1월 22일
You don't happen to have a short example (like the size you posted before) where the threshold method breaks down? Is it that in certain circumstances the second peak falls way below the defined threshold... or does findpeaks not actually see a double peak when those two peaks begin to merge?
Sarah
2012년 1월 22일
Image Analyst
2012년 1월 22일
It looks like you're plotting only the markers and maybe they oscillate on an element by element basis giving the appearance of two separate plots. Can you set xlim([9.475 9.525]) and plot with lines, like plot(data, 'bo-') so we can see what's going on?
Sarah
2012년 1월 22일
Sarah
2012년 1월 22일
Dr. Seis
2012년 1월 22일
Sorry, one more plot. Can you plot <http://i.imgur.com/RzcOW.jpg> using the same limits as <http://i.imgur.com/8K2ZZ.jpg> (i.e., [9.475 9.525])? So, just to be sure, in the earlier picture where there are two peaks, the robust peak finder should in fact return two peaks?
Sarah
2012년 1월 22일
Sarah
2012년 1월 22일
Dr. Seis
2012년 1월 22일
So... I think I see the problem. There are going to be cases where you might need a threshold of 10% so that (as in the case immediately above) it will detect both the primary and the secondary peak. But (maybe) in other cases a threshold of 10% will return peaks that it should not have.
Dr. Seis
2012년 1월 22일
Is there, perhaps, a window of indices around the main peak that it should check? For example, it should only check for extra peaks +/- 500 indices from the main peak?
Sarah
2012년 1월 22일
Dr. Seis
2012년 1월 22일
Try a range of 1.1 times the number of indices associated with the width of your pulse.
Dr. Seis
2012년 1월 22일
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.
카테고리
도움말 센터 및 File Exchange에서 Descriptive Statistics에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!