erlab.interactive.imagetool.provenance¶
Helpers for recording and replaying actions in ImageTool windows.
The provenance model stores how a tool’s data should be reconstructed from a parent
ImageTool window. A ToolProvenanceSpec answers two questions:
What should be used as the starting point?
Use
full_data()when the derived tool should begin from the parent’s current array exactly as shown to the caller.Use
public_data()when the derived tool should begin from the parent’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.
Which operations should be replayed on that starting point?
Each operation is represented by an immutable
ToolProvenanceOperationsubclass whose serialized fields are safe to persist in JSON.
Adding a new provenance-carrying operation follows the same pattern every time:
Define a new
ToolProvenanceOperationsubclass with a uniqueopdiscriminator literal.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.derivation_entry()so the manager can display a user-facing summary and optional copyable code. ReturnNoneonly when the operation should be omitted from the derivation list and copied provenance code while still being replayed at runtime.Give the class a unique
opdiscriminator literal. Subclasses register themselves automatically so serialized payloads can dispatch to the right model.Export the concrete operation class from this module so runtime call sites can instantiate it directly.
Add tests that cover round-trip validation,
apply(), and derivation text/code, plus any save/load 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(), or selection(), then instantiate
concrete operation models from this module directly.
Functions
|
Compose streamlined display provenance from a live source spec. |
|
Compose canonical full provenance from parent and local lineage. |
|
Decode values produced by |
|
Return a direct input expression for simple replay seeds. |
|
Encode non-JSON provenance values into a JSON-safe representation. |
|
Build a spec that starts from the parent's full current data. |
|
Return |
|
Parse a serialized provenance payload into a validated spec instance. |
|
Build a spec that starts from the parent's restored public data. |
|
|
|
Build a replay-only provenance spec for generated code. |
|
Build a spec that starts from the parent's public selection model. |
|
Parse |
Classes
|
|
|
|
|
|
|
|
|
One user-visible step in a provenance derivation listing. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Base class for immutable provenance operations. |
|
Immutable provenance recipe for rebuilding tool data from a parent ImageTool. |
|
- 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.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']¶
- 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.IselOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['isel']¶
- 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.MaskWithPolygonOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['mask_with_polygon']¶
- 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.QSelOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['qsel']¶
- 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.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.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']¶
- 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.SelOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['sel']¶
- 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.SliceAlongPathOperation(**data)[source]¶
Bases:
ToolProvenanceOperation- op: typing.Literal['slice_along_path']¶
- 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']¶
- 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']¶
- fold: int¶
- axes: ProvenanceHashablePair¶
- center: ProvenanceFloatMapping¶
- 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']¶
- 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 immutable provenance operations.
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, and implementderivation_entry()to describe the step in manager UI.- live_applicable: typing.ClassVar[bool] = True¶
- 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.
datais the array produced by the preceding replay step.parent_datais the original parent source array for the enclosing provenance spec and is available for operations that need parent coordinates, ordering, or other contextual metadata while replaying.This method is used only for live-source provenance paths. Operations that are intended purely for generated replay code should raise an error here and set
live_applicable = False.
- derivation_entry()[source]¶
Return the user-visible derivation entry for this operation.
Return a
DerivationEntrywhen the operation should appear in derivation listings and contribute code toToolProvenanceSpec.derivation_code()orToolProvenanceSpec.display_code().Return
Noneonly for replayed operations that should stay hidden from the derivation UI and copied provenance code. Hidden operations are still kept in the spec and still run throughapply(); they are simply omitted from the rendered derivation list. In the current implementation this is used for internal bookkeeping steps such as a final rename.Use
DerivationEntry(..., code=None)instead when the step should remain visible in the derivation list but code generation should stop and returnNone.
- class erlab.interactive.imagetool.provenance.ToolProvenanceSpec(**data)[source]¶
Bases:
BaseModelImmutable provenance recipe for rebuilding tool data from a parent ImageTool.
Author new specs with
full_data(),public_data(), orselection()plus concrete operation instances from this module. Deserialize saved payloads withparse_tool_provenance_spec().- schema_version: typing.Literal[1]¶
- kind: typing.Literal['full_data', 'public_data', 'selection', 'script']¶
- start_label: str | None¶
- seed_code: str | None¶
- active_name: str | None¶
- 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].
- 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.
- to_replay_spec()[source]¶
Normalize the spec into a replay-only script form.
Replay specs are the canonical, composable form used for derivation metadata, copy-code, save/load, and manager lineage. Live updates from ImageTool use the original non-script spec via
require_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 raw replay lineage 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 lineage.
parentrepresents the replay lineage for the current input data.localrepresents the additional steps performed by the current node. The resulting spec is always a replay-only script spec.
- 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.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.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.script(*operations, start_label, seed_code=None, active_name=None)[source]¶
Build a replay-only provenance spec for generated code.