Source code for modelly.data.recorders.config

"""Collection schedule for one dataset: interval, time window and sliding window."""

from __future__ import annotations

from dataclasses import dataclass


[docs] @dataclass class DatasetConfig: """Configuration for dataset collection behavior. Attributes: interval: Collection frequency in time units start_time: First time to begin collection end_time: Last time to collect (None = collect forever) window_size: Max snapshots to keep (None = keep all, N = sliding window) enabled: Whether collection is active _next_collection: Next scheduled collection time (internal) Examples: # Collect every step from 0 to infinity DatasetConfig(interval=1, start_time=0) # Collect every 5 steps from 100 to 500 DatasetConfig(interval=5, start_time=100, end_time=500) # Collect every step, keep only last 1000 snapshots DatasetConfig(interval=1, start_time=0, window_size=1000) # Warmup phase: skip first 100 steps, collect 100-200 DatasetConfig(interval=1, start_time=100, end_time=200) """ interval: int | float = 1 start_time: int | float = 0 end_time: int | float | None = None window_size: int | None = None enabled: bool = True _next_collection: int | float = 0 _last_collection: int | float = -1 def __post_init__(self): """Validate configuration.""" if self.interval <= 0: raise ValueError(f"interval must be > 0, got {self.interval}") if self.start_time < 0: raise ValueError(f"start_time must be >= 0, got {self.start_time}") if self.end_time is not None and self.end_time <= self.start_time: raise ValueError( f"end_time ({self.end_time}) must be > start_time ({self.start_time})" ) if self.window_size is not None and self.window_size <= 0: raise ValueError(f"window_size must be > 0 or None, got {self.window_size}") self._next_collection = self.start_time
[docs] def should_collect(self, current_time: float) -> bool: """Check if we should collect at this time. Args: current_time: The current simulation time Returns: True if collection should happen, False otherwise """ if not self.enabled: return False # Before start time if current_time < self.start_time: return False # After end time if self.end_time is not None and current_time > self.end_time: return False # Not at scheduled time return not current_time < self._next_collection
[docs] def update_next_collection(self, current_time: float) -> None: """Update the next collection time. Args: current_time: The current simulation time """ self._next_collection = current_time + self.interval # Auto-disable if we've passed end_time if self.end_time is not None and self._next_collection > self.end_time: self.enabled = False