Simulation Results
This guide dives into Sim.results() / Sim.raw_results() so you can understand what dynlib records, how to slice/filter/export results, and how to keep large simulations manageable.
1. Named access with ResultsView
Sim.results() returns a ResultsView that provides ergonomic access to simulation results with names derived from the model spec:
res.t,res.step,res.flagsgive you the time axis, step indices, and status flags as NumPy views.res["x"],res["aux.energy"], orres[["x","y"]]return the recorded series for states and aux variables, stacking multi-variable requests into compact copies when necessary.res.analyze(...)builds aTrajectoryAnalyzer/MultiVarAnalyzerfor quick statistics (max/min/crossings), andres.observerssurfaces runtime observer outputs through the ergonomicObserverResultwrapper.res.segmentmirrors the main API while letting you focus on a single run (autorun#Nnames or manual tags). EachSegmentViewslicest,step,flags, and evenevents()for that chunk without copying.
2. Raw access with: Results
For advanced users needing direct access to the underlying buffers, Sim.raw_results() hands you a Results dataclass that mirrors the runner buffers without copying. The key fields are the backing arrays (time T, states Y, optional aux AUX, STEP, FLAGS), the event log (EVT_CODE, EVT_INDEX, EVT_LOG_DATA), filled counts n/m, exit status, and snapshots of the final state/params/workspaces. Each accessor provides a view limited to the filled region so you always see contiguous records, and Results.to_pandas() can materialize the columns as a tidy DataFrame for downstream NumPy/Pandas workflows.
When you need the entire buffer, use Sim.raw_results(). For most users, Sim.results() wraps this low-level object with names, helpers, and segments.
3. Slicing, filtering, and exporting
- Treat
res["var"]as your primary slicing hook; useres[["x","y"]]to stack multiple series and keep the natural ordering. - For trajectory slices per segment, index
res.segment[0]orres.segment["run#1"]. Each segment respects its recording window and exposesevents()for the wrapped portion. - When you prefer tabular exports,
Results.to_pandas()givest,step,flag, each state column, and prefixed aux columns so you can hand the frame to Pandas/NumPy directly.
Event logging results access
Events are stored alongside the trajectory, and each event row carries a code, owning record index, and logged data blob. ResultsView resolves the DSL-defined names/tags so res.event("threshold") knows which code, fields, and tags to use. Due to NumPy's limitations on arbitrary row views, filtering (time ranges, head/tail, sorting) allocates compact arrays, but the API keeps the allocations isolated so the rest of the results stay view-only.
- Call
res.event("spike")to get anEventView, then chain.time(t0, t1),.head(k),.tail(k), or.sort(by="t")before grabbing individual fields withev["id"]orev[["t","id"]].ev.table()materializes all logged columns in order. - Use
res.event(tag="group")for a grouped view over multiple event types;group.select(...)lets you union or intersect fields whilegroup.table(...)can sort the combined rows. res.event.summary()gives quick counts per event type, andres.event.names()/fields()/tags()help you discover what is recorded.
4. Working with large datasets and external tools
- Control logging via
Sim.config()andrun()hooks: togglerecord, jump everyrecord_intervalsteps, or passrecord_vars/[]to capture only what you need. - Increase
cap_rec/cap_evtto preallocate buffers, lowerrecord_intervalfor downsampling, or disable state/aux logging entirely while still recording time/steps/flags. - Use
transient,resume, and snapshots (Sim.reset(),Sim.create_snapshot()) to manage staged experiments without overwhelming buffers. - Export to NumPy/Pandas via the already exposed arrays (
res.t,res["x"],.events(),.table()) orResults.to_pandas()when you need aDataFramewith consistent column names. res.segment[...],res.event(...), andres.observerskeep the slices you care about independent of the rest of the buffer so you can stream them into downstream analyzers without copying more than necessary.
Summary
- Use
Sim.results()when you want ergonomic names and helpers, and fall back toSim.raw_results()when you need the raw buffer. - Explore segments, events, and observers through
ResultsViewto extract slices, and useResults.to_pandas()or stacking withres[["x","y"]]to hand trajectories to NumPy/Pandas. - Tune
record,record_interval,record_vars, and buffer caps before long runs to keep memory usage stable, then replay or export the events/segments you care about.