0

I want to filter a really noisy signal,so to obtain the number of peaks that cross a certain threshold. This is the matlab code I used:

thresh = 3;  % Specify threshold
x = VarName1; 
% Essentially need to pick out values which exceed threshold with the condition that the previous value  
% needs to be below the threshold
idxl = x>=thresh;
idxl(1) = 0;
idx = find(idxl);
yest = x(idx-1)<thresh; 
idx(yest)  % Final output

But the value that I get is too high, and in fact when I locate in the plot the peak it identifies also the neighboring values that cross the threshold as you can see in the picture attached. But I want to count one spike for each time it crossed the threshold. Do you have any idea how can I do that? image_matlab

Simon
  • 75
  • 5

2 Answers2

1

Say you have the indexes of the peaks, then in order to count them, you will have to segment them. This is done most easily by taking the difference between the indexes and then apply some threshold, of the minimum distance between each peak.

peaks = unique([randi([100,110],1,randi(10)),randi([150,160],1,randi(10)),randi([210,220],1,randi(10))]); %Create some peaks
thresh = 20; %Set a threshold
nextPeak = diff([-inf,peaks])>thresh; % Find peak seperators

If you are interested in the number of peaks, you can just count the number of seperators, e.g.

NumPeaks = sum(nextPeak);

If you are interested in the location of the peaks, you will have to decide upon, how to define "the" peak, is it the centre point of the peak or the maximum value, e.t.c.?

In all cases, you will have to run through the number of peaks

nextPeakIdx = [find(nextPeak),length(peaks)+1];
for i = 1:length(nextPeakIdx)-1
    peakIdx = peaks(nextPeakIdx(i):(nextPeakIdx(i+1)-1));
    %Decide which index to keep
end
Nicky Mattsson
  • 3,052
  • 12
  • 28
1

Matlab has a findpeaks() function that should work in your case. In particular, you can set the MinPeakDistance parameter to a smart amount to only detect the peaks you want.

% Build some noisy signal
signal = peaks;  
signal = repmat(signal(18,:) , 1,3);
noisy_signal = signal + randn(1,3*49).*0.5;

% Find peaks and plot them
findpeaks(noisy_signal , 'MinPeakDistance' , 15);
hold on;
plot(signal)

Here is what I get, with the yellow line being the original signal, the blue is the noisy signal and the arrows point to the detected peaks (in the noisy signal of course). You just have to adapt your MinPeakDistance parameter.

enter image description here

Zep
  • 1,541
  • 13
  • 21
  • Thanks for the answer, do you know if there is a way to set a threshold as well? For example if I want to just extract the peak greater then 2 units? – Simon May 10 '18 at 05:32
  • `findpeaks` is a nice function, but especially in this case, where OP's tops have been cut off, it suffers quite a lot of being a black-box function. Try to adapt your data to `noisy_signal(noisy_signal>2)=2+0.001*randn(1,3*49);`, then the peaks are not really well-defined. – Nicky Mattsson May 10 '18 at 07:16