RoG
RoG

Reputation: 849

Using Matlab digitalfilter object from lowpass() in filter()

I need to perform a lowpass filtering operation many times (same cutoff frequency and sampling frequency each time).

It seems that lowpass() is a slow operation and I can speed it up if I reuse the filter object that is created. The help for lowpass() says that:

[Y,D] = lowpass(...) returns the digital filter, D, used to filter the signal. [...] Call filter(D,X) to filter data.

However when I try to use the filter object in this way I get different results to what lowpass() returns. I expect lp1 and lp2 to be identical in this example:

% Test input data
x = rand([200,1]);
% Lowpass filter, and save the filter object to df:
[lp1, df] = lowpass(x,50,1000);
% Reuse the filter object:
lp2 = filter(df, x);

% Plot to show that they are clearly different results
figure;plot(lp1);hold on;plot(lp2);

I have also tried using filtfilt() but this does not produce an identical result.

Upvotes: 0

Views: 289

Answers (1)

Harald Hentschke
Harald Hentschke

Reputation: 26

Quick trick to reuse filter object df if you want the same output as from lowpass IN THIS SPECIFIC SCENARIO and if time's not on your side: lp3 = conv(x, df.Coefficients, 'same');

Explanation: the filter you designed using lowpass.m is a finite impulse response filter (FIR) which shifts phases. Look again at the two curves in the figure your code snippet produces and you'll realize that the curve produced by filter.m is essentially a right-shifted version of the version produced by lowpass.m. You could try to correct for that, see https://de.mathworks.com/help/signal/ug/compensate-for-the-delay-introduced-by-an-fir-filter.html. The surprising part, though, is that lowpass.m corrects for the delay automatically, which a cursory reading of the docs didn't reveal.

filtfilt.m performs filtering twice, once in the forward direction, then in the reverse, and additionally '...minimizes start-up and ending transients...'. Because this to and fro filtering essentially cancels the delays but also filters harder, the results will by definition be different from those of either lowpass.m and filter.m.

In the long term, you will be best off investing some time into designing your filters from the bottom up (the Matlab docs are excellent in this regard), not using relatively new convenience wrapper functions like lowpass which seemingly do things unasked for in the background.

% Test input data
x = rand([200,1]);
t = 1:200;
% Lowpass filter, and save the filter object to df:
[lp1, df] = lowpass(x,50,1000);
% Reuse the filter object:
lp2 = filter(df, x);
% Convolution of time series with filter coefficients
lp3 = conv(x, df.Coefficients, 'same');

% Plot 
figure(1), clf;
subplot(2,1,1)
% Plot lp3 with a tiny offset so we can discern it from lp1
plot(t, lp1, t, lp2, t, lp3+0.01)
legend('lowpass.m','filter.m','convolution')

% Use filtfilt to obtain zero-lag, doubly filtered version (for comparison)
lp4 = filtfilt(df, x);
subplot(2,1,2)
plot(t, lp1, t, lp4)
legend('lowpass.m','filtfilt.m')

Upvotes: 1

Related Questions