Bird
Raised Fist0
Signal Processingdata~7 mins

Low-pass FIR filter design in Signal Processing

Choose your learning style10 modes available
Introduction

A low-pass FIR filter lets low frequencies pass and blocks high frequencies. It helps clean signals by removing noise or unwanted fast changes.

You want to remove high-frequency noise from a sound recording.
You need to smooth sensor data that has sudden spikes.
You want to prepare data by keeping only slow trends and removing fast fluctuations.
You are designing a system that only needs signals below a certain frequency.
You want to reduce data size by removing details that change too fast.
Syntax
Signal Processing
from scipy.signal import firwin

# firwin(numtaps, cutoff, window='hamming', pass_zero=True)
# numtaps: number of filter taps (length)
# cutoff: cutoff frequency (0 to 1, where 1 is Nyquist frequency)
# window: type of window to shape filter
# pass_zero=True means low-pass filter

The cutoff frequency is given as a fraction of the Nyquist frequency (half the sampling rate).

The number of taps controls filter sharpness and length; more taps mean better filtering but more delay.

Examples
This creates a simple low-pass filter using the default Hamming window.
Signal Processing
from scipy.signal import firwin

# Create a low-pass FIR filter with 31 taps and cutoff at 0.3 (30% of Nyquist)
filter_coefs = firwin(31, 0.3)
This creates a low-pass filter with 51 taps and a Blackman window for smoother edges.
Signal Processing
filter_coefs = firwin(51, 0.2, window='blackman')
Explicitly sets the filter as low-pass with cutoff at 40% of Nyquist frequency.
Signal Processing
filter_coefs = firwin(21, 0.4, pass_zero=True)
Sample Program

This program creates a low-pass FIR filter with a cutoff at 100 Hz for a 1000 Hz sampling rate. It filters a signal made of a slow 5 Hz wave and a fast 300 Hz wave. The plots show the original signal, the filtered signal (where the 300 Hz part is removed), and the filter's frequency response.

Signal Processing
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import firwin, lfilter, freqz

# Sampling frequency
fs = 1000  # 1000 Hz

# Design low-pass FIR filter
numtaps = 51
cutoff = 100  # 100 Hz cutoff frequency

# Normalize cutoff frequency to Nyquist frequency (fs/2)
normalized_cutoff = cutoff / (fs / 2)

# Get filter coefficients
fir_coeff = firwin(numtaps, normalized_cutoff)

# Create a sample signal: 5 Hz + 300 Hz sine waves
t = np.linspace(0, 1.0, fs, endpoint=False)
signal = np.sin(2 * np.pi * 5 * t) + 0.5 * np.sin(2 * np.pi * 300 * t)

# Apply the filter to the signal
filtered_signal = lfilter(fir_coeff, 1.0, signal)

# Frequency response of the filter
w, h = freqz(fir_coeff, worN=8000)

# Plot results
plt.figure(figsize=(12, 8))

plt.subplot(3, 1, 1)
plt.plot(t, signal)
plt.title('Original Signal (5 Hz + 300 Hz)')
plt.xlabel('Time [seconds]')
plt.ylabel('Amplitude')

plt.subplot(3, 1, 2)
plt.plot(t, filtered_signal)
plt.title('Filtered Signal (Low-pass FIR)')
plt.xlabel('Time [seconds]')
plt.ylabel('Amplitude')

plt.subplot(3, 1, 3)
plt.plot(w * fs / (2 * np.pi), 20 * np.log10(abs(h)))
plt.title('Frequency Response of the Filter')
plt.xlabel('Frequency [Hz]')
plt.ylabel('Gain [dB]')
plt.ylim(-100, 10)
plt.grid(True)

plt.tight_layout()
plt.show()
OutputSuccess
Important Notes

More taps mean better filtering but slower processing and more delay.

Choosing the right window affects the filter's sharpness and ripple.

Always normalize cutoff frequency by Nyquist frequency (half the sampling rate).

Summary

Low-pass FIR filters keep slow changes and remove fast changes in signals.

Use firwin to design filters by specifying taps and cutoff frequency.

Test filters by applying them to signals and checking frequency response.

Practice

(1/5)
1. What is the main purpose of a low-pass FIR filter in signal processing?
easy
A. To convert analog signals to digital
B. To allow high frequencies and block low frequencies
C. To allow low frequencies and block high frequencies
D. To amplify all frequencies equally

Solution

  1. Step 1: Understand filter types

    Low-pass filters are designed to pass signals with frequencies below a cutoff frequency and attenuate frequencies above it.
  2. Step 2: Identify the filter purpose

    Since the filter blocks high frequencies and allows low frequencies, it matches the description in To allow low frequencies and block high frequencies.
  3. Final Answer:

    To allow low frequencies and block high frequencies -> Option C
  4. Quick Check:

    Low-pass filter = allows low frequencies [OK]
Hint: Low-pass means low frequencies pass through [OK]
Common Mistakes:
  • Confusing low-pass with high-pass filters
  • Thinking it amplifies all frequencies
  • Mixing filter purpose with signal conversion
