Skip to content

Replay a committed chain

Months after you committed a derived result, you need to know whether its recorded recipe still re-derives it before you trust the number in a report.

Replay has no facade verb: reach the plan through sample.core for the same history, and expect a custom facade transformation to stay recorded-only.

This guide assumes: you have finished the tutorial path, including Save, load, and verify and Transform and plot a spectrum, and you know what lineage records.

Every transformation MTRL commits writes down its recipe: the operation name, the exact parameters, and the exact input record. Replay turns that recipe back into action, in three stages you usually run in order. A replay plan lists what a rerun would re-execute, without executing anything. A capability view lists what your installation must supply for the plan to run. A rerun re-executes the recipe, commits a fresh run, and reports how the fresh output digests relate to the recorded ones. All three resolve operations only through your local registry, never through anything stored in the archive.

The example below replays a resample_pchip chain, so it needs the interp extra.

Required install: vector-mtrl[interp]

from pathlib import Path
from tempfile import TemporaryDirectory
import numpy as np
from mtrl import InstrumentRun, MaterialData, Mtrl, Unit
from mtrl.replay import replay_report_to_text
author = Mtrl(sample_id="polymer-film-01")
run = InstrumentRun(run_name="ftir-replicate-01")
axis = np.linspace(2000.0, 3000.0, 101)
content = np.empty(
axis.size,
dtype=[("wavenumber", "<f8"), ("absorbance", "<f8")],
)
content["wavenumber"] = axis
content["absorbance"] = np.exp(-((axis - 2500.0) / 35.0) ** 2)
checkpoint = MaterialData(
content=content,
type="raw",
checkpoint_name="spectrum",
units=Unit.from_raw_map({"wavenumber": "cm^-1", "absorbance": "a.u."}),
)
run.add_checkpoint(checkpoint)
author.add(run)
resampled = author.transform(
run.run_id,
checkpoint.checkpoint_id,
"resample_pchip",
parameters={
"x_field": "wavenumber",
"y_field": "absorbance",
"x_targets": np.linspace(2200.0, 2800.0, 21).tolist(),
},
)
with TemporaryDirectory() as directory:
archive_path = author.save(Path(directory) / "chain.mtrl")
recipient = Mtrl.load(archive_path)
plan = recipient.replay_plan(run.run_id, resampled.checkpoint_id)
print(plan.steps[-1].locally_registered, plan.steps[-1].qualified_identifier)
view = recipient.capability_view(run.run_id, resampled.checkpoint_id)
print(view.missing_distributions)
report = recipient.rerun(run.run_id, resampled.checkpoint_id)
print(replay_report_to_text(report))

The first print shows True mtrl.resample.pchip: the plan’s final step (the target step) names the recorded operation, and your local registry resolves it. The second shows ():

Terminal window
True mtrl.resample.pchip
()
rerun report: run '01a1830d-c489-72b8-a844-3ef315f104ef' checkpoint '01a1830d-c5eb-7397-92da-8a8fe4f371c4'
recorded record '01a1830d-c5ec-7381-b317-72d480dadc62'
fresh run '01a1830d-c676-7202-9533-4520bf7e6b5c' record '01a1830d-c67a-7352-91c1-913a38f69817' revision '01a1830d-c67a-7352-91c1-913b4becf1ed'
step 'mtrl.resample.pchip' relation match recorded_digest 59150c89be3febdf75f5e3e78ee0201762544cae8679d3d3acc68d1c4d3bc16c fresh_digest 59150c89be3febdf75f5e3e78ee0201762544cae8679d3d3acc68d1c4d3bc16c

The identifiers and revision are generated per run, so yours will differ; the shape stays: the plan is replayable with SciPy installed through the interp extra, and the rerun report names the recorded and fresh identities with a match digest relation for the step. The third prints the rerun report: the recorded and fresh identities, one line per step naming the digest relation (match here), one line per stored boundary, and the dependency versions the rerun used. Identifiers are UUIDs, so yours will differ.

The replay plan came first, and it is read-only. recipient.replay_plan(run_id, checkpoint_id) walked the lineage closure of the resampled checkpoint and returned the steps a rerun would re-execute, in order, with the target step last. The locally_registered flag told you whether your registry resolves each recorded identifier, and a rerun refuses any step the flag does not cover. Nothing ran, and nothing was committed.

The capability view came second, and it is also read-only. recipient.capability_view(run_id, checkpoint_id) answered a deployment question: what must this installation supply for the plan to run? Its missing_distributions names the declared distributions the installation lacks, so an empty tuple means every declared dependency is present. That is not the whole compatibility story: a rerun still refuses a plan whose recorded operation contract version does not match the local implementation. On a machine without SciPy, the view would name the gap before you attempted a rerun.

The rerun came third, and it is the only stage that writes. recipient.rerun(run_id, checkpoint_id) re-executed the recipe, committed the fresh records in a new run under a single revision, and returned a report. The report states, per step, the recorded output digest, the fresh output digest, and how they relate: match, differs, or recorded-absent. It adds no tolerance verdict. A difference is reported as a visible fact, and judging whether it matters stays with you.

Notice what the rerun did not touch. The recorded checkpoint is unchanged, and the fresh result lives in its own run with fresh identities. Replay adds evidence to your history; it never rewrites it.