Skip to content

lpd_filter

biosigpy.tools.lpd_filter.lpd_filter

lpd_filter(sampling_frequency: float, stop_frequency: float, pass_frequency: float | None = None, order: int | None = None) -> tuple[np.ndarray, float]

Design a Biosiglib-compatible low-pass differentiator FIR filter.

Parameters:

Name Type Description Default
sampling_frequency float

Positive sampling frequency in Hz.

required
stop_frequency float

Positive stop frequency in Hz. The value must be less than the Nyquist frequency.

required
pass_frequency float or None

Positive pass frequency in Hz. When omitted, stop_frequency - 0.2 is used. The pass frequency must be less than stop_frequency.

None
order int or None

Explicit positive filter order. Automatic order selection is currently unsupported.

None

Returns:

Type Description
tuple[ndarray, float]

(b, delay) where b is a one-dimensional array of FIR coefficients and delay is the filter delay in samples.

Raises:

Type Description
TypeError

If scalar inputs are not real numeric values.

ValueError

If frequencies or order are outside their accepted ranges.

NotImplementedError

If order is None.

Notes

This function implements the Biosiglib tools.lpd_filter specification and follows the MATLAB/Biosigmat-compatible low-pass differentiator design.

Explicit order design is supported. Automatic order selection is not currently implemented. The effective order is rounded up to an even value. Coefficients are scaled by sampling_frequency / (2*pi), and the returned delay is filter_order / 2 for the effective filter order.

Examples:

>>> from biosigpy.tools import lpd_filter
>>> b, delay = lpd_filter(256.0, 12.0, order=4)
>>> b.shape
(5,)
>>> delay
2.0
Source code in src/biosigpy/tools/lpd_filter.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
def lpd_filter(
    sampling_frequency: float,
    stop_frequency: float,
    pass_frequency: float | None = None,
    order: int | None = None,
) -> tuple[np.ndarray, float]:
    """Design a Biosiglib-compatible low-pass differentiator FIR filter.

    Parameters
    ----------
    sampling_frequency : float
        Positive sampling frequency in Hz.
    stop_frequency : float
        Positive stop frequency in Hz. The value must be less than the
        Nyquist frequency.
    pass_frequency : float or None, optional
        Positive pass frequency in Hz. When omitted, ``stop_frequency - 0.2``
        is used. The pass frequency must be less than ``stop_frequency``.
    order : int or None, optional
        Explicit positive filter order. Automatic order selection is currently
        unsupported.

    Returns
    -------
    tuple[numpy.ndarray, float]
        ``(b, delay)`` where ``b`` is a one-dimensional array of FIR
        coefficients and ``delay`` is the filter delay in samples.

    Raises
    ------
    TypeError
        If scalar inputs are not real numeric values.
    ValueError
        If frequencies or order are outside their accepted ranges.
    NotImplementedError
        If ``order`` is ``None``.

    Notes
    -----
    This function implements the Biosiglib ``tools.lpd_filter`` specification
    and follows the MATLAB/Biosigmat-compatible low-pass differentiator design.

    Explicit ``order`` design is supported. Automatic order selection is not
    currently implemented. The effective order is rounded up to an even value.
    Coefficients are scaled by ``sampling_frequency / (2*pi)``, and the
    returned delay is ``filter_order / 2`` for the effective filter order.

    Examples
    --------
    >>> from biosigpy.tools import lpd_filter
    >>> b, delay = lpd_filter(256.0, 12.0, order=4)
    >>> b.shape
    (5,)
    >>> delay
    2.0
    """

    sampling_frequency = as_positive_real_scalar(
        sampling_frequency, name="sampling_frequency"
    )
    stop_frequency = as_positive_real_scalar(stop_frequency, name="stop_frequency")

    if pass_frequency is None:
        pass_frequency = stop_frequency - 0.2
    pass_frequency = as_positive_real_scalar(pass_frequency, name="pass_frequency")

    if stop_frequency >= sampling_frequency / 2.0:
        raise ValueError("stop_frequency must be less than Nyquist frequency")
    if pass_frequency >= stop_frequency:
        raise ValueError("pass_frequency must be less than stop_frequency")

    if order is None:
        raise NotImplementedError("automatic lpd_filter order is not supported")
    filter_order = as_integer_scalar(order, name="order")
    if filter_order <= 0:
        raise ValueError("order must be positive")
    filter_order = filter_order + (filter_order % 2)

    w_pass = pass_frequency / (sampling_frequency / 2.0)
    w_stop = stop_frequency / (sampling_frequency / 2.0)
    b = _firls_differentiator(filter_order, w_pass, w_stop)
    b = b * sampling_frequency / (2.0 * np.pi)
    delay = filter_order / 2.0

    return b, delay