DataSet — Managed Storage¶
DataSet is a container that groups multiple named Arrays (and
other Python objects) and optionally backs them to an HDF5 or zarr file. It is
the recommended way to organise all channels from a single experiment run.
Creating a DataSet¶
With a new result file¶
import escape
ds = escape.DataSet.create_with_new_result_file("run0042_reduced.esc.h5")
The filename must carry the .esc suffix (and .h5 or .zarr to select
the backend).
Without a file (in-memory only)¶
ds = escape.DataSet()
Appending Data¶
append() accepts escape.Array objects, plain NumPy/dask
arrays, or arbitrary Python objects:
from escape.storage.example_data import make_pump_probe_scan
sig, i0, pump_on, delay = make_pump_probe_scan(n_steps=10)
ds.append(sig, name="signal")
ds.append(i0, name="i0")
ds.append(pump_on, name="pump_on")
ds.append(delay, name="delay")
After appending, channels are accessible as attributes:
print(ds.signal.shape) # (5000,)
print(ds.i0.scan.count()) # [500, 500, ...]
Serialisation is handled automatically:
escape.Array→ stored in the HDF5 group as a series of chunked datasets.Arbitrary Python objects → pickled or hickled depending on the file backend.
Loading a Saved DataSet¶
ds = escape.DataSet.load_from_result_file("run0042_reduced.esc.h5")
print(list(ds.datasets.keys()))
# ['signal', 'i0', 'pump_on', 'delay']
escape.Array channels are loaded as lazy dask-backed Arrays — no data is read
until you call .compute() or access a reduction.
Computing and Storing Multiple Arrays Efficiently¶
For dask-backed Arrays you can compute them all in one scheduler pass:
# Derived quantities (still lazy)
sig_norm = sig / i0
# Store a batch of arrays efficiently — all dask graphs are fused
escape.store([ds.datasets["signal"], ds.datasets["i0"]])
Or compute into memory:
sig_np, i0_np = escape.compute(sig, i0)
Storing Small Quantities in Bulk¶
store_datasets_max_element_size() stores all Arrays
whose per-event element size is below a threshold (in number of values) in one
efficient batch. This is useful after loading raw data and attaching derived
quantities:
# Store all scalar or small-array channels (skip large detector images)
ds.store_datasets_max_element_size(max_element_size=5000)
Using DataSet as a Context Manager¶
with escape.DataSet.create_with_new_result_file("output.esc.h5") as ds:
ds.append(sig, name="signal")
escape.store([ds.datasets["signal"]])
# file is closed automatically
Merging Multiple DataSets¶
merge_datasets() concatenates all common
channels:
ds1 = escape.DataSet.load_from_result_file("run0001_reduced.esc.h5")
ds2 = escape.DataSet.load_from_result_file("run0002_reduced.esc.h5")
merged = escape.merge_datasets([ds1, ds2])
print(len(merged.signal)) # combined event count
Converting Between File Formats¶
To convert a zarr dataset to HDF5 (for sharing or archiving):
from escape.storage.dataset import convert_resultsfile
convert_resultsfile("run0042_reduced.esc.zarr", out_type="h5")