"""
Time-domain single-band power estimation.
Two methods are provided:
1. **RMS Band Power** — Bandpass filter, square, window into bins, take the mean, optionally take the square root.
2. **Square-Law + LPF Band Power** — Bandpass filter, square, lowpass filter (smoothing), downsample.
"""
from dataclasses import field
import ezmsg.core as ez
from ezmsg.baseproc import (
BaseProcessor,
BaseStatefulProcessor,
BaseTransformerUnit,
CompositeProcessor,
)
from ezmsg.util.messages.axisarray import AxisArray
from ezmsg.util.messages.modify import ModifyAxisSettings, ModifyAxisTransformer
from .aggregate import AggregateSettings, AggregateTransformer, AggregationFunction
from .butterworthfilter import ButterworthFilterSettings, ButterworthFilterTransformer
from .downsample import DownsampleSettings, DownsampleTransformer
from .materialize import MaterializeMode, materialize_array
from .math.pow import PowSettings, PowTransformer
from .window import WindowTransformer
[docs]
class RMSBandPowerSettings(ez.Settings):
"""Settings for :obj:`RMSBandPowerTransformer`."""
bandpass: ButterworthFilterSettings = field(
default_factory=lambda: ButterworthFilterSettings(order=4, coef_type="sos")
)
"""Butterworth bandpass filter settings. Set ``cuton`` and ``cutoff`` to define the band."""
bin_duration: float = 0.05
"""Duration of each non-overlapping bin in seconds."""
apply_sqrt: bool = True
"""If True, output is RMS (root-mean-square). If False, output is mean-square power."""
materialize: MaterializeMode = MaterializeMode.ASYNC
"""How to evaluate the output on a lazy backend (MLX); see
:obj:`~ezmsg.sigproc.materialize.MaterializeMode`. No-op elsewhere.
Defaults to :obj:`~ezmsg.sigproc.materialize.MaterializeMode.ASYNC`, which
keeps a lazy graph from accumulating without blocking the caller for values
it has no use for. Set ``OFF`` if a downstream node already materializes
every cycle, or ``SYNC`` to time this stage's work as its own."""
[docs]
class RMSBandPower(BaseTransformerUnit[RMSBandPowerSettings, AxisArray, AxisArray, RMSBandPowerTransformer]):
SETTINGS = RMSBandPowerSettings
[docs]
class SquareLawBandPowerSettings(ez.Settings):
"""Settings for :obj:`SquareLawBandPowerTransformer`."""
bandpass: ButterworthFilterSettings = field(
default_factory=lambda: ButterworthFilterSettings(order=4, coef_type="sos")
)
"""Butterworth bandpass filter settings. Set ``cuton`` and ``cutoff`` to define the band."""
lowpass: ButterworthFilterSettings = field(
default_factory=lambda: ButterworthFilterSettings(order=4, coef_type="sos")
)
"""Butterworth lowpass filter settings for smoothing the squared signal."""
downsample: DownsampleSettings = field(default_factory=DownsampleSettings)
"""Downsample settings for rate reduction after lowpass smoothing."""
[docs]
class SquareLawBandPower(
BaseTransformerUnit[SquareLawBandPowerSettings, AxisArray, AxisArray, SquareLawBandPowerTransformer]
):
SETTINGS = SquareLawBandPowerSettings