Find all global minima und maxima of an Graph
16 views (last 30 days)
Benedikt Friedrich Nowak on 10 Nov 2022
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 !
Star Strider on 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)
plot(t(plocs), pks, '^r', 'DisplayName','Peaks')
plot(t(vlocs), -vys, 'vr', 'DisplayName','Valleys')
More Answers (2)
Mathieu NOE on 10 Nov 2022
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
%% 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
%% try#2 with peakseek
minpeakdist = 50; % in samples
% positive peaks
minpeakh = max(yf)/10;
% negative peaks
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
if ~any(del), break; end
[garb, mins]=min([pks(del) ; pks([false del])]); %#ok<ASGLU>
John D'Errico on 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.
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.