How to find the corner points at a plateau

조회 수: 35 (최근 30일)
Armindo
Armindo 2017년 1월 26일
편집: Ajinkya Gorad 2017년 6월 14일
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?

답변 (3개)

John D'Errico
John D'Errico 2017년 2월 27일
편집: John D'Errico 2017년 2월 28일
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
Greg Dionne
Greg Dionne 2017년 2월 28일
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
Ajinkya Gorad 2017년 6월 14일
편집: Ajinkya Gorad 2017년 6월 14일
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')

Greg Dionne
Greg Dionne 2017년 1월 30일
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
Armindo
Armindo 2017년 2월 8일
편집: Armindo 2017년 2월 8일
thak you but this dont seems to work. I get the same index for all the data. This seems to work but not all the corners are well detected. Any other aproch that I can use? yy = flipud(y); indexes = findpeaks(yy,...);
Greg Dionne
Greg Dionne 2017년 2월 27일
편집: Greg Dionne 2017년 2월 27일
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.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Correlation and Convolution에 대해 자세히 알아보기

태그

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by