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:

  1. 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.

  2. Which operations should be replayed on that starting point?

    • Each operation is represented by an immutable ToolProvenanceOperation subclass whose serialized fields are safe to persist in JSON.

Adding a new provenance-carrying operation follows the same pattern every time:

  1. Define a new ToolProvenanceOperation subclass with a unique op discriminator literal.

  2. 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.

  3. 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.

  4. Implement ToolProvenanceOperation.apply() so it transforms a derived array using the recorded parameters. parent_data is provided when the operation needs access to parent coordinates or ordering.

  5. Implement ToolProvenanceOperation.derivation_entry() so the manager can display a user-facing summary and optional copyable code. Return None only when the operation should be omitted from the derivation list and copied provenance code while still being replayed at runtime.

  6. Give the class a unique op discriminator literal. Subclasses register themselves automatically so serialized payloads can dispatch to the right model.

  7. Export the concrete operation class from this module so runtime call sites can instantiate it directly.

  8. 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_display_provenance(parent, ...[, ...])

Compose streamlined display provenance from a live source spec.

compose_full_provenance(parent, local)

Compose canonical full provenance from parent and local lineage.

decode_provenance_value(value)

Decode values produced by encode_provenance_value().

direct_replay_input_name(value)

Return a direct input expression for simple replay seeds.

encode_provenance_value(value)

Encode non-JSON provenance values into a JSON-safe representation.

file_load(*, start_label, seed_code, ...[, ...])

Build structured file-backed provenance for runtime reload.

full_data(*operations)

Build a spec that starts from the parent's full current data.

mark_promoted_1d_source(data)

Return data tagged as originating from a promoted 1D source.

parse_tool_provenance_spec(value)

Parse a serialized provenance payload into a validated spec instance.

public_data(*operations)

Build a spec that starts from the parent's restored public data.

rebase_default_replay_input(code, input_name)

Replace the generic data replay input in generated code.

replay_file_provenance(spec)

Replay structured file provenance without executing generated Python.

require_live_source_spec(value)

script(*operations, start_label[, ...])

Build a replay-only provenance spec for generated code.

selection(*operations)

Build a spec that starts from the parent's public selection model.

to_replay_provenance_spec(value)

Parse value and normalize it into canonical replay provenance.

uses_default_replay_input(code)

Return whether generated replay code refers to the generic data input.

Classes

AffineCoordOperation(**data)

AssignAttrsOperation(**data)

AssignCoord1DOperation(**data)

AssignCoordsOperation(**data)

AssignScalarCoordOperation(**data)

AverageOperation(**data)

CoarsenOperation(**data)

CorrectWithEdgeOperation(**data)

DerivationEntry(label, code[, copyable])

One user-visible step in a provenance derivation listing.

DivideByCoordOperation(**data)

FileLoadSource(**data)

Serializable file origin used by replay-only ImageTool provenance.

FileReplayCall(**data)

Serializable call information used to reload file-backed provenance.

InterpolationOperation(**data)

IselOperation(**data)

MaskWithPolygonOperation(**data)

QSelOperation(**data)

RenameDimsCoordsOperation(**data)

RenameOperation(**data)

ReplayStage(**data)

Structured transformation stage replayed against one parent data array.

RestoreNonuniformDimsOperation(**data)

RotateOperation(**data)

ScriptCodeOperation(**data)

SelOperation(**data)

SelectCoordOperation(**data)

SliceAlongPathOperation(**data)

SortCoordOrderOperation(**data)

SqueezeOperation(**data)

SwapDimsOperation(**data)

SymmetrizeNfoldOperation(**data)

SymmetrizeOperation(**data)

ThinOperation(**data)

ToolProvenanceOperation(**data)

Base class for immutable provenance operations.

ToolProvenanceSpec(**data)

Immutable provenance recipe for rebuilding tool data from a parent ImageTool.

TransposeOperation(**data)

class erlab.interactive.imagetool.provenance.AffineCoordOperation(**data)[source]

Bases: ToolProvenanceOperation

