Source code for superstats.simulation.augmentation.missing

"""Abstract base class for missing-data augmentation processes."""

from abc import ABC, abstractmethod
from collections.abc import Mapping
import numpy as np


[docs] class MissingProcess(ABC): """Introduces missingness into simulated data. Contract: ``(data, rng) -> filled | {"missing_mask": mask}``, where ``data`` is a mapping of named arrays with shape ``(batch_size, num_steps)``. ``mask`` is a boolean array of shape ``(batch_size, num_steps)`` (True = missing), and the returned data keys contain the masked entries set to the process's ``missing_value``. Instances are callable, so a MissingProcess, a subclass, or a bare function with this signature are interchangeable. """ @staticmethod def _default_rng(rng: np.random.Generator | None) -> np.random.Generator: """Single source of truth for the "no rng supplied" fallback. Both `apply` (called directly) and `__call__` (called via the instance) route through this, so there is one definition of what "no rng" means, even though both are safe to call without one. """ return np.random.default_rng() if rng is None else rng
[docs] @abstractmethod def apply(self, data: Mapping[str, np.ndarray], rng: np.random.Generator | None = None) -> dict: """Apply the missingness process. Parameters ---------- data : mapping of np.ndarray Simulated data to corrupt with missingness. rng : np.random.Generator or None, optional, default: None Random generator to use. If None, a fresh, unseeded generator is created via `_default_rng`, so calling `apply` directly is safe but not reproducible unless a seeded `rng` is supplied. Returns ------- result : flat dict with data keys, "missing_mask", and optional metadata """ ...
def __call__(self, data: Mapping[str, np.ndarray], rng: np.random.Generator | None = None) -> dict: return self.apply(data, self._default_rng(rng))