Determining optimal cut off frequency

114 views (last 30 days)
Katie
Katie on 2 Aug 2024
Commented: Star Strider on 23 Sep 2024
Hello,
I have some motion capture data that I need to filter before differentiating to get velocity and acceleration. I have been told to filter at a range of frequencies and then calculate the RMSD between the original and filtered data. I want to used a forth order low pass butterworth filter. I have managed to do so but do not understand how I then interpret the plot to decide on my optimal filtering frequency. I have seen some previous posts mention 'fft' but do not understand what this does and if I should be using it.
This is my function:
function plot_rmsd_vs_cutoff(data, fs, f_min, f_max, num_points)
% Plot RMSD against cut-off frequency for given data
% Data and sampling frequency
% data: input data
% fs: sampling frequency
% Frequency range
% f_min: minimum cut-off frequency
% f_max: maximum cut-off frequency
% num_points: number of points in the frequency range
% Create a vector of cut-off frequencies
cutoff_freqs = linspace(f_min, f_max, num_points);
% Initialize RMSD vector
rmsd_values = zeros(size(cutoff_freqs));
for i = 1:length(cutoff_freqs)
% Filter data
[b, a] = butter(4, cutoff_freqs(i)/(fs/2), 'low'); % Example: 4th order lowpass Butterworth
filtered_data = filtfilt(b, a, data);
% Calculate RMSD
rmsd_values(i) = rms(data - filtered_data);
end
% Plot RMSD against cut-off frequency
plot(cutoff_freqs, rmsd_values);
xlabel('Cut-off Frequency (Hz)');
ylabel('RMSD');
title('RMSD vs Cut-off Frequency');
end
This is how I have used it in my code:
% Call the function
plot_rmsd_vs_cutoff(data, fs, 1, 50, 50);
I have attached my data and the output I have got.
Many thanks for any help.
  16 Comments
Star Strider
Star Strider on 20 Sep 2024
I wrote the ‘FFT1’ function for my own use, so that I didn’t have to type all that whenever I wanted to calculate a Fourier transform.
It is at the end of my posted code, and reproduced here:
function [FTs1,Fv] = FFT1(s,t)
% Arguments:
% s: Signal Vector Or Matrix
% t: Associated Time Vector
t = t(:);
L = numel(t);
if size(s,2) == L
s = s.';
end
Fs = 1/mean(diff(t));
Fn = Fs/2;
NFFT = 2^nextpow2(L);
FTs = fft((s - mean(s)) .* hann(L).*ones(1,size(s,2)), NFFT)/sum(hann(L));
Fv = Fs*(0:(NFFT/2))/NFFT;
% Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
FTs1 = FTs(Iv,:);
end
.
Umar
Umar on 21 Sep 2024
Hi @Katie,
I do apologize for the late reply since busy working with clients.
You mentioned, “ is 'Fourier Transform[FTX1, Fv] = FFT1(X, t);' an inbuilt function or one I need to create? As I am getting an error that it is not recorgnised.”
Please see my response to your comments below.
Copy the entire FFT1 function code below provided by @Star Strider and save it as FFT1.m in your current working directory or in any directory that is included in MATLAB's path. Also, he has tweaked his code to help you out further. If you need any further assistance from us, please let us know, we are here to help you out.

Sign in to comment.

Answers (1)

Star Strider
Star Strider on 3 Aug 2024
I have been told to filter at a range of frequencies and then calculate the RMSD between the original and filtered data.
I do not understand what that is supposed to accomplish!
Ideally, there should be a time vector with this as well. I could then determine if the sampling time intervals are constant, and correct them otherwise using the resample funciton.
Assuming they are constant and with a sampling requency of 100 Hz, this is how I would process them.
First, decide whether you want to eliminate the baseline drift, or retain the baseline drift and eliminate the high-frequency part of the signal, then filter, using either the lowpass or bandpass functions to design efficient elliptic filters —
T1 = readtable('X.xlsx')
T1 = 6000x1 table
X ______ 1.0141 1.0142 1.0145 1.0137 1.0139 1.0139 1.0142 1.0143 1.0144 1.0145 1.0147 1.0147 1.0148 1.0148 1.0147 1.0148
X = T1.X;
L = numel(X);
Fs = 100;
t = linspace(0, L-1, L).'/Fs;
figure
plot(t, X)
grid
xlabel('Time (s)')
ylabel('Amplitude (Units)')
title('Original Signal')
[FTX1,Fv] = FFT1(X,t);
[pks, locsidx] = findpeaks(abs(FTX1)*2, 'MinPeakProminence',0.01);
figure
plot(Fv, abs(FTX1)*2)
hold on
plot(Fv(locsidx), pks, 'vr')
hold off
grid
xlabel('Frequency (Hz)')
ylabel('Magnitude (Units)')
title('Fourier Transform: ‘X’')
xlim([0 1.5])
text(Fv(locsidx), pks, compose('\\leftarrow Frequency = %.3f Hz\n Magnitude = %.3f', [Fv(locsidx).' pks]), 'Vert','top')
xline(Fv(locsidx(1))+0.1, '--r', 'Low-Frequency Cutoff')
xline(Fv(locsidx(2))+[-1 1]*0.1, '--m', 'Bandpass-Frequency Cutoff')
XLP_filt = lowpass(X, Fv(locsidx(1))+0.1, Fs, 'ImpulseResponse','iir'); % Remove High-Frequency Oscillations
XBP_filt = bandpass(X, Fv(locsidx(2))+[-1 1]*0.1, Fs, 'ImpulseResponse','iir'); % Remove Baseline Variation
figure
plot(t, XLP_filt)
grid
xlabel('Time (s)')
ylabel('Amplitude (Units)')
title('Baseline Variation')
[env1,env2] = envelope(XBP_filt, 5, 'peak');
figure
hp1 = plot(t, XBP_filt, 'DisplayName','Data');
hold on
hp2 =plot(t, [env1 env2], '--r', 'DisplayName','Amplitude Envelope');
hold off
grid
ylim([min(ylim) max(ylim)+0.005])
xlabel('Time (s)')
ylabel('Amplitude (Units)')
title('High-Frequency Oscillation')
legend([hp1, hp2(1)], 'Location','best')
function [FTs1,Fv] = FFT1(s,t)
% Arguments:
% s: Signal Vector Or Matrix
% t: Associated Time Vector
t = t(:);
L = numel(t);
if size(s,2) == L
s = s.';
end
Fs = 1/mean(diff(t));
Fn = Fs/2;
NFFT = 2^nextpow2(L);
FTs = fft((s - mean(s)) .* hann(L).*ones(1,size(s,2)), NFFT)/sum(hann(L));
Fv = Fs*(0:(NFFT/2))/NFFT;
% Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
FTs1 = FTs(Iv,:);
end
Do you want one of tthese results, or something entirely different?
There is nothing inherently wrong with using a Butterworth filter, however the elliptic filters designed by these functions are just easier to code and are computationally more efficient.
.
  6 Comments
Star Strider
Star Strider on 23 Sep 2024
My pleasure!
Does it do what you want it to do? I’m still not certain what that is.

Sign in to comment.

Categories

Find more on Predictive Maintenance Toolbox in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!