LIBRE / src /domain /interfaces /services /signal_processor.py
RyZ
feat: adding full working local ETL Pipeline
e391a84
Raw
History Blame Contribute Delete
3.28 kB
"""
domain/interfaces/services/signal_processor.py
────────────────────────────────────────────────
SignalProcessor β€” abstract contract for PPG signal preprocessing.
Implements the **Template Method** pattern:
``process()`` defines the fixed pipeline (filter β†’ normalize β†’ segment)
while ``filter_signal()``, ``normalize()``, and ``segment()`` are abstract
and overridden by concrete implementations (e.g. ScipySignalProcessor).
"""
from __future__ import annotations
from abc import ABC, abstractmethod
import numpy as np
class SignalProcessor(ABC):
"""
PPG signal preprocessing contract.
Pipeline (Template Method):
raw signal β†’ filter_signal() β†’ normalize() β†’ segment() β†’ segments array
"""
# ── Abstract Steps ────────────────────────────────────────────────────────
@abstractmethod
def filter_signal(
self,
signal: np.ndarray,
sampling_rate: float,
) -> np.ndarray:
"""
Apply a bandpass filter to remove noise and baseline wander.
Args:
signal: 1-D array of raw PPG amplitude values.
sampling_rate: Sampling rate of the signal in Hz.
Returns:
Filtered signal as a 1-D NumPy array of the same shape.
"""
...
@abstractmethod
def normalize(self, signal: np.ndarray) -> np.ndarray:
"""
Normalise the signal to a standard scale.
Args:
signal: 1-D filtered PPG signal.
Returns:
Normalised signal (e.g. Z-score: mean=0, std=1).
"""
...
@abstractmethod
def segment(
self,
signal: np.ndarray,
sampling_rate: float,
) -> np.ndarray:
"""
Split the signal into fixed-length windows.
Args:
signal: 1-D normalised PPG signal.
sampling_rate: Sampling rate in Hz.
Returns:
2-D NumPy array of shape ``(n_segments, window_size)``.
"""
...
# ── Template Method ───────────────────────────────────────────────────────
def process(
self,
raw_signal: list[float],
sampling_rate: float,
) -> np.ndarray:
"""
Execute the full preprocessing pipeline.
Steps:
1. Convert list β†’ NumPy array
2. filter_signal()
3. normalize()
4. segment()
Args:
raw_signal: Raw PPG values from a PPGSignal entity.
sampling_rate: Sampling rate of the recording in Hz.
Returns:
2-D NumPy array of shape ``(n_segments, window_size)``
ready for model inference.
"""
arr = np.asarray(raw_signal, dtype=np.float64)
filtered = self.filter_signal(arr, sampling_rate)
normalised = self.normalize(filtered)
segments = self.segment(normalised, sampling_rate)
return segments