Advanced: Custom simulators¶
For minimal usage snippets see Minimal usage.
gwmock-noise exposes a public structural protocol,
gwmock_noise.NoiseSimulator, for simulator implementations that want to plug
into the package without subclassing internal base classes.
Required surface¶
A protocol-conformant simulator provides:
duration,sampling_frequency,detectors, andseedattributesgenerate(...)for one-shot realizationsgenerate_stream(...)for stateful chunk iterationmetadatafor descriptive runtime metadata
The public open_stream(...) helper consumes any object that satisfies that
protocol. The helper does not reach into package internals; it simply validates
the public contract and returns the simulator's stream iterator.
Minimal example¶
from collections.abc import Iterator
from typing import Any
import numpy as np
from gwmock_noise import NoiseSimulator, open_stream
class RampNoiseSimulator:
def __init__(self) -> None:
self.duration = 1.0
self.sampling_frequency = 8.0
self.detectors = ["H1"]
self.seed = None
self._offset = 0
def generate(
self,
duration: float,
sampling_frequency: float,
detectors: list[str],
seed: int | None = None,
) -> dict[str, np.ndarray]:
n_samples = round(duration * sampling_frequency)
self.duration = duration
self.sampling_frequency = sampling_frequency
self.detectors = list(detectors)
self.seed = seed
return {detector: np.arange(n_samples, dtype=float) for detector in detectors}
def generate_stream(
self,
chunk_duration: float,
sampling_frequency: float,
detectors: list[str],
seed: int | None = None,
) -> Iterator[dict[str, np.ndarray]]:
n_samples = round(chunk_duration * sampling_frequency)
while True:
start = self._offset
stop = start + n_samples
self._offset = stop
yield {detector: np.arange(start, stop, dtype=float) for detector in detectors}
@property
def metadata(self) -> dict[str, Any]:
return {"implementation": "ramp"}
simulator: NoiseSimulator = RampNoiseSimulator()
stream = open_stream(
simulator,
chunk_duration=0.5,
sampling_frequency=8.0,
detectors=["H1", "L1"],
seed=7,
)
first_chunk = next(stream)
Continuation contract¶
If your simulator advertises stateful continuation, consecutive chunks from
generate_stream(...) should be the same realization a caller would obtain by
asking the same simulator for one seeded single-shot run over the combined
duration. For overlap-add or filter-memory models, keep that state inside the
iterator rather than serializing opaque tokens between calls.