An attempt at rebuilding Robert Meyer's pypet.
The original pypet package, while fantastic, is a little outdated in terms of modern Python practices and dependencies. This is an attempt to rebuild it with modern practices in mind. This is all my own code, but credit to Robert Meyer and other contributors for the original ideas and implementations.
pypet_rebuild is a modern Python toolkit for parameter exploration and result management in numerical simulations. It aims to preserve the core ideas of the original pypet:
- Central trajectory abstraction that holds parameters, results, and metadata.
- Natural naming for ergonomic access (e.g.
traj.parameters.traffic.ncars). - Execution environment that runs user-defined simulations over sets of parameter combinations.
- Structured storage of runs to disk.
The focus is on a clean, typed, and testable core that you can use for experiments, simulations, and small parameter sweeps, with room to grow into more complex workflows.
At a high level, you:
- Define a
Trajectoryand attachParameterobjects. - Write a simulation function that consumes a
Trajectoryand writes backResultobjects. - Use an
Environment(and helpers likecartesian_product) to run that simulation over many parameter combinations. - Optionally persist everything to an HDF5 file via a
StorageService.
This project is under active development and does not yet match the full feature set of the original pypet. So far, the following pieces are in place:
-
Core abstractions
Trajectorywith internal mappings for parameters/results and natural-naming views.Parameter[T]andResult[T]as typed dataclasses.Environmentwithrunandrun_explorationmethods.
-
Exploration
- A small
cartesian_producthelper. Environment.run_explorationto iterate over combinations, update the trajectory, and run a simulation function for each.
- A small
-
Storage
StorageServiceprotocol defining a minimal interface for backends.HDF5StorageServiceimplementation usingh5py, with a simple layout:/trajectories/<name>/parameters/<param_name>/trajectories/<name>/results/<result_name>
- Basic round-trip tests for JSON-serializable values.
-
Testing and tooling
- pytest-based test suite.
- Project managed with
uvandpyproject.toml(Python>=3.12).
See TODO.md for a more detailed roadmap and remaining work.
Below is a minimal example showing how to:
- Define a trajectory with parameters.
- Write a simulation function that computes results.
- Run the simulation over a cartesian product of parameter values.
- Optionally save the trajectory to an HDF5 file.
from pathlib import Path
from pypet_rebuild import (
Environment,
HDF5StorageService,
Parameter,
Result,
Trajectory,
cartesian_product,
)
def simulate(traj: Trajectory) -> None:
"""Simple simulation that multiplies two parameters and records the result."""
x = traj.parameters["x"].value
y = traj.parameters["y"].value
traj.add_result(Result(name=f"product.{x}_{y}", value=x * y))
def main() -> None:
traj = Trajectory(name="multiplication")
# Seed parameters; values will be overwritten during exploration
traj.add_parameter(Parameter(name="x", value=0))
traj.add_parameter(Parameter(name="y", value=0))
storage = HDF5StorageService(file_path=Path("example.h5"))
env = Environment(trajectory=traj, storage=storage)
# Define the parameter space and run over all combinations
space = {"x": [1, 2, 3], "y": [10, 20]}
env.run_exploration(simulate, space=space)
# After this, traj.results contains one result per combination, and
# the data has been written to example.h5.
if __name__ == "__main__":
main()This rebuild intentionally makes some early, concrete improvements relative to the original implementation:
-
Modern packaging and environment
- Uses
pyproject.tomlanduvinstead of legacysetup.pyworkflows. - Targets modern Python versions (currently
>=3.12).
- Uses
-
Typed, dataclass-based domain model
Parameter[T]andResult[T]are simple, generic@dataclassstructures.- Clear, explicit types and signatures across the public API.
-
Clean separation of concerns
Trajectoryis responsible for in-memory parameter/result management and natural naming.Environmentcoordinates execution (single run + exploration) but knows nothing about storage internals.StorageServiceis a small protocol that HDF5 and future backends can implement.
-
Small, composable exploration API
cartesian_productis a pure helper that produces combinations as dictionaries.Environment.run_explorationconsumes any mapping of parameter names to sequences; no hidden global state.
-
Simpler, explicit storage layout
- First-pass HDF5 backend with JSON-encoded values for basic types.
- Clear, documented location for trajectory data in the file.
Future improvements will cover richer data type support (NumPy arrays, pandas), parallel execution, and more robust logging/resuming behavior, while keeping the design modular and testable.