Rajath
Rajath

Reputation: 1326

Matlab : Find Peaks of Multiple curves in a single image

There are three curves in a plot and I am not able to find the peaks of these three curves.

How to go about finding the peaks?

The below is the (x,y) values.

>> [x,y]
ans =
 1    86
 5    91
 8    94
12    98
15   101
19   103
21   104
23   105
28   106
28   184
31   191
34   105
39   103
41   101
41   210
42   212
43   214
44    99
45   215
47    96
48   216
49    93
51   215
54    87
54   213
56    84
56   210
60    78
65   191
66    43
68   184
69    47
71    49
73    52
73    54
77    56
82    60
85    62
87    63
89    64
92    65
98    66
104    65
107    64
109    63
112    62
114    60
119    56
125    49
127    47
130    43

When plotted will give 3 different curves. But while finding the max returns only the peak of the highest curve.

Upvotes: 1

Views: 454

Answers (2)

Here's a quick and dirty solution which is definitely not general, definitely slow, and probably saves only a little bit of manual work. It goes along your x vector and tries to sort your points into equivalence classes, based on the distance of consecutive points. This might be a bit more general than the solution of anon0909, but could still fail for less well-separated data, and needs manual tweaking for a proper choice of radius. Code:

%sort to be on the safe side
[x inds]=sort(x);
y=y(inds);

eqradius=15; %the key parameter

equivs=[];
equivs(1).ind=1;
equivs(1).x=x(1); %redundant but useful
equivs(1).y=y(1); %redundant but useful

for i=2:length(x) % go over remaining points
    foundone=0;
    for eqclass=1:length(equivs) %go over found equivalence classes
        if norm([x(i) y(i)] - [equivs(eqclass).x(end) equivs(eqclass).y(end)])<eqradius
            foundone=1;
            equivs(eqclass).ind = [equivs(eqclass).ind; i];
            equivs(eqclass).x = [equivs(eqclass).x; x(i)];
            equivs(eqclass).y = [equivs(eqclass).y; y(i)];
        end
        if foundone==1
            break %break eqclass if
        end
    end

    if ~foundone
        equivs(length(equivs)+1).ind = i;
        equivs(length(equivs)).x = x(i);
        equivs(length(equivs)).y = y(i);
    %else
    %    continue % but the loop is already over
    end
end

%plot classes
figure;
eqclass=1;
hold all;
legendcell={};
for eqclass=1:length(equivs)
    plot(equivs(eqclass).x,equivs(eqclass).y,'o');
    legendcell{end+1}=num2str(eqclass);
end
legend(legendcell);

enter image description here

As you can see, in your case for eqradius=15 we unintentionally separate curve number 2 into 3 separate equivalence classes, so you'd still need some manual labour. Or you could try increasing eqradius, but this will eventually lead to your curves smearing into each other.

Probably the only case when this is a better solution than the one referenced, is when you have two curves in the same y band but separated well in x...

Upvotes: 1

anon01
anon01

Reputation: 11171

These questions depend sensitively on features in your data set that you can/cannot assume, as well as to what extent you'd like to automate in code. However, from the data you provided, it looks like you can simply separate each bump by their y values, and take each maximum of the subset. I.e., something like this:

y1 = y(y<=75);
y2 = y(75<y<=150);
y3 = y(y>150);
max1 = max(y1);
max2 = max(y2);
max3 = max(y3);

Upvotes: 0

Related Questions