op: typing.Literal['affine_coord']
coord_name: str
scale: float
offset: float
apply(data, *, parent_data)[source]
derivation_entry()[source]
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']
attrs: ProvenanceMapping
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property decoded_values: ndarray
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property decoded_values: ndarray
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property decoded_value: Any
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property coarsen_kwargs: dict[str, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property decoded_edge_fit: Dataset
apply(data, *, parent_data)[source]
derivation_entry()[source]
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: object

One user-visible step in a provenance derivation listing.

label: str
code: str | None
copyable: bool = False
class erlab.interactive.imagetool.provenance.DivideByCoordOperation(**data)[source]

Bases: ToolProvenanceOperation

op: typing.Literal['divide_by_coord']
coord_name: ProvenanceHashable
divisor_code(data_name)[source]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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: BaseModel

Serializable file origin used by replay-only ImageTool 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: BaseModel

Serializable call information used to reload file-backed provenance.

kind: typing.Literal['erlab_loader', 'callable']
target: str
kwargs: dict[str, typing.Any]
selected_index: int
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.InterpolationOperation(**data)[source]

Bases: ToolProvenanceOperation

op: typing.Literal['interpolate']
dim: ProvenanceHashable
values: typing.Any
method: typing.Literal['linear', 'nearest']
property decoded_values: ndarray
apply(data, *, parent_data)[source]
code(data_name, *, assign=None)[source]
derivation_entry()[source]
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']
kwargs: ProvenanceMapping
property decoded_kwargs: dict[Hashable, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property kwargs: dict[str, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property decoded_kwargs: dict[Hashable, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
apply(data, *, parent_data)[source]
derivation_entry()[source]
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: BaseModel

Structured 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].

classmethod from_source_spec(source)[source]
class erlab.interactive.imagetool.provenance.RestoreNonuniformDimsOperation(**data)[source]

Bases: ToolProvenanceOperation

op: typing.Literal['restore_nonuniform_dims']
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property kwargs: dict[str, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property decoded_kwargs: dict[Hashable, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property kwargs: dict[str, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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']
apply(data, *, parent_data)[source]
derivation_entry()[source]
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']
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property kwargs: dict[str, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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']
property kwargs: dict[str, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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
property kwargs: dict[str, Any]
apply(data, *, parent_data)[source]
derivation_entry()[source]
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: BaseModel

Base 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 implement derivation_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.

data is the array produced by the preceding replay step. parent_data is 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 DerivationEntry when the operation should appear in derivation listings and contribute code to ToolProvenanceSpec.derivation_code() or ToolProvenanceSpec.display_code().

Return None only 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 through apply(); 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 return None.

class erlab.interactive.imagetool.provenance.ToolProvenanceSpec(**data)[source]

Bases: BaseModel

Immutable provenance recipe for rebuilding tool data from a parent ImageTool.

Author new specs with full_data(), public_data(), or selection() plus concrete operation instances from this module. Deserialize saved payloads with parse_tool_provenance_spec().

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, ...]
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].

property is_live_source: bool
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.

drop_trailing_rename()[source]
append_replacement_operations(*operations)[source]

Replace a final rename, if present, then append new operation instances.

append_final_rename(name)[source]
append_replay_stage(source)[source]

Append one live-source transformation stage to file provenance.

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. Structured file provenance remains structured so runtime reloads can replay typed operations without exec. Live updates from ImageTool use the original non-script spec via require_live_source_spec().

apply(parent_data)[source]
derivation_entries()[source]
derivation_code()[source]
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().

display_code(*, parent_data=None)[source]

Return streamlined replay code for UI and clipboard actions.

The display path preserves exact live-source behavior while omitting user-facing no-op and normalization steps from copied provenance code.

class erlab.interactive.imagetool.provenance.TransposeOperation(**data)[source]

Bases: ToolProvenanceOperation

op: typing.Literal['transpose']
dims: NullableProvenanceHashableTuple
apply(data, *, parent_data)[source]
derivation_entry()[source]
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.

parent represents the replay lineage for the current input data. local represents 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 = data continue to use derived so 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 data tagged 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 ToolProvenanceSpec instances 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 data replay 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.replay_file_provenance(spec)[source]

Replay structured file provenance without executing generated Python.

erlab.interactive.imagetool.provenance.require_live_source_spec(value)[source]
erlab.interactive.imagetool.provenance.script(*operations, start_label, seed_code=None, active_name=None, file_load_source=None)[source]

Build a replay-only provenance spec for generated code.

erlab.interactive.imagetool.provenance.selection(*operations)[source]

Build a spec that starts from the parent’s public selection model.

erlab.interactive.imagetool.provenance.to_replay_provenance_spec(value)[source]

Parse value and normalize it into canonical replay provenance.

erlab.interactive.imagetool.provenance.uses_default_replay_input(code)[source]

Return whether generated replay code refers to the generic data input.