Skip to content

FIR

Download Flojoy Studio to try this app
Apply a low-pass FIR filter to an input vector. The filter is designed with the window method. This filter takes a few inputs: the sample_rate (will be passed as a parameter if the target node is not connected), the window type of the filter, the cutoff frequency, and the number of taps (or length) of the filter. Inputs ------ default : OrderedPair The data to apply a FIR filter to. Params: sample_rate : int the amount of samples within a second filter_type : select how the filter behaves window : select the window function used in the FIR cutoff_low : float the frequency cutoff to filter out the lower frequencies cutoff_high : float the frequency cutoff to filter out the upper frequencies taps : int the length of the filter Returns: out : OrderedPair x: time domain y: filtered signal
Python Code
from scipy import signal
from flojoy import flojoy, OrderedPair
from typing import Literal


@flojoy
def FIR(
    default: OrderedPair,
    sample_rate: int = 100,
    filter_type: Literal["lowpass", "highpass", "bandpass", "bandstop"] = "lowpass",
    window: Literal[
        "boxcar",
        "triang",
        "blackman",
        "hamming",
        "hann",
        "bartlett",
        "flattop",
        "parzen",
        "bohman",
        "blackmanharris",
        "nuttall",
        "barthann",
        "cosine",
        "exponential",
        "tukey",
        "taylor",
        "lanczos",
    ] = "hann",
    cutoff_low: float = 10.0,
    cutoff_high: float = 15.0,
    taps: int = 200,
) -> OrderedPair:
    """Apply a low-pass FIR filter to an input vector. The filter is designed with the window method.

    This filter takes a few inputs: the sample_rate (will be passed as a parameter if the target node is not connected), the window type of the filter, the cutoff frequency, and the number of taps (or length) of the filter.

    Inputs
    ------
    default : OrderedPair
        The data to apply a FIR filter to.

    Parameters
    ----------
    sample_rate : int
        the amount of samples within a second
    filter_type : select
        how the filter behaves
    window : select
        the window function used in the FIR
    cutoff_low : float
        the frequency cutoff to filter out the lower frequencies
    cutoff_high : float
        the frequency cutoff to filter out the upper frequencies
    taps : int
        the length of the filter

    Returns
    -------
    OrderedPair
        x: time domain
        y: filtered signal
    """

    sample_rate: int = sample_rate  # Hz
    filter_type: str = filter_type
    window_type: str = window
    cutoff_low: float = cutoff_low
    cutoff_high: float = cutoff_high
    n_taps: int = taps
    times = default.x
    input_signal = default.y

    if input_signal.size < n_taps * 3:
        raise ValueError("length of the data should be three times longer than taps")
    elif (
        n_taps % 2 == 0
    ):  # in the case where the passband contains the Nyquist frequency
        n_taps = n_taps + 1

    # create the filter with the parameter inputs
    if filter_type == "bandpass" or filter_type == "bandstop":
        fil = signal.firwin(
            numtaps=n_taps,
            cutoff=[cutoff_low, cutoff_high],
            fs=sample_rate,
            pass_zero=filter_type,
            window=window_type,
        )
    elif filter_type == "lowpass":
        fil = signal.firwin(
            numtaps=n_taps,
            cutoff=cutoff_high,
            fs=sample_rate,
            pass_zero=filter_type,
            window=window_type,
        )
    else:
        fil = signal.firwin(
            numtaps=n_taps,
            cutoff=cutoff_low,
            fs=sample_rate,
            pass_zero=filter_type,
            window=window_type,
        )

    # ... and then apply it to the signal
    filtered_x = signal.filtfilt(fil, 1.0, input_signal)
    return OrderedPair(x=times, y=filtered_x)

Find this Flojoy Block on GitHub

Example App

Having problems with this example app? Join our Discord community and we will help you out!
React Flow mini map

In this example, five BASIC_OSCILLATOR nodes generates an array of 400 samples with a sample rate of 100. Each with different amplitude and a unique frequency between 10-35hz. They are then all summed together into one signal using the ADD node.

To then get one of the initial sine waves, which is the one generated by OSC_3 in this case, the FIR node is used to filter out all other frequencies that’s not 25hz.

For the filter type, it will be bandpass as there are unwanted frequencies both above and below 25hz. The high cutoff would be 28hz and the low cutoff would be 23hz. For the window, barthann is used for a sharper cutoff since we don’t want any other frequencies in this example.

For taps, there are a couple of ways of calculating depending on how much attenuation or how much ripple is in the signal. Here are some formulas, the top-rated answer would be the one used in this example. With the transition width being 20, the number of taps would be 80 after calculation.

Finally, the output of FIR node will be displayed with the LINE node, which gives us a very similar graph to OSC_3. Also, two FFT nodes are included to show the frequencies before and after the FIR node.