Getting NaN after filtfilt function

18 ビュー (過去 30 日間)
Ritesh
Ritesh 2024 年 1 月 15 日
コメント済み: Star Strider 2024 年 1 月 28 日
I am applying a simple butterworth bandpass filter to a signal having low cut off freq 0.5 and higher cutoff freq 3. But after designing the filter when i am applying filtfilt function i am getting the signal as array of NaN. To check if in the specified frequency range any signal does not exist, i crosschecked it with fft and there was some peaks in that range, which indicate the presence of signl in that range. I dont understand why i am getting NaN.
I am giving the data link of matlab drive, fft plots and code.
sampling_frequency = 1000000;
signal = concatenatedData(:, 2);
order = 11;
low_cutoff = 0.5;
high_cutoff = 3;
[b, a] = butter(order, [low_cutoff, high_cutoff] / (sampling_frequency / 2));
filtered_signal = filtfilt(b, a, signal);

採用された回答

Star Strider
Star Strider 2024 年 1 月 15 日
編集済み: Star Strider 2024 年 1 月 15 日
You are using transfer function (‘[b,a]’) output implementation. Often, this creates an unstable filter, producing NaN values in the fitlered output. Using freqz, the instability is readily apparent —
sampling_frequency = 1000000;
% signal = concatenatedData(:, 2);
order = 11;
low_cutoff = 0.5;
high_cutoff = 3;
[b, a] = butter(order, [low_cutoff, high_cutoff] / (sampling_frequency / 2));
% filtered_signal = filtfilt(b, a, signal);
figure
freqz(b, a, 2^16, sampling_frequency)
set(subplot(2,1,1), 'XScale','log')
set(subplot(2,1,2), 'XScale','log')
The solution is to use second-order-section implementation instead, as discussed in the butter documentation section on Limitations. (This is true generally, not simply with Butterworth filters, and the same discussion appears in the documentation on all of them.)
sampling_frequency = 1000000;
% signal = concatenatedData(:, 2);
order = 11;
low_cutoff = 0.5;
high_cutoff = 3;
[z, p, k] = butter(order, [low_cutoff, high_cutoff] / (sampling_frequency / 2));
[sos,g] = zp2sos(z,p,k);
% filtered_signal = filtfilt(sos, g, signal);
figure
freqz(sos, 2^16, sampling_frequency)
set(subplot(2,1,1), 'XScale','log')
set(subplot(2,1,2), 'XScale','log')
There is no instability in the second-order-section implementation.
EDIT — (15 Jan 2024 at 16:52)
Added the buttord call, that designs a 113-order filter —
Wp = [low_cutoff, high_cutoff] / (sampling_frequency / 2);
Ws = [0.9 1.1] .* Wp;
Rp = 1;
Rs = 60;
[n,Wn] = buttord(Wp,Ws,Rp,Rs)
n = 59
Wn = 1×2
1.0e-05 * 0.0991 0.6053
[z,p,k] = butter(n,Wn);
[sos,g] = zp2sos(z,p,k);
% filtered_signal = filtfilt(sos, g, signal);
figure
freqz(sos, 2^16, sampling_frequency)
set(subplot(2,1,1), 'XScale','log')
xt1 = get(subplot(2,1,1), 'XTick')
xt1 = 1×3
1000 10000 100000
set(subplot(2,1,2), 'XScale','log')
xt2 = get(subplot(2,1,2), 'XTick')
xt2 = 1×5
10 100 1000 10000 100000
NOTE — A passband of [0.5 3.0] Hz with a 1 MHz sampling frequency may be difficult to realise in the best of circumstances.
.
  17 件のコメント
Ritesh
Ritesh 2024 年 1 月 28 日
Ok thanks for the clarification.
Star Strider
Star Strider 2024 年 1 月 28 日
As always, my pleasure!

サインインしてコメントする。

その他の回答 (1 件)

Hassaan
Hassaan 2024 年 1 月 15 日
編集済み: Hassaan 2024 年 1 月 15 日
  1. Stability of the Filter: With high filter orders, like the 11th order you're using, the filter can become unstable, especially when applied in a forward-backward manner as filtfilt does. The Butterworth filter design should theoretically be stable, but numerical issues can arise due to finite precision arithmetic.
  2. Initial Conditions: The filtfilt function typically handles initial conditions to reduce transients by using a certain method of padding. If something is off with the initial conditions or the padding, it might lead to NaN values.
  3. Data Quality: Ensure there are no NaN or Inf values in your input signal. filtfilt will not be able to handle these and will propagate NaNs throughout the output.
  4. Filter Coefficients: Check the filter coefficients b and a for any NaN or Inf values. This could happen if the butter function encounters numerical issues.
  5. Signal Characteristics: If the signal has certain characteristics that are not compatible with the filtering process, it might lead to issues. However, since you mentioned that the FFT shows peaks within the passband, this seems less likely.
Here's what you can do to debug:
  • Check for NaNs or Infs in your input signal and filter coefficients.
  • Reduce the filter order. A lower order might be more stable numerically.
  • Normalize your signal if it has very large or very small values. Such values could cause numerical instability.
  • Use a different filtering approach or design method to see if it's specific to filtfilt or Butterworth design.
This script includes checks for NaNs in your signal, filter stability, and also reduces the filter order for better numerical stability.
% Load your signal data
% Assuming 'concatenatedData' is already in your workspace
signal = concatenatedData(:, 2);
% Check for NaNs or Infs in the input signal
if any(isnan(signal)) || any(isinf(signal))
error('Signal contains NaNs or Infs.');
end
% Define filter parameters
sampling_frequency = 1000000;
order = 2; % Reduced order for stability
low_cutoff = 0.5;
high_cutoff = 3;
% Calculate filter coefficients
[b, a] = butter(order, [low_cutoff, high_cutoff] / (sampling_frequency / 2), 'bandpass');
% Check for NaNs or Infs in filter coefficients
if any(isnan(b)) || any(isnan(a)) || any(isinf(b)) || any(isinf(a))
error('Filter coefficients contain NaNs or Infs.');
end
% Check stability of the filter
if any(abs(roots(a)) >= 1)
error('Filter is unstable.');
end
% Apply the filter using filtfilt
filtered_signal = filtfilt(b, a, signal);
% Check for NaNs in the filtered signal
if any(isnan(filtered_signal))
nan_indices = find(isnan(filtered_signal));
fprintf('NaNs start at index %d.\n', nan_indices(1));
else
fprintf('Filtering completed without NaNs.\n');
end
% Plot the original and filtered signals for comparison
figure;
subplot(2,1,1);
plot(signal);
title('Original Signal');
subplot(2,1,2);
plot(filtered_signal);
title('Filtered Signal');
---------------------------------------------------------------------------------------------------------------------------------------------------------
If you find the solution helpful and it resolves your issue, it would be greatly appreciated if you could accept the answer. Also, leaving an upvote and a comment are also wonderful ways to provide feedback.
Professional Interests
  • Technical Services and Consulting
  • Embedded Systems | Firmware Developement | Simulations
  • Electrical and Electronics Engineering
Feel free to contact me.
  1 件のコメント
Ritesh
Ritesh 2024 年 1 月 16 日
Thank you Muhammad for the information. I came to know that the filter is unstable. The reason is clear with star striders answer.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeMultirate and Multistage Filters についてさらに検索

製品


リリース

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by