I am trying to create an FIR bandpass filter in python using scipy with the following characteristics:

$$f_{c_{low}} = 310\,Hz$$

$$f_{c_{high}} =600\, Hz$$ giving me a bandwidth of: $$Bandwidth = f_{c_{high}} - f_{c_{low}} = 390 $$

frequency response of the band pass filter

I generate an real valued input signal using a sampling frequency of 1 kHz [using the following code]: $$y(t) = sin(2\pi\cdot 10 \cdot t) +sin(2\pi\cdot 480 \cdot t) + sin(2\pi\cdot 500 \cdot t) +sin(2\pi\cdot 800 \cdot t)$$

fs     = 1000  # the sampling frequency
w0     = 10
w1     = 480
w2     = 500
w3     = 800

t      = np.linspace(0, 1, fs, False)  # 1 second

signal = np.sin(2*np.pi*w0*t) +np.sin(2*np.pi*w1*t) + np.sin(2*np.pi*w2*t)+np.sin(2*np.pi*w3*t) 

and I use the following code snippet to produce the bandpass filter:

def bandpass_filter_fir(cut_l,cut_h,order=5):
    def t(fs_,gn=1):
        nyq = 0.5 * fs_
        return sig.firwin2(order+1, [0,cut_l/nyq,cut_l/nyq,cut_h/nyq,cut_h/nyq,1],[0,0,gn,gn,0,0])
    return t

I divide the cutoff frequencies by the Nyquist frequency to normalize them. However, doing so for this particular example would produce a normalized frequency larger than 1 for the cutoff high frequency:

$$\frac{2 \cdot f_c}{fs} = \frac{2 \cdot 600}{1000}=1.2$$

which is not valid since according to the Nyquist sampling theory: $$ f_c \leq \frac{f_s}{2} $$

Executing the following code snippet:

order      = 1001
f1,f2      = 310,600
bp_filter = bandpass_filter_fir(f1,f2,order=order)

w, h = sig.freqz(bp2_filter(1000), worN=500) # since I plan to plot the frequency response

would lead to the following generated error in python:

~/.local/lib/python3.8/site-packages/scipy/signal/fir_filter_design.py in firwin(numtaps, cutoff, width, window, pass_zero, scale, nyq, fs)
    396         raise ValueError("At least one cutoff frequency must be given.")
    397     if cutoff.min() <= 0 or cutoff.max() >= 1:
--> 398         raise ValueError("Invalid cutoff frequency: frequencies must be "
    399                          "greater than 0 and less than fs/2.")
    400     if np.any(np.diff(cutoff) <= 0):

ValueError: Invalid cutoff frequency: frequencies must be greater than 0 and less than fs/2.

So my question is how to deal with it ? Do I up-sample the signal such that the $f_s = 2f_{c_{high}}$ and pass it through the filter then down-sample the output of the filter back to its original sampling frequency?

  • $\begingroup$ Is your signal real or complex? If real, then the sampled waveform only has unique frequencies from DC to the Nyquist Frequency and you can only filter in that range. What is the bandwidth and frequency range of the analog filter just before the signal was sampled? $\endgroup$ Jun 12 '21 at 1:46
  • $\begingroup$ @DanBoschen The input signal i am using is real. what do you mean by and you can only filter in that range? How do i restrict it to that range? the bandwidth is 290 Hz. I have slightly modified the question, to perhaps add more clarity. i am not understand what you mean by frequency range of the analog filter just before the signal was sampled. Does the frequency range of the filter change depending on how the signal was sampled? $\endgroup$
    – harry
    Jun 12 '21 at 3:11
  • $\begingroup$ @V.V.T: are you familiar with the Sampling Theorem ? $\endgroup$
    – Hilmar
    Jun 12 '21 at 13:13
  • $\begingroup$ harry, see my answer below that I think will help fill in the blanks. $\endgroup$ Jun 12 '21 at 14:24

It appears the OP is missing a critical point about the effects of sampling a continuous time signal, so I provide some slides I have below that may be helpful demonstrating the periodic frequency spectrum that results due to sampling. The spectrum is only unique from $-f_s/2$ to $+f_s/2$ where $f_s$ is the sampling rate and for real waveforms that spectrum is complex conjugate symmetric. Thus we can only represent real analog waveforms (and associated filters) that are less than half the sampling rate:

This is demonstrated with a sampling of a 3 Hz cosine wave at a 20 Hz sampling rate:


Multiplication in time is convolution in frequency, so the sampling process is the convolution in frequency of the analog waveform with the spectrum of the sampling process (which is an impulse train):

FT of an impulse train

The result of this convolution is repetition (periodicity) in frequency. This is the reason we only concern ourselves with the digital spectrum from $-f_s/2$ to $+f_s/2$ or equivalently in units of normalized angular frequency $-\pi$ to $\pi$.

sampling a 3 Hz Cosine Wave

$|f_s/2|$ is the Nyquist boundary, if we go beyond that in the analog domain, aliasing results:


Notice in the graphic above this is the general case for aliasing applicable to all waveforms including complex signals. What goes over one edge ($+f_s/2$) wraps around and comes back in through the other edge ($-f_s/2$). This occurs for both real and complex signals, but since real signals are complex conjugate symmetric, it give us the misleading impression that the signal "folds" over $f_s/2$, resulting in what I would call an unfortunate name for the Nyquist frequency as the "folding frequency". Given the utility and use of complex signal processing, I recommend using the notion of wrapping (such as with a cylinder) when envisioning aliasing and not "folding".

  • $\begingroup$ Thanks a lot for the detailed explanation ! I may or may not have understood the answer so bear with me I am sorry. So from what I understand, the signal is under-sampled for the filter I am using is that right? , and that would cause aliasing leading to a distorted signal that is far different than the original when brought back into the time domain due to folding? $\endgroup$
    – harry
    Jun 12 '21 at 15:12
  • $\begingroup$ If I understood well , maybe I suppose my question could have been better framed as, Given any signal that is under-sampled, how do overcome aliasing ? and Given that i donot have control over the sampling, do I resample the already sampled signal at a much higher sampling frequency (using interpolation) , perform operations that would otherwise have not been possible then restore the signal back to it's original, OR do i limit the operation to the allowed |fs/2| Nyquist boundary ? $\endgroup$
    – harry
    Jun 12 '21 at 15:18
  • $\begingroup$ @Harry We can leverage aliasing to perform frequency translation with aliasing and that would be a purpose for "undersampling". But in all cases the signal in the analog must occupy a total bandwidth that is less than $f_s/2$ (if a real signal), and then that analog signal must be filtered (bandpass if undersampling) to eliminate all the other frequency locations that would also map to the primary first Nyquist zone of $-f_s/2$ to $+f_s/2$. Does that make more sense? $\endgroup$ Jun 12 '21 at 15:35
  • $\begingroup$ Once a signal is aliased and destructively combined with signals aliased from other locations, if we don't know any other information about the signal, the effect of the aliasing is irreversible. This would be similar to saying x+y = 12, find x and y. $\endgroup$ Jun 12 '21 at 15:37
  • $\begingroup$ Thanks a lot again! much appreciated. $\endgroup$
    – harry
    Jun 12 '21 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.