How to find a specific number of peaks and exclude specific ones

6 views (last 30 days)
Hello,
I have data from an experiment I dervied the FFT of and I need to find certain Peaks in the frequency domain.
For that I use the findpeaks function with MinPeakProminence and MinPeakDistance to avoid getting peaks caused by noise.
First,I need to exclude all the peaks at a certain frequency and it's first 6 multiples, because they're uninteresting to me and I do this by calculating them and excluding peaks in a small range around those frequencies from the peaks I find using findpeaks.
Relevant Parts of my Code:
%% FFT of filtered Data
F = F_s*(0:(Ln/2))/Ln;
Y.kraft_x = fft(Fx_filt);
P2.kraft_x = abs(Y.kraft_x/Ln);
P1.kraft_x = P2.kraft_x(1:Ln/2+1);
P1.kraft_x(2:end-1) = 2*P1.kraft_x(2:end-1);
%% find peaks
for i = 1:6
F_t(i) = Parameter(v_nr,2)*i*(1/60); % [Hz] Engagement frequencies
end
[pk,pkf] = findpeaks(P1.kraft_x,F,'MinPeakProminence',0.25,'MinPeakDistance',10);
tol = 50; % tolerance around engagement frequency and its multiples
log_ind_1 = pkf < F_t(1)-tol | pkf > F_t(1)+tol & pkf < F_t(2)-tol | pkf > F_t(2)+tol & pkf < F_t(3)-tol | pkf > F_t(3)+tol & pkf < F_t(4)-tol | pkf > F_t(4)+tol & pkf < F_t(5)-tol | pkf > F_t(5)+tol & pkf < F_t(6)-tol | pkf > F_t(6)+tol;
pkf = pkf(log_ind_1);
pk = pk(log_ind_1);
Now I'm presented with following Problem:
In total there are 80 experiments with different parameters which causes different amounts of peaks and differently prominent peaks.
I'd like to set up my findpeak function (probably with the optimization Toolbox) in a way, that it returns a sepcific amount of peaks dependend on the Parameters of MinPeakProminence and MinPeakDistance
For example setting the output amount to 11 so I get my known peaks at those 6 Frequencies, plus the most prominent 5 peaks I'm looking for.
I tried to use the optimization App but I have trouble setting it up.
Additionally I'd like to ask if somebody knows a way to set this up:
log_ind_1 = pkf < F_t(1)-tol | pkf > F_t(1)+tol & pkf < F_t(2)-tol | pkf > F_t(2)+tol & pkf < F_t(3)-tol | pkf > F_t(3)+tol & pkf < F_t(4)-tol | pkf > F_t(4)+tol & pkf < F_t(5)-tol | pkf > F_t(5)+tol & pkf < F_t(6)-tol | pkf > F_t(6)+tol;
more "elegantly" by using a loop.
Thank you for reading
  3 Comments
Edward Schreiner
Edward Schreiner on 13 Apr 2020
It excludes the peak frequencies which are irrelevant for me as I explained. For example my engagement Frequency is 500Hz so it excludes 500 and its first 6 multiples (500,1000,1500,...) because I get guaranteed peaks at those points. Additionially I does this within a small range which is
tol = 50;
(I normally set it lower around 5-10) in this case.
So:
log_ind_1 = pkf < F_t(1)-tol | pkf > F_t(1)+tol ..
is the first frequency excluded and:
.. & pkf < F_t(2)-tol | pkf > F_t(2)+tol
the second and so on.
It returns a vector of ones and zeros
darova
darova on 13 Apr 2020
You can replace it using for loop
log_ind = logical(pkf*0);
for x = 500*(1:6)
log_ind = log_ind | (abs(x-pkf) < 50);
end

Sign in to comment.

Answers (0)

Community Treasure Hunt

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

Start Hunting!