Find all global minima und maxima of an Graph
22 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Benedikt Friedrich Nowak
le 10 Nov 2022
Commenté : Star Strider
le 13 Nov 2022
Hi there,
i would like to find all global minima and maxima (red circles) of an graph. The graph itself was created with two vectors: Vektor 1 = Force in Newton [11902x2] and Vektor two = Time in seconds [11902x1]. So every Force-value has its own timestamp.
The Problem is that when i use the command 'findpeaks' it doesnt find the four global maxima and the three global minima (red circles), but it result in many small local peaks. The graph itself isnt so smooth after all and 'trembles` if you zoom in on it.
Does anyone know how to programm a code in which i can filter for those global peaks only ?
Thank you for your time and effort, Ben !
0 commentaires
Réponse acceptée
Star Strider
le 10 Nov 2022
The findpeaks function has a number of name-value pair arguments that you can use to restrict what it returns. (My favourite is 'MinPeakProminence' and doing some experimenting will return the correct result.)
t = linspace(0, 10);
s = sin(2*pi*t*0.5) + randn(size(t))*0.25;
[pks,plocs] = findpeaks(s, 'MinPeakProminence',0.75)
[vys,vlocs] = findpeaks(-s, 'MinPeakProminence',0.75)
figure
plot(t,s, 'DisplayName','Signal')
hold on
plot(t(plocs), pks, '^r', 'DisplayName','Peaks')
plot(t(vlocs), -vys, 'vr', 'DisplayName','Valleys')
hold off
legend('Location','best')
.
2 commentaires
Plus de réponses (2)
Mathieu NOE
le 10 Nov 2022
hello Benedikt
someone will probably tell you how findpeaks is powerfull but sometimes I simply prefer to rely on old but good / simple code like peakseek - even not bothered by the small amount of noise I added to the waveform.
a big thanks to Peter O'Connor, the author of peakseek
results :
%% dummy data
n = 1000;
x = 25*(0:n-1)/n;
y = sign(sin(x+0.05*x.^2)).*(1-0.01*x);
% low pass 1st order
% y = (1-alpha) * y_old + alpha * x
alpha = 0.02;
numd = [alpha 0];
dend = [1 -(1-alpha)];
yf = filter(numd,dend,y);
%% add some noise
yf = yf + 0.02*randn(size(yf));
%% try#1 with findpeaks
figure(1)
plot(x,yf);
findpeaks(yf)
%% try#2 with peakseek
minpeakdist = 50; % in samples
% positive peaks
minpeakh = max(yf)/10;
[locs1, pks1]=peakseek(yf,minpeakdist,minpeakh);
% negative peaks
[locs2, pks2]=peakseek(-yf,minpeakdist,minpeakh);
figure(2)
plot(x,yf,'b',x(locs1),yf(locs1),'dr',x(locs2),yf(locs2),'dg');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [locs, pks]=peakseek(x,minpeakdist,minpeakh)
% x is a vector input (generally a timecourse)
% minpeakdist is the minimum desired distance between peaks (optional, defaults to 1)
% minpeakh is the minimum height of a peak (optional)
%
% (c) 2010
% Peter O'Connor
% peter<dot>ed<dot>oconnor .AT. gmail<dot>com
if size(x,2)==1, x=x'; end
% Find all maxima and ties
locs=find(x(2:end-1)>=x(1:end-2) & x(2:end-1)>=x(3:end))+1;
if nargin<2, minpeakdist=1; end % If no minpeakdist specified, default to 1.
if nargin>2 % If there's a minpeakheight
locs(x(locs)<=minpeakh)=[];
end
if minpeakdist>1
while 1
del=diff(locs)<minpeakdist;
if ~any(del), break; end
pks=x(locs);
[garb, mins]=min([pks(del) ; pks([false del])]); %#ok<ASGLU>
deln=find(del);
deln=[deln(mins==1) deln(mins==2)+1];
locs(deln)=[];
end
end
if nargout>1
pks=x(locs);
end
end
0 commentaires
John D'Errico
le 10 Nov 2022
A peak is a peak. If your data has many peaks in it, can findpeaks really know that? At the same time, findpeaks is the correct tool to use. You just need to smooth out the noise, FIRST. So that means you need to use a tool that can smooth your curve in advance. smooth is a good choice, because it has multiple methods to perform the smoothing, and you can make the choice yourself.
help smooth
Which method is correct for you? The best thing is to try out a few, and see which one makes you happy. Really, it will not be the specific methoid you choose, but how wide you make the window or span of that method. And that is dependent on how much noise is in your data. So noiser data will require a longer span to help to smooth out the noise and thus to elmininate the spurious bumps and crap. Of course, if you make the span too large, then your peaks will become brodened out more than you want. So this will be a tradeoff, and we don't actually have your data to give an example specific to your problem. In turn, all that allows me to do is suggest you smooth your data using perhaps smooth.
Other methods like a spline fit are less likely to be good choices, because your curve seems to have sharp transitions in slope at the peaks. And spline hate singularities, even singularities in the derivative. That means you want to use a simpler low order method, like the ones you will find in smooth.
So just smooth your data, THEN call findpeaks. If you are finding too many spurious peaks, then you needed to smooth your data a little more strongly.
0 commentaires
Voir également
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!