Filtfilt returns NaN matrix

조회 수: 2 (최근 30일)
Aboltabol
Aboltabol 2023년 5월 10일
댓글: Star Strider 2023년 5월 11일
I am running the following operation (please download the attached file to your working directory):
load('Channel_Sim.mat');
[b,a] = butter(4, [3 20] ./ (1000/2)); % Sampling frequency is 1000 Hz.
chan_filtered = filtfilt(b, a, chan_data)
However, chan_filtered is a NaN matrix. Why?
I have checked that chan_data does not contain any NaN or Inf. I also tried resetting the butterworth filter range (3-20) over a wide range of values but to no avail. A PSD plot (see attached jpeg file) shows that chan_data encompasses a wide range of frequencies inluding the target frequency (3-20).
  댓글 수: 2
Walter Roberson
Walter Roberson 2023년 5월 10일
If you have even 1 nan or inf in your data the filtered results will likely be nan
Aboltabol
Aboltabol 2023년 5월 10일
@Walter Roberson : I have checked that.
>> sum(isnan(chan_data))
ans =
0
>> sum(isinf(chan_data))
ans =
0

댓글을 달려면 로그인하십시오.

채택된 답변

Star Strider
Star Strider 2023년 5월 10일
The transfer function implementation of the filter is unstable, however I cannot determine the reasson for the instability, although it may simply be the relative magnitudes of the numerator and denominator coefficients.
The easiest way to solve that problem is to use second-order-section implementation of the same filter —
load('Channel_Sim.mat')
% chan_data
Fs = 1000;
[b,a] = butter(4, [3 20] ./ (1000/2));
[z,p,k] = butter(4, [3 20] ./ (1000/2));
[sos,g] = zp2sos(z,p,k);
sos = 4×6
1.0000 2.0000 1.0000 1.0000 -1.8460 0.8546 1.0000 2.0000 1.0000 1.0000 -1.9175 0.9319 1.0000 -2.0000 1.0000 1.0000 -1.9598 0.9604 1.0000 -2.0000 1.0000 1.0000 -1.9885 0.9889
g = 7.1024e-06
figure
freqz(b,a, 2^18, 1000)
set(subplot(2,1,1), 'XLim',[0 50])
set(subplot(2,1,2), 'XLim',[0 50])
Check = nnz(isnan(chan_data))
Check = 0
L = numel(chan_data);
L = 7000
t = linspace(0, L-1, L)/Fs;
figure
plot(t, chan_data)
grid
Fn = Fs/2;
NFFT = 2^nextpow2(L)
NFFT = 8192
FTcd = fft((chan_data-mean(chan_data)).*hann(L), NFFT)/L;
Fv = linspace(0, 1, NFFT/2+1)*Fn;
Iv = 1:numel(Fv);
figure
plot(Fv, abs(FTcd(Iv))*2)
grid
chan_filtered = filtfilt(b, a, chan_data)
chan_filtered = 7000×1
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
chan_filtered = filtfilt(sos, g, chan_data);
figure
plot(t, chan_filtered)
grid
chan_filtered = bandpass(chan_data, [3 20], Fs, 'ImpulseResponse','iir');
figure
plot(t, chan_filtered)
grid
The second-order-section implementation of the same Butterworth filter then works, and produces essentially the same result as an elliptic bandpass filter with the same essential parameters.
.
  댓글 수: 2
Aboltabol
Aboltabol 2023년 5월 11일
편집: Aboltabol 2023년 5월 11일
Okay, so, on running this code-block:
load('Channel_Sim.mat') % Sampling frequency is 1000 Hz.
[b,a] = butter(4, [3 20] ./ (1000/2));
[z,p,k] = butter(4, [3 20] ./ (1000/2));
[sos,g] = zp2sos(z,p,k);
chan_filtered_1 = filtfilt(b, a, chan_data);
chan_filtered_2 = filtfilt(sos, g, chan_data);
chan_filtered_1 is NaN but chan_filtered_2 is all right. This is just weird, because they are equivalent representations?! Why does using a SOS implementations skirts around the issue?
Star Strider
Star Strider 2023년 5월 11일
The second-order-section implementation of a filter is always stable (at least in my experience).
The reason has to do with the way the filters are implemented and how filtfilt handles them. The relevant discussion is in the sos documentation section for filtfilt, and a more extensive discussion is in the sosfilt documentation. (I cannot determine from reading the documentation if sosfilt does the same forward-backward filtering that filtfilt does, so filtfilt still appears to be the preferred method of doing the actual filtering.)
.

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Analog Filters에 대해 자세히 알아보기

태그

제품


릴리스

R2023a

Community Treasure Hunt

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

Start Hunting!

Translated by