""" domain/value_objects/signal_metadata.py ──────────────────────────────────────── SignalMetadata — immutable value object summarising the technical characteristics of a PPG recording. """ from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True) class SignalMetadata: """ Technical metadata for a PPG signal recording. Attributes: sampling_rate: Number of samples per second (Hz). duration_seconds: Length of the recording in seconds. num_samples: Actual number of data points captured. """ sampling_rate: float duration_seconds: float num_samples: int def __post_init__(self) -> None: if self.sampling_rate <= 0: raise ValueError("SignalMetadata.sampling_rate must be positive") if self.duration_seconds <= 0: raise ValueError("SignalMetadata.duration_seconds must be positive") if self.num_samples <= 0: raise ValueError("SignalMetadata.num_samples must be positive") @property def expected_samples(self) -> int: """Expected sample count derived from duration × sampling_rate.""" return int(self.duration_seconds * self.sampling_rate) @property def nyquist_frequency(self) -> float: """Nyquist frequency = sampling_rate / 2 (Hz).""" return self.sampling_rate / 2.0 def __str__(self) -> str: return ( f"SignalMetadata(" f"fs={self.sampling_rate} Hz, " f"duration={self.duration_seconds}s, " f"samples={self.num_samples})" )