# Problem finding "valleys" in signal

15 views (last 30 days)
Kcire L on 18 May 2023
Answered: Star Strider on 18 May 2023
Hello,
I am using the findpeaks function to find the valleys in a signal, but it is not consistent and was wondering if there was a better way of doing this.
My code is below along with an image of a "missed" valley around the 8 second mark. Any help on this would be greatly appreciated.
[yfft_, freqvec_, yfft_dB_, freq_res] = calcFFT(temp_snip, 'hamming', Fs*100, Fs);
[fft_pks fft_locs] = findpeaks(yfft_, 'MinPeakHeight', 0.004);
BreathrateHz = freqvec_(fft_locs(2));
RespRate = (BreathrateHz * snippp)/2
%Get valleys
inverted_snip = max(temp_snip) - temp_snip;
snip_lo = max(inverted_snip);
[v1, vv] = findpeaks(inverted_snip, "MinPeakDistance", Fs*((RespRate)/2), "MinPeakHeight", snip_lo *.85); %-(Fs*BreathInstance_error))/5);

Steven Lord on 18 May 2023
Have you tried using islocalmin on your original data rather than findpeaks on the "flipped" data?

Image Analyst on 18 May 2023
Is it possible your MinPeakDistance is too large?
You could also try to smooth your data with movmean or sgolayfilt before using findpeaks
help sgolayfilt
SGOLAYFILT Savitzky-Golay Filtering. SGOLAYFILT(X,ORDER,FRAMELEN) smooths the signal X using a Savitzky-Golay (polynomial) smoothing filter. The polynomial order, ORDER, must be less than the frame length, FRAMELEN, and FRAMELEN must be odd. The length of the input X must be >= FRAMELEN. If X is a matrix, the filtering is done on the columns of X. Note that if the polynomial order ORDER equals FRAMELEN-1, no smoothing will occur. SGOLAYFILT(X,ORDER,FRAMELEN,WEIGHTS) specifies a weighting vector WEIGHTS with length FRAMELEN containing real, positive valued weights employed during the least-squares minimization. If not specified, or if specified as empty, WEIGHTS defaults to an identity matrix. SGOLAYFILT(X,ORDER,FRAMELEN,[],DIM) and SGOLAYFILT(X,ORDER,FRAMELEN,WEIGHTS,DIM) operate along the dimension DIM. % Example: % Smooth the mtlb signal by applying a cubic Savitzky-Golay filter % to data frames of length 41. load mtlb % Load data smtlb = sgolayfilt(mtlb,3,41); % Apply 3rd-order filter plot([mtlb smtlb]); legend('Original Data','Filtered Data'); See also SGOLAY, MEDFILT1, FILTER Documentation for sgolayfilt doc sgolayfilt

Star Strider on 18 May 2023
I prefer using 'MinPeakProminence' instead of 'MinPeakHeight' since that is usually more robust.
t = linspace(0, 10);
y = 0.03*sin(2*pi*t*0.7) + 0.06 + randn(size(t))/100;
[pks,locs] = findpeaks(-y, 'MinPeakDistance', 10, 'MinPeakProminence',0.025);
figure
plot(t, y)
hold on
plot(t(locs), -pks, 'xr')
hold off
Adjust the 'MinPeakProminence' value to get the desired result with your data.
.