Bamboost

Reading data

Once simulation runs have produced their data.h5 file, the default Simulation objects expose a read-only view of everything that was stored via the writing APIs described earlier. This page focuses on interactive exploration inside notebooks or post-processing scripts.

Locate the simulation

from bamboost import Collection, Simulation

coll = Collection(uid="315628DE80")  # or Collection.fromUID[...]
sim = coll["kelvin-helmholtz"]  # immutable Simulation

# When you already know the full UID
same_sim = Simulation.from_uid("315628DE80:kelvin-helmholtz")

The returned instance lazily opens data.h5 as an immutable file. All objects derived from it are simple handles—no data is loaded until you slice or call [...].

Inspect metadata, parameters, and files

sim.parameters
sim.metadata["description"]
sim.files["run.sh"]  # pick a file stored next to data.h5
sim.links["mesh"]  # resolve linked simulations

Metadata and parameter dictionaries are the same structures that writers mutate, so they already contain everything that was registered during setup or the run itself.

Explore the default series

More guidance is available in the Series User Guide.

The sim.data property returns the default Series stored at /data. Rendering the object in a notebook prints an HTML summary (number of steps, available fields, global diagnostics). You can also query it programmatically:

sim.data.values  # numpy array with the stored step values (e.g. time)
sim.data.get_field_names()  # list of field names
['pressure', 'velocity']

Read global datasets

Global data stays in a single dataset per quantity (shape = (n_steps, *value_shape)). Use pandas to combine them quickly:

diagnostics = sim.data.globals.df
diagnostics.head()
values energy mass
0 0.0 678.859997 521.509861
1 0.1 695.994317 521.157519
2 0.2 708.395087 512.151310
3 0.3 690.082926 513.027323
4 0.4 686.795547 517.443834

To work with plain numpy arrays:

energy = sim.data.globals["energy"][:]       # read every step
subset, names = sim.data.globals.get("en*", "mass")  # wildcard selection
subset, names
((array([678.85999723, 695.99431696, 708.39508727, 690.08292629,
         686.79554685, 690.18930199, 671.30498008, 699.46591738,
         680.64663633, 689.71799194, 705.41799224]),
  array([521.5098607 , 521.15751857, 512.15131027, 513.0273229 ,
         517.4438335 , 508.60329627, 494.4984517 , 506.28011232,
         509.13282612, 528.91031932, 510.86936242])),
 ('energy', 'mass'))

Read field data

Field datasets are stored one per step (named "0", "1", …). The FieldData wrapper behaves like a numpy array along the first dimension:

pressure = sim.data["pressure"]
pressure[-1]                 # most recent step
pressure[::10, :, :]         # strided slicing
pressure.at(0)               # dataset handle for step 0 (no read yet)
<HDF5 Dataset "/data/fields/pressure/0" (VALID, file /home/runner/work/bamboost-docs/bamboost-docs/content/docs/../data/getting-started/kelvin-helmholtz/data.h5)>

Slicing loads the requested steps into memory. If the per-step shapes differ, the return value falls back to an object array so that heterogeneous meshes can still be read.

Work with other series

Any additional series created via require_series is reachable from the reader as well:

diagnostics = sim.require_series("dynamic_loading")
diagnostics.values          # e.g. probe locations or custom coordinates
drag = diagnostics.globals["energy"][:]

require_series on an immutable simulation simply returns an existing series (it will raise NotASeriesError if the path is not tagged as a series). Use the helper methods such as series.get_fields("*pressure*") when working with many fields at once.

Access custom HDF5 content

Whenever you need something outside of the series abstraction, fall back to the generic HDF objects:

stats = sim.root["statistics"]
stats.attrs
residual_history = stats["residual_history"][:]
mesh_coords = sim.root["/mesh/fluid"]["coordinates"][()]

These APIs mirror h5py.Group/Dataset but keep the benefits of the lazy file handler, auto-retry, and MPI-aware single-process queue. That means you can mix high-level series reads with low-level inspection without ever manually touching h5py.File.

On this page