How to find the corner points at a plateau
35 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
I need to find the two corner points at a plateau. For that I am using this function and I am able to get the first but not the second (at the right corner of the red mark and before the curve goes down). Note that the top not always is as flat as in the image.
y = -Data; % invert the signal and get the index of all the first maxs [peakValues, indexes] = findpeaks(y,'MinPeakProminence',500, 'MinPeakWidth', 0.4);
Please any help apreciated.
There is another nd better way to achieve this?
0 comentarios
Respuestas (3)
John D'Errico
el 27 de Feb. de 2017
Editada: John D'Errico
el 28 de Feb. de 2017
I think this is easier than it has been made out to be. Findpeaks won't really work, since it is looking for peaks, and these plateaus are not really constant in value.
The plateaus are regions of the curve here where it has a value of 0, within some tolerance. I lack your data, nor do I know what a reasonable tolerance would be.
Since the plateau appears to be at zero, just do a simple test.
pbool = (y >= -tol);
this gives you a logical vector where the curve is in the plateau region. Then, find the locations in that logical vector where a transition is made into the plateau, and then out of it.
Start by adding with zeros (false) at each end, in case a plateau is already in existence at either end.
pbool = [false, pbool, false];
Now just search for the string [0 1]. That will indicate where a plateau starts. And we will find EVERY plateau in the one operation. Searching for the transition out of the plateau is also easy, because we search for [1 0].
pstart = strfind(pbool,[0 1]);
pend = strfind(pbool,[1 0]) - 1;
the elements of pstart are the beginnings of each plateau. And the corresponding elements of pend are the end points for that plateau. I had to subtract 1 from the end points, because of the zero pad.
y = min(0,sin(0:.1:14) - 0.9);
y = y + randn(size(y)) * 0.001;
plot(y)
grid on
Lets try it out. I know a good tolerance, because I know the noise standard deviation was 0.001. 5 sigma should suffice, so 0.005 should be quite adequate. But if you have no a-priori clue as to the noise variance, you could try my estimatenoise code (on the FEX)
sqrt(estimatenoise(y))
ans =
0.0012083
So 5 sigma would then be 0.006. Either will be close enough for government work.
tol = 0.005;
pbool = (y >= -tol);
pbool = [false, pbool, false];
pstart = strfind(pbool,[0 1]);
pend = strfind(pbool,[1 0]);
pstart
pstart =
13 75 138
pend
pend =
21 84 141
plot(1:numel(y),y,'-b',pstart,y(pstart),'ro',pend,y(pend),'rx')
grid on
The change in case your nominal plateau level is not actually at zero is trivial to code, as long as you know where to set it. That too would be easily done automatically.
1 comentario
Greg Dionne
el 28 de Feb. de 2017
Hi John,
If you look at Armindo's original post, you'll see the findpeaks(-x) trick, so it looks like this is an attempt to find the base points of each peak.
So my hunch is that the data is clipped for anything less than zero (no fuzzy noise on it). BTW, I've always liked your FEX submissions.
Ajinkya Gorad
el 14 de Jun. de 2017
Editada: Ajinkya Gorad
el 14 de Jun. de 2017
You can use the findpeaks to find both the points of the plateau. You could multiply your function with the plateau with the increasing function (e^x) to find the ending maxima & also by a decreasing function to find the starting maxima. Then merge both the locations and check the slope between the points if is less than some threshold values it is a plateau. Otherwise it could be a rising or falling signal. This will find the top plateaus. For finding the bottom plateaus, invert the signal and follow the same procedure.
This image shows the detected plateaus
This image shows the detection procedure
%%Plateau detection
%
% Detect plateau in the simulated signal using findpeak
x = 1:0.01:10;
freq = 4;
y = sawtooth(freq*x,0.5);
y(find(y>0.5)) =0.5;
y(find(y<-0.5)) =-0.5;
y = awgn(y,40); %add some gaussian noise
H = (x-x(1))./(x(end)-x(1)); % make a linear transformation
Hc = 1-H;
% convert them into different transformation for the signal
H = exp(4*H); % the extent upto which the signal is changing
Hc = exp(4*Hc);
Hy = H.*y; % apply the transform to find the peaks
Hcy = Hc.*y;
min_peak_dist = 80; % a value little less than the time period of the signal
[~,lcs_end] = findpeaks(Hy,'MinPeakDistance',min_peak_dist);
[~,lcs_start] = findpeaks(Hcy,'MinPeakDistance',min_peak_dist);
plot(x,y,'-',x(lcs_start),y(lcs_start),'*',x(lcs_end),y(lcs_end),'o');
clf;
plot(x,H,'--',x,Hc,'--',x,Hy,'-',x,Hcy,'-',x(lcs_start),Hcy(lcs_start),'*',x(lcs_end),Hy(lcs_end),'o')
0 comentarios
Greg Dionne
el 30 de En. de 2017
If you like FINDPEAKS' behavior, you can reverse your signal to get the other index.
iytemp = findpeaks(y(end:-1:1), ...)
iy = length(y) + 1 - iytemp(end:-1:1)
2 comentarios
Greg Dionne
el 27 de Feb. de 2017
Editada: Greg Dionne
el 27 de Feb. de 2017
Try something like this:
n = 2000;
x = sin(2*pi*10*(1:n)/n) + 0.5*sin(2*pi*5*(1:2000)/n) - linspace(0,3,2000);
x( x > 0) = 0;
plot(x);
[~,ifwd] = findpeaks(x);
[~,irev] = findpeaks(x(n:-1:1));
irev = n + 1 - irev(end:-1:1);
plot(1:n,x,'-', ...
ifwd,x(ifwd),'>', ...
irev,x(irev),'<');
legend('signal','leftside','rightside');
One caveat: FINDPEAKS does not consider endpoints to be peaks unless they are infinite.
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!