Band-pass filter extraction.
Afficher commentaires plus anciens
Dear all, How are you?
Currently, I’m dealing with a band-pass filter that extracts a specific frequency band from a synthetic time series. Unfortunately, my band-pass filter is not extracting the original series as the following code shows. I would appreciate any suggestions on how to make the filter process more effective.
clear all,close all;
Inertial_period = 20.215;
K1_period = 24; % K1 period (hours)
M2_period = 12;
Inertial_amplitude = 1.0;
K1_amplitude = 0.3;
M2_amplitude = 0.5;
Inertial_phase = 0; % Example phase (radians)
K1_phase = pi/4;
M2_phase = pi/2;
% Time Vector (1 Month)
Fs = 1; % Sampling frequency (1 sample per hour)
duration_hours = 510; % 510 Hours
t = 0:1/Fs:duration_hours;
% Generate Components
I = Inertial_amplitude * cos(2*pi*t/Inertial_period + M2_phase);
K1 = K1_amplitude * cos(2*pi*t/K1_period + K1_phase);
M2 = M2_amplitude * cos(2*pi*t/M2_period + M2_phase);
u = K1+M2+I; %Time Serie
clearvars -except u I;

Now, I built a band-pass filter to extract the original signal "I" from the time series 'u'.
Fs = 1; % 1 sample per hour
In = 20.215;
low_cutoff = 1/(In+1); % I + 1hour
high_cutoff = 1/(In-1); % I - 1Hour
% Normalize the cutoff frequencies by the Nyquist frequency (Fs/2)
Wn = [low_cutoff, high_cutoff] / (Fs/2);
% Design the Butterworth bandpass filter
[b, a] = butter(2, Wn, 'bandpass');
clear Fs low_cutoff_I high_cutoff_I Wn_I
fu = filtfilt(b,a,u);


Clearly, the band-pass filter with a central frequency +/- 1 hour is more accurate than the same band-pass filter with +/- 0.2 hours, but it is not identical to the original signal (orange). Is there any way I can better extract the frequency so the filtered signal will be almost identical to the original? Thanks to all; I would appreciate any suggestions.
1 commentaire
The filter removes signal energy from the original signal. That the amplitude of the filtered signal is less than the amplitude of the original signal is to be expected. The design frequency of the filter passband appears to be about 49.5.
Fs = 1; % 1 sample per hour
In = 20.215;
low_cutoff = 1/(In+1); % I + 1hour
high_cutoff = 1/(In-1); % I - 1Hour
% Normalize the cutoff frequencies by the Nyquist frequency (Fs/2)
Wn = [low_cutoff, high_cutoff] / (Fs/2);
% Design the Butterworth bandpass filter
[b, a] = butter(2, Wn, 'bandpass');
% clear Fs low_cutoff_I high_cutoff_I Wn_I
[h,fv] = freqz(b,a,2^16,Fs);
[Hmax,idx] = findpeaks(abs(h));
FreqMaxMag = fv(idx)/max(fv)*500
figure
freqz(b,a,2^16,Fs);
xline(subplot(2,1,1),fv(idx)/max(fv)*500)
xline(subplot(2,1,2),fv(idx)/max(fv)*500)
set(subplot(2,1,1), 'XGrid','on', 'YGrid','on')
set(subplot(2,1,2), 'XGrid','on', 'YGrid','on')
.
Réponse acceptée
Plus de réponses (1)
Hi Claudio,
Start with the original code
Inertial_period = 20.215;
K1_period = 24; % K1 period (hours)
M2_period = 12;
Inertial_amplitude = 1.0;
K1_amplitude = 0.3;
M2_amplitude = 0.5;
Inertial_phase = 0; % Example phase (radians)
K1_phase = pi/4;
M2_phase = pi/2;
% Time Vector (1 Month)
Fs = 1; % Sampling frequency (1 sample per hour)
duration_hours = 510; % 510 Hours
t = 0:1/Fs:duration_hours;
% Generate Components
I = Inertial_amplitude * cos(2*pi*t/Inertial_period + M2_phase);
K1 = K1_amplitude * cos(2*pi*t/K1_period + K1_phase);
M2 = M2_amplitude * cos(2*pi*t/M2_period + M2_phase);
u = K1+M2+I; %Time Serie
%clearvars -except u I;
%Now, I built a band-pass filter to extract the original signal "I" from the time series 'u'.
Fs = 1; % 1 sample per hour
In = 20.215;
low_cutoff = 1/(In+1); % I + 1hour
high_cutoff = 1/(In-1); % I - 1Hour
% Normalize the cutoff frequencies by the Nyquist frequency (Fs/2)
Wn = [low_cutoff, high_cutoff] / (Fs/2);
% Design the Butterworth bandpass filter
[b, a] = butter(2, Wn, 'bandpass');
%clear Fs low_cutoff_I high_cutoff_I Wn_I
At this point, it's probably easier to see what's going on if we apply the fitler to I instead of u. Let's filter forward only
fu = filter(b,a,I);
figure
plot(t,I,t,fu)
The bandpass effect of the filter is a steady-state concept. But, as we can see from the plot, the filter has a transient response of roughly 200 seconds before the output reaches steady state.
Now, when we use filtfilt to do forward/backard filtering, we're kind of, sort of, essentially, approximately also applying the filter to the red curve above, but starting from the right and going to the left. So we'd expect that same 200 second transient, but going from right to left,
fu = filtfilt(b,a,I);
figure
plot(t,I,t,fu)
which is basically what happens. There's a very small window where the response has reached steady state going in both directions.
So I believe the effect you're observing is due to the slow transient reponse of the filter relative to the time span of the data. Let's try with more data.
t = 0:1/Fs:3*duration_hours;
% Generate Components
I = Inertial_amplitude * cos(2*pi*t/Inertial_period + M2_phase);
figure
plot(t,I,t,filtfilt(b,a,I))
The effect of the transient response is still there, of course, but now the red curve looks more like what's probably expected.
If more data can't be used, then I guess one could try to design a bandpass filter with a much faster transient response.
Catégories
En savoir plus sur Analog Filters dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!




