erlab.interactive.imagetool.provenance¶
Helpers for recording, displaying, and replaying ImageTool provenance.
The saved provenance model stores enough history to explain or rebuild an ImageTool
without persisting runtime-only replay state. ToolProvenanceSpec has a small
set of source forms:
Live single-parent source specs.
Use
full_data()when the derived tool should begin from the parent ImageTool’s current array exactly as shown to the caller.Use
public_data()when the derived tool should begin from the parent ImageTool’s public data model, including restoration of non-uniform dimensions.Use
selection()when the derived tool should begin from the public ImageTool selection model, including restoration of non-uniform dimensions.
Durable replay specs.
Use
file_load()for data that can be reloaded from a recorded file source and replayed through structuredReplayStageoperations.Use
script()for console-derived and other multi-input results. Script specs may reference any number ofScriptInputrecords. Each input stores an immutable replay name, a historical display label, optional live manager node identity andnode_snapshot_token, and an optional nested provenance snapshot.
Each transformation is represented by an immutable
ToolProvenanceOperation subclass whose serialized fields are safe to persist
in JSON. Persisted specs are the source of truth for workspace save/load. Runtime
reload, copied code, and shared-input deduplication compile those specs on demand
through erlab.interactive.imagetool._replay_graph; the graph itself is not
saved.
Manager children opened from an ImageTool cursor or bin selection do not keep the
first generated qsel arguments as their refresh state. They store the selected
parent indices in ImageToolSelectionSourceBinding and rebuild qsel or
isel operations from the current parent data each time they refresh.
Adding a new provenance-carrying operation follows the same pattern every time:
Define a new
ToolProvenanceOperationsubclass with a uniqueopdiscriminator literal. Subclasses register themselves automatically so serialized payloads can dispatch to the right model.Prefer the annotated provenance field aliases defined in this module for hashable dimension identifiers and dim-keyed mappings so runtime values stay decoded while JSON dumps remain lossless.
If the operation needs already-encoded payloads such as xarray objects or array-like vertex data, validate them with
ToolProvenanceOperation._validate_encoded_field()and expose decoded convenience properties for runtime use.Implement
ToolProvenanceOperation.apply()so it transforms a derived array using the recorded parameters.parent_datais provided when the operation needs access to parent coordinates or ordering.Implement
ToolProvenanceOperation.expression_code()andToolProvenanceOperation.derivation_label()so copied code and manager derivation entries come from the same operation metadata. OverrideToolProvenanceOperation.derivation_entry()only when the operation is not a structured transform, such as free-form script code.If the operation maps cleanly from manager-console calls, declare
ToolProvenanceOperation.console_patternsor implementToolProvenanceOperation.from_console_call(). Unsupported or ambiguous console calls should returnNoneso they remain valid script provenance instead of being recorded as lossy structured operations.Make generated code executable in the replay namespace. Use the literal helpers in this module for persisted values, and make
expression_codehonor the input name it is given. The basereplay_codewrapper assigns the caller-selected output name.Export the operation class from this module so runtime call sites can instantiate it directly.
Add tests that cover round-trip validation,
apply(), derivation text/code, console matching when supported, and any save/load or reload path that persists the new operation.
Parsing of serialized payloads happens only through parse_tool_provenance_spec()
and parse_tool_provenance_operation(). Runtime authoring code should create specs
with full_data(), public_data(), selection(), file_load(), or
script(), then instantiate operation models from this module directly.
Functions
|
Compose streamlined display provenance from a live source spec. |
|
Compose canonical full provenance from parent and local provenance. |
|
Decode values produced by |
|
Return a direct input expression for simple replay seeds. |
|
Encode non-JSON provenance values into a JSON-safe representation. |
|
Build structured file-backed provenance for runtime reload. |
|
Build a spec that starts from the parent's full current data. |
|
Return |
|
Return chained expression code for structured operations. |
|
Parse a serialized provenance payload into a validated spec instance. |
|
Build a spec that starts from the parent's restored public data. |
|
Replace the generic |
|
Return |
|
Replay structured file provenance without executing generated Python. |
|
Execute script provenance from already resolved input arrays. |
|
|
|
Build script provenance from code, structured steps, and named inputs. |
|
Return all live manager dependency references stored in script inputs. |
Return whether script provenance is self-contained enough to execute. |
|
|
Build a spec that starts from the parent's public selection model. |
|
Parse |
Return whether generated replay code refers to the generic |
Classes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
One user-visible step in a provenance derivation listing. |
|
|
|
Serializable selection of one displayable array from a loaded file object. |
|
Serializable file origin used by saved file-backed provenance. |
|
Serializable call information used to reload file-backed provenance. |
|
|
|
ImageTool selection state stored for manager child refreshes. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Structured transformation stage replayed against one parent data array. |
|
|
|
|
|
|
|
Named input captured by script or multi-tool provenance. |
|
Live manager dependency captured by a script input. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Base class for typed operations stored in |
|
Saved provenance recipe for ImageTool data. |
|
- class erlab.interactive.imagetool.provenance.AffineCoordOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['affine_coord']¶
- coord_name: str¶
- scale: float¶
- offset: float¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.AssignAttrsOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['assign_attrs']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- attrs: ProvenanceMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.AssignCoord1DOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['assign_coord_1d']¶
- coord_name: ProvenanceHashable¶
- dim: ProvenanceHashable¶
- values: typing.Any¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.AssignCoordsOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['assign_coords']¶
- coord_name: str¶
- values: typing.Any¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.AssignScalarCoordOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['assign_scalar_coord']¶
- coord_name: ProvenanceHashable¶
- value: typing.Any¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.AverageOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['average']¶
- dims: ProvenanceHashableTuple¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.CoarsenOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['coarsen']¶
- dim: ProvenanceIntMapping¶
- boundary: str¶
- side: str¶
- coord_func: str¶
- reducer: str¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.CorrectWithEdgeOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['correct_with_edge']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- edge_fit: typing.Any¶
- shift_coords: bool¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.DerivationEntry(label, code, copyable=False)[source]¶
Bases:
objectOne user-visible step in a provenance derivation listing.
- class erlab.interactive.imagetool.provenance.DivideByCoordOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['divide_by_coord']¶
- coord_name: ProvenanceHashable¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.FileDataSelection(**data)[source]¶
Bases:
BaseModelSerializable selection of one displayable array from a loaded file object.
New provenance stores stable Dataset variable names and DataTree data paths instead of the positional parsed-array index used by older workspaces.
- kind: typing.Literal['dataarray', 'dataset_variable', 'datatree_path', 'parsed_index']¶
- value: typing.Any¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.FileLoadSource(**data)[source]¶
Bases:
BaseModelSerializable file origin used by saved file-backed provenance.
- path: str¶
- loader_label: str¶
- loader_text: str¶
- kwargs_text: str¶
- replay_call: FileReplayCall | None¶
- load_code: str | None¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.FileReplayCall(**data)[source]¶
Bases:
BaseModelSerializable call information used to reload file-backed provenance.
- kind: typing.Literal['erlab_loader', 'callable']¶
- target: str¶
- kwargs: dict[str, typing.Any]¶
- selection: FileDataSelection¶
- cast_float64: bool¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.GaussianFilterOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['gaussian_filter']¶
- sigma: ProvenanceFloatMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.ImageToolSelectionSourceBinding(**data)[source]¶
Bases:
BaseModelImageTool selection state stored for manager child refreshes.
Stores the parent dimension indices selected in an ImageTool plot. When a child refreshes after parent coordinates change,
materialize()rebuildsqseloriseloperations from the current parent data so the child follows the same cursor or bin position instead of old coordinate labels.- Parameters:
selection_mode (Literal['qsel', 'isel']) – Use
"qsel"when selected hidden dimensions should be represented by current coordinate values, or"isel"when they must stay index-based.selection_indexers (Annotated[dict[Hashable, Any], BeforeValidator(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._coerce_hashable_mapping_field, json_schema_input_type=PydanticUndefined), PlainSerializer(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._json_encode_field, return_type=PydanticUndefined, when_used=json)]) – Parent dimension names mapped to integer indices or index slices from the cursor or bin selection.
selection_binned_dims (Annotated[tuple[Hashable, ...], BeforeValidator(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._coerce_hashable_tuple_field, json_schema_input_type=PydanticUndefined), PlainSerializer(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._json_encode_field, return_type=PydanticUndefined, when_used=json)]) – Dimensions in
selection_indexerswhose slices should becomeqselcenter and width arguments.crop_sel_indexers (Annotated[dict[Hashable, Any], BeforeValidator(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._coerce_hashable_mapping_field, json_schema_input_type=PydanticUndefined), PlainSerializer(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._json_encode_field, return_type=PydanticUndefined, when_used=json)]) – Index slice selections from visible axes that should be represented by current coordinate values during refresh.
crop_isel_indexers (Annotated[dict[Hashable, Any], BeforeValidator(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._coerce_hashable_mapping_field, json_schema_input_type=PydanticUndefined), PlainSerializer(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._json_encode_field, return_type=PydanticUndefined, when_used=json)]) – Index slice selections from visible non-uniform axes.
transpose_dims (Annotated[tuple[Hashable, ...] | None, BeforeValidator(func=~erlab.interactive.imagetool.provenance._coerce_nullable_hashable_tuple_field, json_schema_input_type=PydanticUndefined), PlainSerializer(func=~erlab.interactive.imagetool.provenance.ToolProvenanceOperation._json_encode_field, return_type=PydanticUndefined, when_used=json)]) – Dimension order to apply after selection, if the opened tool expects a transposed input.
squeeze (bool) – Whether to squeeze singleton dimensions after selection.
- schema_version: typing.Literal[1]¶
- kind: typing.Literal['imagetool_selection']¶
- selection_mode: typing.Literal['qsel', 'isel']¶
- selection_indexers: ProvenanceMapping¶
- selection_binned_dims: ProvenanceHashableTuple¶
- crop_sel_indexers: ProvenanceMapping¶
- crop_isel_indexers: ProvenanceMapping¶
- transpose_dims: NullableProvenanceHashableTuple¶
- squeeze: bool¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- materialize(parent_data)[source]¶
Build a source spec for the current parent data.
- Parameters:
parent_data (
DataArray) – Current data from the parent ImageTool.- Returns:
ToolProvenanceSpec– Source spec whoseqsel,isel, andseloperations match this binding onparent_data.- Return type:
- class erlab.interactive.imagetool.provenance.InterpolationOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['interpolate']¶
- dim: ProvenanceHashable¶
- values: typing.Any¶
- method: typing.Literal['linear', 'nearest']¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.IselOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['isel']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- kwargs: ProvenanceMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.LeadingEdgeOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['leading_edge']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- fraction: float¶
- dim: ProvenanceHashable¶
- direction: typing.Literal['positive', 'negative']¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.MaskWithPolygonOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['mask_with_polygon']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- vertices: typing.Any¶
- dims: ProvenanceHashableTuple¶
- invert: bool¶
- drop: bool¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.NormalizeOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['normalize']¶
- dims: ProvenanceHashableTuple¶
- mode: typing.Literal['area', 'minmax', 'min', 'min_area']¶
- denominator_rtol: float¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.QSelAggregationOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['qsel_aggregate']¶
- dims: ProvenanceHashableTuple¶
- func: typing.Literal['mean', 'min', 'max', 'sum']¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.QSelOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['qsel']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- kwargs: ProvenanceMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.RenameDimsCoordsOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['rename_dims_coords']¶
- mapping: ProvenanceHashableMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.RenameOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['rename']¶
- name: str¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.ReplayStage(**data)[source]¶
Bases:
BaseModelStructured transformation stage replayed against one parent data array.
- source_kind: typing.Literal['full_data', 'public_data', 'selection']¶
- operations: tuple[pydantic.SerializeAsAny[ToolProvenanceOperation], ...]¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.RestoreNonuniformDimsOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['restore_nonuniform_dims']¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.RotateOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['rotate']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- angle: float¶
- axes: ProvenanceHashablePair¶
- center: tuple[float, float]¶
- reshape: bool¶
- order: int¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.ScriptCodeOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['script_code']¶
- label: str¶
- code: str | None¶
- copyable: bool¶
- live_applicable: typing.ClassVar[bool] = False¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.ScriptInput(**data)[source]¶
Bases:
BaseModelNamed input captured by script or multi-tool provenance.
nameis the immutable replay variable,labelis the historical display label,node_uidandnode_snapshot_tokenidentify the live manager input that was used, andprovenance_specstores the historical replay source used when that live input is unavailable.- name: str¶
- label: str¶
- node_uid: str | None¶
- node_snapshot_token: str | None¶
- provenance_spec: dict[str, typing.Any] | None¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.ScriptInputDependencyRef(name, label, node_uid, node_snapshot_token=None)[source]¶
Bases:
objectLive manager dependency captured by a script input.
- class erlab.interactive.imagetool.provenance.SelOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['sel']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- kwargs: ProvenanceMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.SelectCoordOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['select_coord']¶
- coord_name: ProvenanceHashable¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.SliceAlongPathOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['slice_along_path']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- vertices: ProvenanceFloatSequenceMapping¶
- step_size: float¶
- dim_name: str¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.SortCoordOrderOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['sort_coord_order']¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.SqueezeOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['squeeze']¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.SwapDimsOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['swap_dims']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- mapping: ProvenanceHashableMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.SymmetrizeNfoldOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['symmetrize_nfold']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- fold: int¶
- axes: ProvenanceHashablePair¶
- center: typing.Any¶
- reshape: bool¶
- order: int¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.SymmetrizeOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['symmetrize']¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = (<erlab.interactive.imagetool.provenance.ConsoleOperationPattern object>,)¶
- dim: ProvenanceHashable¶
- center: float¶
- subtract: bool¶
- mode: typing.Literal['full', 'valid']¶
- part: typing.Literal['both', 'below', 'above']¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.ThinOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['thin']¶
- mode: typing.Literal['global', 'per_dim']¶
- factor: int | None¶
- factors: ProvenanceIntMapping¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- class erlab.interactive.imagetool.provenance.ToolProvenanceOperation(**data)[source]¶
Bases:
BaseModelBase class for typed operations stored in
ToolProvenanceSpec.New operations should keep runtime fields in their decoded Python form, prefer the annotated provenance field aliases in this module for lossless JSON serialization, implement
apply()to replay the transformation, implementexpression_code()to emit the public Python expression for the same transformation, and implementderivation_label()to describe the step in manager UI.Operation instances store the exact arguments used by live refresh, replay graph execution, copied code, and derivation display. If a public console call maps exactly to an operation, expose it with
console_patternsorfrom_console_call(); ambiguous calls should returnNoneso script provenance records the original code instead.- live_applicable: typing.ClassVar[bool] = True¶
- console_patterns: typing.ClassVar[tuple[ConsoleOperationPattern, ...]] = ()¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- apply(data, *, parent_data)[source]¶
Apply this operation to the current derived array.
Subclasses that participate in live refresh or executable provenance replay should reimplement this method. The implementation must be deterministic for the operation’s stored model fields and must not mutate
dataorparent_datain place.- Parameters:
- Returns:
xarray.DataArray– Array after this operation has been applied.- Return type:
Notes
Operations that only emit generated code should set
live_applicable = Falseand raise from this method.
- derivation_entry()[source]¶
Return the user-visible derivation entry for this operation.
Structured transform subclasses should normally reimplement
derivation_label()andexpression_code()instead of overriding this method. Override this method only for operations whose display entry cannot be represented as a label plus parameterized operation code, such as stored free-form script code.- Returns:
DerivationEntry– Label, replay code, and copyability flag shown in derivation UI and used by legacy derivation-code paths.- Return type:
Notes
The base implementation keeps the legacy
derivedreplay contract while letting concrete operations emit expression code for any input variable.Use
DerivationEntry(..., code=None)instead when the step should remain visible in the derivation list but code generation should stop and returnNone.
- derivation_label()[source]¶
Return the derivation-list label for this operation.
Subclasses should reimplement this for every structured operation that uses the base
derivation_entry()implementation.
- expression_code(input_name, *, source_name=None)[source]¶
Return a Python expression applying this operation to an input name.
Subclasses should reimplement this for every structured operation that can be represented as ordinary user-facing Python code. The emitted expression should be complete, public-API-based, and free of assignment to hardcoded temporary names.
- Parameters:
input_name (
str) – Python expression or identifier for the array produced by the previous replay step. Use this exact value as the operation receiver/input instead of assuming a variable name such asderived.source_name (
str|None, default:None) – Python expression or identifier for the original public input array for the enclosing replay sequence. Operations that need parent/source context, such as coordinate-order restoration, should use this name for that context. Operations that only transforminput_namemay ignore it.
- Returns:
str– Python expression that evaluates to the transformed DataArray.- Return type:
- replay_code(input_name, *, output_name=None, source_name=None)[source]¶
Return replay code for this operation with caller-selected names.
This method usually should not be reimplemented by subclasses. Implement
expression_code()instead so replay graph emission, dialog copy code, and derivation entries all share the same operation expression.- Parameters:
input_name (
str) – Python expression or identifier for the array produced by the previous replay step.output_name (
str|None, default:None) – Variable name to assign the transformed value to. IfNone, return only the expression fromexpression_code().source_name (
str|None, default:None) – Python expression or identifier for the original public input array for the enclosing replay sequence. Passed through toexpression_code().
- Returns:
str– Either an assignment statement whenoutput_nameis provided, or a bare expression when it isNone.- Return type:
- classmethod from_console_call(call)[source]¶
Build an operation from a normalized manager-console call.
Subclasses should reimplement this when a console call maps cleanly to the operation but cannot be expressed with declarative
console_patternsalone. ReturnNonefor unsupported, ambiguous, or lossy calls so the original console code remains recorded as script provenance.- Parameters:
call (
ConsoleCall) – Normalized descriptor for the function, method, or accessor call observed by the ImageTool manager console, including unwrapped arguments, keyword arguments, display code, and receiver data when available.- Returns:
ToolProvenanceOperationorNone– Operation instance when the call is exactly representable by this operation class; otherwiseNone.- Return type:
ToolProvenanceOperation | None
- class erlab.interactive.imagetool.provenance.ToolProvenanceSpec(**data)[source]¶
Bases:
BaseModelSaved provenance recipe for ImageTool data.
Live child-tool refresh uses single-parent specs from
full_data(),public_data(), orselection(). Durable reload and copied code usefileandscriptspecs, including multi-inputscript_inputsfor console or UI actions that combine several ImageTools. Deserialize saved payloads withparse_tool_provenance_spec().A spec records exact operation arguments for live refresh, runtime replay, copied code, and derivation display. Manager children opened from ImageTool cursor or bin selections should keep
ImageToolSelectionSourceBindingas their refresh state; that binding builds a spec before refresh so edited parent coordinates are used.- schema_version: typing.Literal[2]¶
- kind: typing.Literal['full_data', 'public_data', 'selection', 'script', 'file']¶
- start_label: str | None¶
- seed_code: str | None¶
- active_name: str | None¶
- operations: tuple[pydantic.SerializeAsAny[ToolProvenanceOperation], ...]¶
- file_load_source: FileLoadSource | None¶
- replay_stages: tuple[ReplayStage, ...]¶
- script_inputs: tuple[ScriptInput, ...]¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- append_operations(*operations)[source]¶
Append operation instances to the spec.
Runtime code should pass operation instances from this module. Saved mappings should be normalized with
parse_tool_provenance_spec()before calling this method.
- append_replacement_operations(*operations)[source]¶
Replace a final rename, if present, then append new operation instances.
- append_replay_stage(source)[source]¶
Append one live-source transformation stage to file provenance.
- to_replay_spec()[source]¶
Return the durable replay form for this spec.
Replay specs are the canonical, composable form used for derivation metadata, copied code, workspace save/load, and manager dependency status. Structured file provenance remains structured so runtime reloads can replay typed operations without
exec. Live ImageTool refresh uses the original single-parent spec viarequire_live_source_spec().
- display_entries(*, parent_data=None)[source]¶
Return streamlined derivation entries for UI and copy-code output.
The display path hides internal ImageTool normalization steps while keeping the recorded replay steps available through
derivation_entries().
- class erlab.interactive.imagetool.provenance.TransposeOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['transpose']¶
- dims: NullableProvenanceHashableTuple¶
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}¶
Configuration for the model, should be a dictionary conforming to [
ConfigDict][pydantic.config.ConfigDict].
- erlab.interactive.imagetool.provenance.compose_display_provenance(parent, source_spec, *, parent_data=None)[source]¶
Compose streamlined display provenance from a live source spec.
- erlab.interactive.imagetool.provenance.compose_full_provenance(parent, local)[source]¶
Compose canonical full provenance from parent and local provenance.
parentrepresents the replay provenance for the current input data.localrepresents the additional steps performed by the current node. File-backed parents remain structured when composed with live-source specs so runtime reloads can avoid executing generated Python.
- erlab.interactive.imagetool.provenance.decode_provenance_value(value)[source]¶
Decode values produced by
encode_provenance_value().
- erlab.interactive.imagetool.provenance.direct_replay_input_name(value)[source]¶
Return a direct input expression for simple replay seeds.
This only applies to non-default single-line seeds such as watched variables. Generic replay aliases like
derived = datacontinue to usederivedso existing non-watched code generation remains stable.
- erlab.interactive.imagetool.provenance.encode_provenance_value(value)[source]¶
Encode non-JSON provenance values into a JSON-safe representation.
- erlab.interactive.imagetool.provenance.file_load(*, start_label, seed_code, file_load_source, active_name='derived', replay_stages=())[source]¶
Build structured file-backed provenance for runtime reload.
- erlab.interactive.imagetool.provenance.full_data(*operations)[source]¶
Build a spec that starts from the parent’s full current data.
- erlab.interactive.imagetool.provenance.mark_promoted_1d_source(data)[source]¶
Return
datatagged as originating from a promoted 1D source.
- erlab.interactive.imagetool.provenance.operations_expression_code(operations, input_name, *, source_name=None)[source]¶
Return chained expression code for structured operations.
source_nameis the public/source array name passed to operations that need context beyond the transformed input, such as coordinate-order restoration.
- erlab.interactive.imagetool.provenance.parse_tool_provenance_spec(value)[source]¶
Parse a serialized provenance payload into a validated spec instance.
This is the deserialize boundary for saved tool and workspace metadata. Runtime authoring code should pass
ToolProvenanceSpecinstances directly.
- erlab.interactive.imagetool.provenance.public_data(*operations)[source]¶
Build a spec that starts from the parent’s restored public data.
- erlab.interactive.imagetool.provenance.rebase_default_replay_input(code, input_name)[source]¶
Replace the generic
datareplay input in generated code.Manager clipboard actions use this when a concrete source is known, such as a watched variable, a load snippet target, or a user-provided variable name.
- erlab.interactive.imagetool.provenance.rebase_script_input_node_uids(value, uid_map)[source]¶
Return
valuewith script input node UIDs remapped recursively.
- erlab.interactive.imagetool.provenance.replay_file_provenance(spec, *, cache=None)[source]¶
Replay structured file provenance without executing generated Python.
- erlab.interactive.imagetool.provenance.replay_script_provenance(spec, inputs)[source]¶
Execute script provenance from already resolved input arrays.
The caller is responsible for trust and input resolution. This function only validates the provenance shape, compiles it through the replay graph, and returns the replayed
xarray.DataArray.
- erlab.interactive.imagetool.provenance.script(*operations, start_label, seed_code=None, active_name=None, file_load_source=None, script_inputs=())[source]¶
Build script provenance from code, structured steps, and named inputs.
- erlab.interactive.imagetool.provenance.script_input_dependency_refs(value)[source]¶
Return all live manager dependency references stored in script inputs.
- erlab.interactive.imagetool.provenance.script_provenance_replayable(spec)[source]¶
Return whether script provenance is self-contained enough to execute.
This checks the saved code and structured operations. It does not mean live manager inputs are present; callers still need to resolve
script_inputs.
- erlab.interactive.imagetool.provenance.selection(*operations)[source]¶
Build a spec that starts from the parent’s public selection model.