1
$\begingroup$

I have the following plot and a file of the data which creates that plot. I would like to have Matlab find the following points for me:

  1. [y,x] for peak noted by the 100% line
  2. [x] for where the plot crosses the y=0 line
  3. [x] for where y is 50% and 20% of the peak found in part 1.

Are there any add-on tools or packages which people are aware of which can help me accomplish this? I need to do this for a collection of plots so something reasonably automated would be ideal.

I can certainly do the programming and calculation parts in Matlab, it's just a matter of being able to load in the data file, matching it to a curve or function, and find the various [x,y] co-ordinates.

Data plot

Update Here's a sample dataset I am testing with:

x-values        y-values
-9.90056E+01    4.08949E-03
-8.58224E+01   -2.52083E-02
-7.26381E+01    3.39976E-02
-5.94526E+01   -6.90023E-02
-4.62659E+01    8.37428E-02
-3.30781E+01   -1.74139E-01
-1.98891E+01    2.09784E-01
-6.69894E+00    7.43248E-01
6.49238E+00    6.08539E-02
1.96849E+01   -1.64983E-01
3.28785E+01    8.34376E-02
4.60733E+01   -6.71712E-02
5.92692E+01    7.21458E-02
7.24664E+01   -2.20038E-02
8.56646E+01    3.44554E-02
9.88641E+01   -9.46063E-04
$\endgroup$

2 Answers 2

2
$\begingroup$

Maybe this code can help you:

function mse


x = linspace(0,10,100);
y = sin(x)+x-(x/5).^2;
hold off

plot(x,y)

yMax = max(y);
xMax = x(find(y==yMax));

hold on
plot(xMax,yMax,'*g')



y90 = yMax*0.9;
plot(x,y90,'-k')


for i=2:length(x)
    if y(i-1)<=y90 && y(i)>=y90 || y(i-1)>=y90 && y(i)<=y90
        plot(x(i),y(i),'og')
        plot(x(i-1),y(i-1),'og')

    end
end


y50 = yMax*0.5;
plot(x,y50,'-k')
for i=2:length(x)
    if y(i-1)<=y50 && y(i)>=y50 || y(i-1)>=y50 && y(i)<=y50
        plot(x(i),y(i),'og')
        plot(x(i-1),y(i-1),'og')

    end
end
end

Here $x,y$ are my data. Finding the maximum is easy, but for the 90% or 50% values I iterated through the data. As we do not have continous data we check, whether the 90% or 50% values lies between to points. The result is shown below. If you only want to highlight a single point instead of the two you could perform some (linear) interpolation. enter image description here

EDIT: This would highlight all points that match the X% criteria. If you only want to highlight the closest points to the maximum, you could change the loop to something like

 for i=find(y==ymax):length(x)

Which finds the point on the right and for the left side

 for i=find(y==ymax):-1:length(x)

To mark only one point you could use a break command.

EDIT2: The following code performs the same thing as the for loops, but it is shorter.

y90 = yMax*0.9;
xId= find(diff(sign(y-y90))~=0);
plot(x(xId),y(xId),'*k')
plot(x(xId+1),y(xId+1),'*k')

EDIT3: For your date you need to interpolate between the two values. Replace the loop with something like

for i=2:length(x)
    if y(i-1)<=y90 && y(i)>=y90 || y(i-1)>=y90 && y(i)<=y90
        plot(x(i),y(i),'og')
        plot(x(i-1),y(i-1),'og')

        xl = x(i-1);
        yl = y(i-1);
        xr = x(i);
        yr = y(i);

        xMid  = (y90-yl)*(xr-xl)/(yr-yl)+xl;
        plot(xMid,y90,'or');

    end
end
$\endgroup$
9
  • 1
    $\begingroup$ You can get the index by calling with two output parameters: $[value,index]=\max(array)$. $\endgroup$
    – Daryl
    Apr 8, 2013 at 11:50
  • $\begingroup$ @Daryl: Thanks! I did not know that. $\endgroup$
    – Thomas
    Apr 8, 2013 at 11:51
  • $\begingroup$ @macydanim: This is a great help. When I replace your signal with the data I have though, it doesn't hit the points on the 50%/90% line. I'll update the question with my dataset. $\endgroup$
    – Carl
    Apr 8, 2013 at 12:31
  • $\begingroup$ @Carl, yeah that is due to the problem that the jumps between your data are large. In my example this is not the case. Therefore, the point above and below the 90% line is exactly the maximum and a value far below. I think you need to interpolate in this case, give me some time. $\endgroup$
    – Thomas
    Apr 8, 2013 at 12:38
  • $\begingroup$ @Carl see the last edit, this works for me, using your date $\endgroup$
    – Thomas
    Apr 8, 2013 at 12:45
1
$\begingroup$

You can find the maximum point using the $\tt max$ and $\tt find$ commands in Matlab:

$\tt ymax = max(y);$

$\tt xmax = x(find(y == ymax));$

The other points do not exist in your data, i.e. there is probably no point that hits exactly the 20% line or the 50% line. For these you would need to interpolate.

$\endgroup$
4
  • $\begingroup$ That Matt. That's a useful start for me. Much appreciated. How would I go about getting Matlab to approximate a gaussian curve to fit the signal? From that I should be able to interpolate the 20% and 50% points. $\endgroup$
    – Carl
    Apr 8, 2013 at 11:28
  • 1
    $\begingroup$ $xmax$ would not be the x-position of the maximum, but the ID of the element of vector $x$ where the maximum occurs. So it should rather be xmax = x(find(y==ymax)) $\endgroup$
    – Thomas
    Apr 8, 2013 at 11:30
  • $\begingroup$ @Carl You can also get the index of the maximum value of an array by $[value,index] =\max(array)$. $\endgroup$
    – Daryl
    Apr 8, 2013 at 11:49
  • $\begingroup$ Thanks macydanim for pointing out my mistake, you are perfectly right of course. $\endgroup$
    – Matt L.
    Apr 8, 2013 at 12:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.