Find peaks from noisy data

105 views (last 30 days)
photoon
photoon on 15 Feb 2021
Edited: photoon on 25 Aug 2021
I am trying to find the method of locating the gaussian peaks.
I used findpeaks function to find peaks. The solid line is created by sgolayfilt.
hgcs = sgolayfilt(hgc, 10, 41);
findpeaks(hgc, 'MinPeakDistance', 20)
Question1: Are there any functions or algorithms that can determine the number of peaks and the locations?
Question2: After 160, there are small features. Some of them may be still peaks following the first four peaks. At least, we know that the locations of peaks are quasi-periodic. Could we also find more peaks?

Accepted Answer

Star Strider
Star Strider on 16 Feb 2021
I gave up on estimating the width parameter, and just went for the amplitude and location with a uniform width.
Try this:
D = load('hgc.mat');
hgc = D.hgc;
x = linspace(0, numel(hgc), numel(hgc));
hgcs = sgolayfilt(hgc, 10, 41);
figure
plot(x,hgc)
hold on
plot(x,hgcs)
hold off
grid
[pks,locs,w] = findpeaks(hgc, 'MinPeakDistance', 20, 'MinPeakProminence',5);
gausfcn = @(b,x) b(1).*exp(-(x-b(2)).^2 * 0.05);
for k = 1:numel(locs)
B(:,k) = lsqcurvefit(gausfcn, [pks(k); x(locs(k))], x, hgcs);
end
figure
plot(x,hgc)
hold on
for k = 1:numel(locs)
plot(x, gausfcn(B(:,k),x), 'LineWidth',2)
end
hold off
grid
.
  8 Comments
photoon
photoon on 17 Feb 2021
Edited: photoon on 25 Aug 2021
For the fitting, this was closer to what I was thinking about.
nl = numel(locs);
gnl = strcat('gauss', num2str(nl));
gaoptions = fitoptions(gnl);
gaoptions.Upper = [];
Thanks,
Star Strider
Star Strider on 17 Feb 2021
I don’t have the Curve Fitting Toolbox (I don’t need it for what I do), so I can’t run that code snippet, and I can’t help you with it. (However I essentially understand what it’s doing.)
The only other suggestion I have with respect to identifying the peaks is to detrend the filtered signal. That would perform an additional sort of highpass filtering on the filtered signal, eliminating the baseline variations, and could make it easier to isolate the peaks you want.

Sign in to comment.

More Answers (1)

Image Analyst
Image Analyst on 16 Feb 2021
I'm attaching a demo where you can specify how many Gaussians are in your signal and it will find them. If you don't know how many there are then you can maybe specify more and take the 4 with the largest area under the curve. Adap the demo to use 4 instead of 6, and to read in your actual data instead of using made up data.
  5 Comments
Image Analyst
Image Analyst on 17 Feb 2021
If using a linear filter like movmean() or fft() followed by a low pass filter, works better than a non-linear filter like sgolayfilt() that's fine (though I'm surprised).
But you still need to find the locations, regardless of what method you use to smooth the signal. So you can either use findpeaks(), or my Gaussian fitting code. findpeaks() will give you every peak and you don't need to know how many there are in advance, while the Guassian fitting code requires you to specify how many Gaussians your signal should be fit to.
photoon
photoon on 17 Feb 2021
findpeaks() is what I am using. However, I have to change parameters for each data set in order to choose the peaks of interest. Are there better ways of making this autonomous?

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!