Skip to content

Save, load, and verify

In this lesson you will turn your in-memory measurement into a .mtrl archive: one file you can keep, share and check. By the end you will have saved the polymer film, loaded it back and seen why a check belongs to a particular saved state. It takes about five minutes.

This lesson carries on from Record your first measurement. The block below contains only the new work. It uses the sample you already recorded, so keep that session open or rerun the earlier example first.

Saving a table would keep the numbers, but leave you to explain their units and history elsewhere. sample.save(path) keeps those things together. The resulting archive holds the committed records, their history, units and lineage: the links showing where results came from. It also holds an integrity manifest, a set of digests used to check the file.

Think of saving as packing your lab folder, not taking another measurement. It writes the current history without adding a scientific-result revision. Sample.load(path) opens that folder again through the bounded archive reader and returns a new Sample.

There is one distinction worth watching as you run the example. Before saving, there is no saved archive for MTRL to check. After saving, there is. If you then transform a result, your current work has moved beyond the saved state, even when the transformation only copies the values. An earlier check cannot silently become a check of that new work.

The example uses a temporary directory so you can repeat it without leaving files behind. Inside that directory it saves the first archive, reloads it, commits a copied spectrum and saves the updated history under a second filename.

The call to loaded.one(...) finds the unique active result with the requested name. That gives the newly loaded sample its own handle to the measurement before processing it.

def copy_spectrum(data):
return data.copy()
print("before saving:", sample.verify().hash_status.value)
archive = sample.save("polymer-film-01.mtrl")
checked = sample.verify()
print(checked.format_summary())
loaded = Sample.load(archive)
loaded_raw = loaded.one(name="ftir-replicate-01")
print(f"reloaded sample: {loaded.sample_id}; records: {len(loaded.records)}")
loaded.transform(loaded_raw, copy_spectrum, name="copied-spectrum")
stale = loaded.verify()
print("after transform:", stale.structural_status.value, stale.hash_status.value)
print("earlier report:", checked.hash_status.value)
loaded.save("polymer-film-01-updated.mtrl")
print("after saving again:", loaded.verify().hash_status.value)
before saving: not-checked
structural: valid
hash: consistent
anchor: no-receipt
coverage: full
source closure: not-applicable
evidence availability: complete
issues: 0
reloaded sample: polymer-film-01; records: 1
after transform: not-checked not-checked
earlier report: consistent
after saving again: consistent

Read the report line by line. Before saving, nothing has been checked yet; afterwards, each fact answers its own question. The reloaded sample holds one record, a transform makes the checked facts stale again, and saving the updated state restores a consistent hash.

It is tempting to read that report as a single green tick. Instead, read each line as an answer to a different question. Structural status asks whether the archive is well formed. Hash status asks whether the contents match their recorded digests. Anchor status concerns an independently supplied receipt, while coverage describes how much the manifest covers. Source closure describes the route from derived records to recorded source evidence, and evidence availability tells you whether that evidence is available to inspect.

Those distinctions matter. An internally consistent archive does not, by itself, establish who created it, prove a scientific interpretation or supply an independent historical anchor. Here no-receipt is not another spelling of consistent: it answers a different question, for which we have not supplied a receipt.

You saved and reloaded the same committed history, then added a result to the loaded sample. The saved archive did not yet contain that new revision, so the current state’s structural and hash checks became not-checked. Saving again let MTRL check the updated archive.

Notice that checked did not change when you transformed the spectrum. It remains a report about the evidence checked at the earlier point. That is useful: a report should tell you what was checked, not quietly follow whatever you do next.

Now that you can keep the history, you can add to it. Transform and plot a spectrum picks up the recorded spectrum from lesson 1 again and applies your own scientific function without changing the original. For independent anchors, use verification receipts.