""" domain/interfaces/services/cardiogan_preprocessor.py ──────────────────────────────────────────────────── Abstract interface for CardioGAN signal preprocessing. """ from __future__ import annotations from abc import ABC, abstractmethod import numpy as np class CardioGANSignalPreprocessor(ABC): """ Contract for preprocessing signals for CardioGAN. Responsible for: 1. PPG Resampling: 125 Hz -> 128 Hz 2. Filtering: Butterworth 1-8 Hz 3. Normalization: Z-score (per-subject) 4. Segmentation: 512-sample sliding windows (10% overlap) 5. Scaling: Min-max normalize to [-1, 1] per window """ @abstractmethod def preprocess_ppg(self, ppg_raw: np.ndarray) -> np.ndarray: """ Ingest raw continuous PPG signals @ 125 Hz and output segmented, filtered windows of shape (N_windows, 512) @ 128 Hz in range [-1, 1]. Args: ppg_raw: 1-D array of raw PPG values (usually 125 Hz). Returns: 2-D NumPy array of shape (N_windows, 512) ready for CardioGAN inference. Raises: PreprocessingError: If preprocessing fails (e.g. signal too short). """ ... @abstractmethod def postprocess_ecg(self, ecg_windows_128: np.ndarray) -> np.ndarray: """ Ingest the synthetic ECG windows (N_windows, 512) @ 128 Hz produced by CardioGAN and downsample them back to 125 Hz and align/clip/pad them to VGTL-Net format (224 samples per window). Args: ecg_windows_128: 2-D array of synthetic ECG windows @ 128 Hz. Returns: 2-D NumPy array of shape (N_windows, 224) aligned for VGTL-Net. Raises: PreprocessingError: If postprocessing fails. """ ...