spool_to_xarray
spool_to_xarray(
spool: Spool ,
dim: str = time,
group: str | Sequence[str] | None = None,
tolerance = 1.5,
conflict: Literal[‘drop’, ‘raise’, ‘keep_first’] = raise,
block_size: str | int | None[str, int, None] = None,
)
Convert a spool to a lazy, dask-backed xarray DataTree.
Patches are partitioned exactly as chunk partitions them: one tree node per group of related patches, holding one child node per merged output (segment_0 onward, ordered along dim), each with a dask-backed data variable. Node names follow the spool’s own naming rule — the one its repr’s tracks and a coverage plot’s lanes use. Building the tree reads no patch data — every shape, dtype, and coordinate comes from the spool’s metadata — and computing a selection loads only the source patches it touches.
Parameters
| Parameter | Description |
|---|---|
| spool | The spool to convert. |
| dim | The dimension segments are merged along. |
| group |
Attributes which partition patches into unrelated groups, exactly as chunk uses them. Defaults to the config’s patch_kind_attrs.
|
| tolerance |
The continuity tolerance deciding when a gap splits segments, as in chunk (not the sampling-step grouping tolerance).
|
| conflict |
How attribute conflicts within a segment resolve, as in chunk.
|
| block_size |
The most a single dask block may hold, as a byte count or a string dask parses (“256MiB”, “1GB”). This bounds a bulk read: computing a whole segment asks for one block at a time, so a source patch bigger than this is read in several windows along dim rather than whole. It does not affect a selection, whichreads only what it asks for whatever the blocks are. None takes the configured xarray_block_size (256 MiB by default); zeromakes each source patch one block. A patch whose format cannot hand back a window (see FiberIO.read_array) stays one blockwhatever this says: splitting it would read the file once per block instead of once. |
A selection reads only the samples it names: the arrays are backed by a source spanning each segment, and dask fuses the selection into that source’s own read, which asks each member for its part of the window and no other member at all.
Requires xarray and dask. Coordinates associated with a dimension (rather than defining one) are not carried into the tree, and coordinates are rebuilt from their indexed envelopes, whose numeric values are floats — an integer-valued dimension coordinate comes back as floats.
The merged dimension’s coordinate, when it is a range or segmented, is served lazily by dascore.xarray.index.CoordIndex: its labels are computed on demand from the merged coordinate rather than stored, so an arbitrarily long merged time coordinate costs nothing to build, even when sub-tolerance gaps or slightly different sampling steps leave it segmented rather than one range. Label selection on it answers as Patch.sel does, and reading .values or asking for the pandas index materializes labels on demand. Other dimensions keep materialized labels, which per-channel arrays (gains, offsets) align with. xarray aligns a lazy index only with lazy ones: to combine a segment with arrays indexed along the merged dimension, or reindex it, give it an ordinary index first, which reads all its labels into memory (so select first where possible), e.g. data.drop_indexes("time").set_xindex("time"), or give the other array this index type, other.drop_indexes("time").set_xindex("time", CoordIndex), which reads no lazy labels where the two agree.
A spool with pending value-range selections cannot be converted: the catalog states such bounds as candidacy rather than sample positions, so the arrays cannot be sized without reading. Convert first and select on the tree (e.g. sel(time=...)), or select with samples=True on dimensions, which stays exact. Pending inventory enrichment is likewise refused, since the tree would omit the enriched attributes.