param_io
data.param_io
Resolve a :class:Parameter’s value from its declared provenance.
A parameter says where its value comes from in exactly one of three ways, and the choice is by provenance, never by size:
value: A YAML literal. Returned as-is; codegen inlines it.
source: (+ measure:) WHERE existing bytes live — a curated entity’s IRI, or a path resolved against the declaring spec’s directory. measure selects one array out of a source holding several; its address space is the source’s own (an HDF5/Zarr dataset key, a Network’s per-node measure name).
producer: HOW derived bytes are made — a :class:FunctionCall naming the callable, its arguments, and (via output) which entry to take from a callable returning several named arrays.
Sourced and produced values are never materialised into Parameter.value, so loading a spec stays cheap no matter how large the array is, and a dumper never sees bytes it would try to serialise back into YAML. Resolution happens here, on demand, and the result is cached in this module — the Parameter object is never mutated.
That is deliberate: Parameter appears at 16 nesting sites in the schema, and LinkML always constructs the declared range class, so a tvbo subclass carrying lazy behaviour would need a hand-written re-wrap at every one of them (and would diverge between the dataclass and pydantic flavours). Keeping resolution outside the class means the generated datamodel is untouched and both flavours behave identically.
Functions
| Name | Description |
|---|---|
| clear_cache | Drop every resolved array. Mainly for tests and long-lived processes. |
| is_lazy | True when this parameter’s value is resolved rather than inlined. |
| is_reference | True when an argument value points at an entity rather than being a literal. |
| live_artifacts | (paths, producers) this study still reaches in the produced-constant store. |
| materialise | The (file, key) a backend reads this parameter’s array from. |
| read_artifact | Load a materialised (path, key) artifact back to its array — for codegen probes that need a produced/sourced constant’s shape (e.g. a partition’s group count) without re-running the producer. |
| resolve | This parameter’s value, resolving source/producer on demand. |
| resolve_network_node | Per-node vector for a network.<measure> reference. |
| superseded_artifacts | Artifacts of THIS study’s producers that it no longer reaches, newest first. |
clear_cache
data.param_io.clear_cache()Drop every resolved array. Mainly for tests and long-lived processes.
is_lazy
data.param_io.is_lazy(param)True when this parameter’s value is resolved rather than inlined.
The one rule codegen branches on: a literal is materialised and inlined; anything obtained (source) or derived (producer) is read at run time and must never be embedded in generated source.
is_reference
data.param_io.is_reference(value)True when an argument value points at an entity rather than being a literal.
live_artifacts
data.param_io.live_artifacts(root, cache_dir=None)(paths, producers) this study still reaches in the produced-constant store.
producers is every module.function whose liveness could be decided; a producer whose arguments cannot be resolved is left out of BOTH sets, so its artifacts are never judged dead on the strength of a failure to look at them.
materialise
data.param_io.materialise(param, source_dir=None, context=None, cache_dir=None)The (file, key) a backend reads this parameter’s array from.
Codegen emits this pair rather than the bytes, so a large constant never enters the spec or the generated source and is read at run time instead. Generated modules are exec’d in memory as often as they are written to disk, so the path is absolute (resolved against the declaring spec’s directory) — the same way bids_dir is emitted. A kit stays correct without rewriting code: its emitter rewrites the spec to point at the companion it staged and re-renders, exactly as it already does for network.h5.
A source: parameter already lives in a file, so nothing is written. A producer: parameter is computed once and cached content-addressed under ~/.tvbo/constants, keyed by the producing call — so it survives across runs and every parameter naming that producer shares the one artifact.
Raises for a literal (there is nothing to read; it inlines) or for a parameter with no declared value.
read_artifact
data.param_io.read_artifact(path, key=None)Load a materialised (path, key) artifact back to its array — for codegen probes that need a produced/sourced constant’s shape (e.g. a partition’s group count) without re-running the producer.
resolve
data.param_io.resolve(param, source_dir=None, context=None)This parameter’s value, resolving source/producer on demand.
Returns the literal value untouched when there is one, so a scalar costs nothing. Returns None for a parameter that declares no value at all (a free parameter, say) rather than raising — the caller decides whether that is an error.
context is the owning experiment (or a network); a producer argument naming an entity — positions: network.nodes.position — resolves against it. Resolved arrays are cached and returned read-only: they are shared, and a resolved constant is not the caller’s to modify.
resolve_network_node
data.param_io.resolve_network_node(net, measure)Per-node vector for a network.<measure> reference.
The single definition shared by the producer-argument path (_resolve_ref) and the observation-embedding path (utils.collect_network_node_arrays), so both resolve network.positions / network.instrength / network.labels identically. positions → region centroids (n_nodes, 3); instrength → weighted in-degree matrix('weight').sum(axis=1) (row sum = incoming, the TVB/Koller convention); labels → the region-label string array (Network.node_labels).
Anything else is read as a named per-node attribute, the node-side twin of network.edges.<attr>: first from the nodes’ own parameters (in node order), then from a nodes/<attr> dataset in the companion store. That is what lets a study carry a measured per-region array — a per-node current range, a region size — in the network file and reference it from a spec instead of pasting it into code. Returns None when the measure is unknown or unbuildable.
superseded_artifacts
data.param_io.superseded_artifacts(root, cache_dir=None)Artifacts of THIS study’s producers that it no longer reaches, newest first.
Superseded, not merely old: the content address keys on the producing call and on its module’s source, so an artifact of a producer this study uses, at a digest this study no longer computes, can only be a version left behind by an edit or by a changed argument. Files belonging to producers not seen here are never listed — they may well be another study’s, and this reads one study.