To obtain the cumulative signal power spectrum from the single-sided spectrum of a biomechanical signal to identify the frequency under which 99% of the signal power is
59 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
I am looking to select an appropriate cut-off frequency for a Butterworth filter applied to biomechanical data. I have read the process of performing a fast fourier transformation to take the signal from a time to frequency domain before then identifying the frequency under which 99% of the signal power is contained to quantify the cutoff frequency. Below is an image I have frequently seen to outline this process.
I have come across some resources to help with this process but it is a bit of a minefield when you are attempting to learn MATLAB at the same time as FFT. Has anyone got any advice or tips towards completing this in MATLAB? If I can plot the cumulative signal power % against the frequency then I can identify the appropriate cutoff frequency for a Butterworth filter as the frequency for which 99% of the signal power resides under.
Many thanks,
T
5 Commenti
Alexander
il 29 Mar 2023
If you are sampling at 1 kHz the input filter must be lower than 500 Hz cutoff frequency (theoretical) and 100-200 (engineering approach). Why don't you make a simple fft of your data? Mirrored frequencies should be clearly visible, especially if do an oversampling with (e.g.) 10 kHz. In the most cases (my experience, automotive) there were no filters necessary. What kind of excitation do you have?
Risposte (1)
Star Strider
il 29 Mar 2023
Modificato: Star Strider
il 29 Mar 2023
I cannot find a time vector or sampling frequency. I need at least one of those.
This should get you started —
M1 = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1339494/AEL_CMJ_1123.txt')
Fs = 1000; % Sampling Frequency (Default Value)
L = size(M1,1);
t = linspace(0, L-1, L).'/Fs; % Time Vector
figure
plot(t, M1)
grid
xlabel('Time (s)')
ylabel('$Amplitude (\frac{g\cdot cm}{s^2})$', 'Interpreter','latex')
legend('R','L', 'Location','best')
Fn = Fs/2;
NFFT = 2^nextpow2(L)
FTM1 = fft((M1-mean(M1)).*hann(L), NFFT)/L;
Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FTM1(Iv,:))*2)
grid
xlabel('Frequuency')
ylabel('Magnitude')
legend('R','L', 'Location','best')
xlim([0 0.2*Fs])
ctz = cumtrapz(Fv,(abs(FTM1(Iv,:))*2).^2);
figure
plot(Fv, ctz)
grid
xlabel('Frequuency')
ylabel('Cumulative Power')
legend('R','L', 'Location','best')
xlim([0 0.2*Fs])
ctzn = ctz./ctz(end,:);
cpnv = [0.9; 0.95; 0.99];
for k = 1:size(ctzn,2)
Fv_vals(:,k) = interp1(ctzn(:,k), Fv, cpnv);
end
% Fv_vals
figure
plot(Fv, ctzn)
grid
xlabel('Frequuency')
ylabel('Cumulative Power (Normalised)')
legend('R','L', 'Location','best')
xlim([0 0.2*Fs])
FrequencyLimits = table(cpnv*100,Fv_vals(:,1),Fv_vals(:,2), 'VariableNames',{'PowerVal (%)','Right (Hz)','Left (Hz)'})
EDIT — (29 Mar 2023 at 15:12)
Updated sampling frequency, re-ran code
.
3 Commenti
Star Strider
il 29 Mar 2023
My pleasure!
It does. I updated the sampling frequency and then re-ran my code.
I am still not exactly certain what you want to do. An acceptable baandpass frequency design would be:
Fz_Filt = lowpass(M1, mean(FrequencyLimits{end,[2 3]}), Fs, 'ImpulseResponse','iir');
And here that produces:
M1 = readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1339494/AEL_CMJ_1123.txt')
Fs = 1000; % Sampling Frequency (Default Value)
L = size(M1,1);
t = linspace(0, L-1, L).'/Fs; % Time Vector
figure
plot(t, M1)
grid
xlabel('Time (s)')
ylabel('Amplitude $(\frac{g\cdot cm}{s^2})$', 'Interpreter','latex')
legend('R','L', 'Location','best')
Fn = Fs/2;
NFFT = 2^nextpow2(L)
FTM1 = fft((M1-mean(M1)).*hann(L), NFFT)/L;
Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FTM1(Iv,:))*2)
grid
xlabel('Frequency')
ylabel('Magnitude')
legend('R','L', 'Location','best')
xlim([0 0.2*Fs])
ctz = cumtrapz(Fv,(abs(FTM1(Iv,:))*2).^2);
figure
plot(Fv, ctz)
grid
xlabel('Frequency')
ylabel('Cumulative Power')
legend('R','L', 'Location','best')
xlim([0 0.2*Fs])
ctzn = ctz./ctz(end,:);
cpnv = [0.9; 0.95; 0.99];
for k = 1:size(ctzn,2)
Fv_vals(:,k) = interp1(ctzn(:,k), Fv, cpnv);
end
% Fv_vals
figure
plot(Fv, ctzn)
grid
xlabel('Frequency')
ylabel('Cumulative Power (Normalised)')
legend('R','L', 'Location','best')
xlim([0 0.2*Fs])
FrequencyLimits = table(cpnv*100,Fv_vals(:,1),Fv_vals(:,2), 'VariableNames',{'PowerVal (%)','Right (Hz)','Left (Hz)'})
Fz_Filt = lowpass(M1, mean(FrequencyLimits{end,[2 3]}), Fs, 'ImpulseResponse','iir');
figure
plot(t, Fz_Filt)
grid
xlabel('Time (s)')
ylabel('Amplitude $(\frac{g\cdot cm}{s^2})$', 'Interpreter','latex')
legend('R','L', 'Location','best')
The filter doesn’t do much filtering because of the relatively high cutoff frequency. By design, it lets 99% of the signal power through.
.
Alexander
il 29 Mar 2023
I'm a little bit late(it took some time to analyse), and I think that the most things are mentioned in the answer above, I'll post it anyway so the work was not for nothing.
My short analyse of your data, w/o nowing your test setup, test and equipment. I assume the dimension of your data is N. It seems there is a base load of about 400 N. After 3 s the load decreaes to 800N and then something brakes(?). After that a very fast drop to (low) negative forces, as something is pulling at the force transducer. This remains for half a second and then raising again very quickly. Sometimes FzL and FzR are showing a diametral behavior (good seen after 5s). Wobbling platform?
My steps:
1. Fz I set to (FzR+FzL)/2. I think a simple sum makes no sense, but that is your decision. I'm now focused on FZ.
2. Looking at the time data in figure(1) what I have assumed above.
3. In figure(2) (below) you can see the pure fft of Fz (not much).
4. In figure(3) I removed the mean of Fz to make the interesting part more visible. The mean is allways around the frequency of 0Hz and scales the y-axis.
Some remarks to "my" fft I used. I don't like normalized data and also a amplitude density in 1/Hz is not very interpretable on the first view. In the plots attached you see frequency in Hz and the amplitudes not amplitudes/Hz. This helps to get a quick first view, but you can't use this for a ifft. I will attach the data so you can make your plots yourselfe as you like.
IMHO, you don't need a filter. Of cause this depends on the noise and frequencies you want to accept. You will find in the plots and data, above 250Hz that more or less nothing happens.
If you want to have a filter anyway, you can use a butterworth whith 100Hz cutoff frequency and order of 2 (sample frequency 1 kHz) with the coefficients:
B =
0.0675 0.1349 0.0675
A =
1.0000 -1.1430 0.4128
Frequency response and phase in figure(4).
If you have any questions or you find a mistake: please report.
Vedere anche
Categorie
Scopri di più su Digital Filter Analysis in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!