Skip to content

medfilt_threshold

biosigpy.tools.medfilt_threshold.medfilt_threshold

medfilt_threshold(x: ArrayLike, window: int, factor: float, max_threshold: float) -> np.ndarray

Compute a capped median-filtered adaptive threshold.

Parameters:

Name Type Description Default
x array_like

One-dimensional real numeric signal with at least two samples. Infinite values are invalid.

required
window int

Median window length in samples. Values below 2 are invalid. Windows longer than the signal are clipped to the signal length.

required
factor float

Positive multiplier applied to the median-filtered signal.

required
max_threshold float

Positive upper bound applied to the threshold.

required

Returns:

Type Description
ndarray

One-dimensional threshold array with the same length as x.

Raises:

Type Description
TypeError

If numeric inputs are not real numeric data.

ValueError

If x is empty, has fewer than two samples, is not a vector, contains infinite values, or if scalar parameters are outside their accepted ranges.

Notes

This function implements the Biosiglib tools.medfilt_threshold specification.

Examples:

>>> import numpy as np
>>> from biosigpy.tools import medfilt_threshold
>>> x = np.array([1.0, 1.2, 2.4, 1.1, 1.0])
>>> medfilt_threshold(x, window=3, factor=1.5, max_threshold=2.0).shape
(5,)
Source code in src/biosigpy/tools/medfilt_threshold.py
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
94
def medfilt_threshold(
    x: ArrayLike, window: int, factor: float, max_threshold: float
) -> np.ndarray:
    """Compute a capped median-filtered adaptive threshold.

    Parameters
    ----------
    x : array_like
        One-dimensional real numeric signal with at least two samples.
        Infinite values are invalid.
    window : int
        Median window length in samples. Values below 2 are invalid. Windows
        longer than the signal are clipped to the signal length.
    factor : float
        Positive multiplier applied to the median-filtered signal.
    max_threshold : float
        Positive upper bound applied to the threshold.

    Returns
    -------
    numpy.ndarray
        One-dimensional threshold array with the same length as ``x``.

    Raises
    ------
    TypeError
        If numeric inputs are not real numeric data.
    ValueError
        If ``x`` is empty, has fewer than two samples, is not a vector,
        contains infinite values, or if scalar parameters are outside their
        accepted ranges.

    Notes
    -----
    This function implements the Biosiglib ``tools.medfilt_threshold``
    specification.

    Examples
    --------
    >>> import numpy as np
    >>> from biosigpy.tools import medfilt_threshold
    >>> x = np.array([1.0, 1.2, 2.4, 1.1, 1.0])
    >>> medfilt_threshold(x, window=3, factor=1.5, max_threshold=2.0).shape
    (5,)
    """

    x = as_real_vector(x, name="x")
    if x.size == 0:
        raise ValueError("x must not be empty")
    if x.size < 2:
        raise ValueError("x must contain at least two samples")
    if np.any(np.isinf(x)):
        raise ValueError("x must not contain infinite values")

    window = as_integer_scalar(window, name="window")
    if window < 2:
        raise ValueError("window must be greater than or equal to 2")

    factor = as_positive_real_scalar(factor, name="factor")
    max_threshold = as_positive_real_scalar(max_threshold, name="max_threshold")

    window = min(window, x.size)
    half_window = window // 2
    padded = np.concatenate(
        (
            x[:half_window][::-1],
            x,
            x[-half_window:][::-1],
        )
    )

    filter_length = window - 1
    mf = np.empty(x.size, dtype=np.float64)
    for output_index in range(x.size):
        padded_index = output_index + half_window
        start = padded_index - filter_length // 2
        window_values = padded[start : start + filter_length]
        mf[output_index] = np.median(window_values)

    threshold = factor * mf
    threshold[threshold > max_threshold] = max_threshold
    return threshold