Source code for diamondback.filters.window_filter

"""**Description**
    A window filter realizes a discrete difference equation as a function
    of a forward coefficient array of a specified order, consuming an
    incident signal and producing a reference signal.

    .. math::

        y_{n} = b_{n}\\ x_{n}

    A forward coefficient array of a specified order is defined.  A
    style, order, and normalization are specified.

    Style is in ("Blackman", "Hamming", "Hann", "Kaiser").

    * | "Blackman" filters demonstrate low resolution and spectral leakage
      | with improved rate of attenuation.

    * | "Hamming" filters demonstrate minimal nearest side lobe magnitude
      | response.

    * | "Hann" filters demonstrate high resolution and spectral leakage.

    * | "Kaiser" filters demonstrate flexible resolution and spectral
      | leakage dependent upon a beta value of a Bessel function of the
      | first kind, with beta equal to 7.0.

    Normal condition scales a forward coefficient array to electively
    compensate for energy loss.

    .. math::

        b_{n} = b_{n}\\ \\frac{ N }{ \\sum_{0}^{N-1}\\ |\\ b_{n}\\ |}

**Example**

    .. code-block:: python

        from diamondback import ComplexExponentialFilter, WindowFilter
        import numpy

        window_filter = WindowFilter(style = "Hann", order = 15, normal = True)
        x = ComplexExponentialFilter(0.0).filter(numpy.ones(len(window_filter.b)) * 0.1).real
        y = window_filter.filter(x)

**License**
    `BSD-3C.  <https://github.com/larryturner/diamondback/blob/master/license>`_
    © 2018 - 2025 Larry Turner, Schneider Electric Industries SAS. All rights reserved.

**Author**
    Larry Turner, Schneider Electric, AI Hub, 2018-04-13.
"""

import numpy
import scipy.signal


[docs] class WindowFilter(object): """Window filter.""" STYLE: tuple[str, ...] = ("Blackman", "Hamming", "Hann", "Kaiser") @property def b(self): return self._b def __init__(self, style: str, order: int, normal: bool = True) -> None: """Initialize. Arguments: style: str - in ("Blackman", "Hamming", "Hann", "Kaiser"). order: int. normal: bool. """ style = style.title() if style not in WindowFilter.STYLE: raise ValueError(f"style = {style} Expected Style in {WindowFilter.STYLE}") if order < 0: raise ValueError(f"Order = {order} Expected Order in [0, inf)") if style == "Kaiser": window = (style.lower(), 7.0) else: window = style.lower() # type: ignore super().__init__() b = scipy.signal.get_window(window, order + 1, False) if normal: b *= (order + 1) / sum(abs(b)) self._b = numpy.array(b)
[docs] def filter(self, x: list | numpy.ndarray) -> numpy.ndarray: """Filters an incident signal and produces a reference signal. Arguments: x: list | numpy.ndarray - incident signal. Returns: y: numpy.ndarray - reference signal. """ if not isinstance(x, numpy.ndarray): x = numpy.array(list(x)) if (len(x.shape) != 1) or (len(x) != len(self.b)): raise ValueError(f"X = {x}") return self.b * x