Source code for modelly.data.recorders.registry

"""DataRegistry: the named datasets a model exposes to its recorders."""

from __future__ import annotations

from typing import TYPE_CHECKING

import numpy as np

from modelly.core.agent import Agent
from modelly.core.agentset import AbstractAgentSet
from modelly.data.recorders.numpy_dataset import NumpyAgentDataSet
from modelly.data.recorders.object_datasets import AgentDataSet, ModelDataSet

if TYPE_CHECKING:
    from modelly.core.model import Model
    from modelly.data.recorders.protocol import DataSet


[docs] class DataRegistry: """A registry for data sets.""" def __init__(self): """Initialize the registry.""" self.datasets = {}
[docs] def add_dataset(self, dataset: DataSet): """Add a dataset to the registry. Args: dataset: the dataset to register Raises: RuntimeError: if a dataset with the same name is already registered """ if dataset.name not in self.datasets: self.datasets[dataset.name] = dataset else: raise RuntimeError(f"Dataset '{dataset.name}' already registered")
[docs] def create_dataset( self, dataset_type, name, *args, fields: str | list[str] | None = None, **kwargs ) -> DataSet: """Create a dataset of the specified type and add it to the registry.""" dataset = dataset_type(name, *args, fields=fields, **kwargs) self.datasets[name] = dataset return dataset
[docs] def track_agents( self, agents: AbstractAgentSet, name: str, fields: str | list[str] | None = None, *, use_dirty_flag: bool = False, ) -> AgentDataSet: """Track the specified fields for the agents in the AgentSet.""" return self.create_dataset( AgentDataSet, name, agents, fields=fields, use_dirty_flag=use_dirty_flag, )
[docs] def track_model( self, model: Model, name: str, fields: str | list[str] | None = None, ) -> ModelDataSet: """Track the specified fields in the model.""" return self.create_dataset(ModelDataSet, name, model, fields=fields)
[docs] def track_agents_numpy( self, agent_type: type[Agent], name: str, fields: str | list[str] | None = None, n: int = 100, dtype: np.dtype | type = np.float64, ) -> NumpyAgentDataSet: """Track agent fields using NumPy storage. Args: agent_type: The agent class to install properties on name: Name of the dataset fields: Attribute names to track n: Initial capacity dtype: NumPy dtype for the array Returns: The created NumpyAgentDataSet """ dataset = NumpyAgentDataSet(name, agent_type, fields=fields, n=n, dtype=dtype) self.datasets[name] = dataset return dataset
[docs] def close(self): """Close all datasets.""" for dataset in self.datasets.values(): dataset.close()
def __getitem__(self, name: str) -> DataSet: """Get a dataset by name.""" return self.datasets[name] def __contains__(self, name: str) -> bool: """Check if a dataset exists.""" return name in self.datasets
[docs] def get(self, name: str, default=None) -> DataSet | None: """Get a dataset by name.""" return self.datasets.get(name, default)
def __iter__(self): """Iterate over datasets.""" return iter(self.datasets.values())