2. Which of the following is the correct way to design a low-pass FIR filter using scipy.signal.firwin with cutoff frequency 0.3 and filter length 51?
easy
A. firwin(51, 0.3, pass_zero=True)
B. firwin(51, 0.3, pass_zero='bandpass')
C. firwin(51, 0.3, pass_zero=False)
D. firwin(51, cutoff=0.3, pass_zero='highpass')

Solution

  1. Step 1: Recall firwin parameters

    The firwin function uses numtaps for length and cutoff frequency. The pass_zero parameter set to True designs a low-pass filter.
  2. Step 2: Match correct syntax

    firwin(51, 0.3, pass_zero=True) uses firwin(51, 0.3, pass_zero=True), which is the correct way to specify a low-pass FIR filter with length 51 and cutoff 0.3.
  3. Final Answer:

    firwin(51, 0.3, pass_zero=True) -> Option A
  4. Quick Check:

    pass_zero=True means low-pass [OK]
Hint: Use pass_zero=True for low-pass in firwin [OK]
Common Mistakes:
  • Using pass_zero='bandpass' instead of True
  • Setting pass_zero=False which makes high-pass
  • Incorrect parameter names like cutoff= instead of positional
3. Given the following code, what is the length of the filter coefficients array coeffs?
from scipy.signal import firwin
coeffs = firwin(numtaps=31, cutoff=0.25, pass_zero=True)
medium
A. 30
B. 31
C. 25
D. 26

Solution

  1. Step 1: Understand numtaps parameter

    The numtaps parameter in firwin specifies the number of filter coefficients (taps) to generate.
  2. Step 2: Check given numtaps value

    Here, numtaps=31 means the filter will have 31 coefficients.
  3. Final Answer:

    31 -> Option B
  4. Quick Check:

    numtaps = length of coeffs = 31 [OK]
Hint: numtaps equals filter length in firwin [OK]
Common Mistakes:
  • Confusing cutoff frequency with length
  • Off-by-one errors in counting taps
  • Assuming length is cutoff * numtaps
4. Identify the error in this FIR filter design code:
from scipy.signal import firwin
coeffs = firwin(50, cutoff=0.4, pass_zero=False)
print(len(coeffs))
medium
A. pass_zero=False creates a high-pass filter, not low-pass
B. numtaps must be an odd number for low-pass filters
C. The cutoff frequency must be between 0 and 1
D. firwin requires window parameter to be set

Solution

  1. Step 1: Check pass_zero parameter meaning

    Setting pass_zero=False in firwin designs a high-pass filter, not a low-pass filter.
  2. Step 2: Identify mismatch with question intent

    The code intends to design a low-pass filter but uses pass_zero=False, which is incorrect for low-pass.
  3. Final Answer:

    pass_zero=False creates a high-pass filter, not low-pass -> Option A
  4. Quick Check:

    pass_zero=False means high-pass, not low-pass [OK]
Hint: pass_zero=False means high-pass filter [OK]
Common Mistakes:
  • Assuming pass_zero=False is low-pass
  • Thinking cutoff frequency range is invalid
  • Believing window parameter is mandatory
5. You want to design a low-pass FIR filter with a cutoff frequency of 1000 Hz for a signal sampled at 8000 Hz. Which firwin call correctly sets the cutoff parameter?
hard
A. firwin(51, cutoff=1000, pass_zero=True)
B. firwin(51, cutoff=0.125, fs=8000, pass_zero=True)
C. firwin(51, cutoff=0.125, pass_zero=True)
D. firwin(51, cutoff=1000, fs=8000, pass_zero=True)

Solution

  1. Step 1: Understand cutoff frequency scaling

    When specifying fs (sample rate), the cutoff frequency must be given in Hz, not normalized frequency.
  2. Step 2: Calculate normalized cutoff frequency

    Normalized cutoff = cutoff frequency / (fs / 2) = 1000 / (8000 / 2) = 1000 / 4000 = 0.25. But since fs=8000 is given, cutoff should be in Hz, so cutoff=1000 is valid.
  3. Step 3: Check options

    firwin(51, cutoff=1000, fs=8000, pass_zero=True) uses cutoff=1000 with fs=8000, which is correct. firwin(51, cutoff=0.125, fs=8000, pass_zero=True) uses cutoff=0.125 with fs=8000, which is incorrect because cutoff should be in Hz if fs is specified. firwin(51, cutoff=0.125, pass_zero=True) uses cutoff=0.125 without fs, which means normalized frequency. firwin(51, cutoff=1000, pass_zero=True) uses cutoff=1000 without fs, which is invalid.
  4. Step 4: Correct interpretation

    Actually, when fs is specified, cutoff is in Hz. So cutoff=1000 with fs=8000 is correct (firwin(51, cutoff=1000, fs=8000, pass_zero=True)). firwin(51, cutoff=0.125, fs=8000, pass_zero=True) cutoff=0.125 Hz is too low. So firwin(51, cutoff=1000, fs=8000, pass_zero=True) is correct.
  5. Final Answer:

    firwin(51, cutoff=1000, fs=8000, pass_zero=True) -> Option D
  6. Quick Check:

    With fs, cutoff is in Hz [OK]
Hint: With fs, cutoff is in Hz; without fs, cutoff is normalized [OK]
Common Mistakes:
  • Using normalized cutoff with fs parameter
  • Omitting fs when cutoff is in Hz
  • Confusing normalized and absolute frequency units
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard