Skip to content

Reading a run

homeostat.simulate() returns a Run. It holds three views of the same data and the ground truth behind them.

Values

Attribute What it holds
run.truth The true value of every signal that is not an instrument stage: sources, process variables, setpoints, modes, controller outputs, valve positions, and parameters that events change.
run.measured The final output of every instrument: what the controllers read and what a historian can record.
run.observed The historian view: every measured tag plus each controller's setpoint, mode and output. A signal without an instrument never appears here.

Each is a pandas DataFrame with one column per signal. The index is the elapsed time (a TimedeltaIndex), or calendar time when the scenario sets output.start:

output:
  every: 1min
  start: 2026-01-05T06:00:00

run.seconds gives the simulation time of each row in seconds, whichever index the run has.

A run with several lanes (see Twin runs and lanes) has (lane, signal) columns; run.lane(k) gives one lane as a single-lane run, with its own event log.

run.frame(signals) returns any signals, including intermediate instrument stages.

Ground truth

run.meta is a dictionary:

Key Contents
signals A table of every signal: its level (true, measured or internal), whether the historian records it, its unit and description, the operator that writes it, and its roles.
loops Every control loop: its controller, regulated variable, measurement, setpoint, remote setpoint, mode, manual output, output and output limits.
causal_graph Nodes (signals) and edges; each edge says which operator links the two signals and whether the effect is within the same step.
events Every change that was applied, per lane: when, what, how, the value before and after, and whether it was planned or a fault.
timeline The plan's regimes, transitions and maintenance intervals.
promoted Parameters that events change, and the operators they belong to.
units For each unit of a domain library: its template, its signals and its components.
trace Every value drawn from a distribution: its address, value, distribution and log-probability.
scenario The scenario as validated.
reproducibility Homeostat, NumPy and Python versions, platform, seed, step, lanes, noise keys, recording interval, initial state and a hash of the configuration.
warnings Anything worth knowing that did not stop the run.

Roles

A role describes what a signal does, relative to a control loop where it has one. In the first scenario:

Signal Level Recorded Roles
FT-101 measured yes measured@FIC-101
FIC-101.cv true no regulated@FIC-101
FV-101 true no manipulated@FIC-101
FIC-101.pressure true no exogenous
FIC-101.sp true yes reference@FIC-101

A signal may hold several roles, for example the regulated variable of one loop and the disturbance of another. Roles come from the structure of the graph, not from names; see Graphs and roles.

Saving a run

The values are ordinary DataFrames:

run.observed.to_csv("historian.csv")
run.truth.to_csv("truth.csv")
run.meta["events"].to_csv("events.csv", index=False)