Skip to content

Samples, runs, and checkpoints

Think of a lab binder. You keep one binder for each physical sample you characterise. Inside the binder, each tab collects everything from one measurement session. Behind each tab sit printed pages: one page for each table of data you chose to save. You can always add new tabs and new pages, and the binder is organised so that you can find any page again, even years later.

MTRL organises your data in exactly this shape, with three levels: the sample container, the instrument run, and the checkpoint.

The application (the Mtrl object) is the binder. One application holds one physical sample, named by its sample identifier, such as polymer-film-01. Everything you commit to that application — every run, every table, every correction — belongs to that sample and travels with it when you save the archive.

The application keeps its runs in a read-only mapping called data. You can look up any run, but you cannot add, replace, or delete entries through the mapping itself. All changes go through the application, so nothing enters the record without being validated and committed. When you read the mapping back, runs appear in commit order: the order in which you recorded them, which a save and reload preserves.

An instrument run (the InstrumentRun object) is one tab in the binder. It groups the metadata and the checkpoints from one measurement session. You give each run a run name, such as ftir-replicate-01, and MTRL generates a separate run identifier for it. A replicate measured the next day gets its own run, named ftir-replicate-02, even if you measured the same sample in the same way.

Names and identifiers are different things, and confusing them trips many new users. A run name is for people, and names are allowed to repeat: application.get_runs_by_name() returns every run that shares one. The run identifier is generated, unique within an application, and it is what identifier-based routes expect — application.get_run() and application.transform() take run.run_id, not the name. If you try to add a second run with an identifier that already exists, MTRL refuses rather than guess which run you meant.

A checkpoint (the MaterialData object) is one printed page: one stable version of measurement data. In the running story, each FTIR run saves one checkpoint with the display name spectrum. A checkpoint carries:

  • its content, the measured values themselves;
  • a stage, one of raw, cleaned, transformed, or aggregated, describing how far the data has progressed from the instrument;
  • a generated identifier that names this logical result;
  • a display name, the human-readable label such as spectrum;
  • an optional source file type, when the data came from an instrument file;
  • its lineage: when it was created, which checkpoint it was derived from, and the transformation or aggregation that produced it.

Raw checkpoints start the story, so they have no parent. A cleaned or transformed checkpoint points back at the checkpoint it came from, and its lineage names the exact versions it was computed from.

One run may hold several checkpoints of the same type or the same name. A run might, for example, contain more than one table labelled spectrum. Display names are for people; they are allowed to repeat. Identifiers are for MTRL, and they never repeat. Whenever you ask for a checkpoint, it is the identifier — not the name or the stage — that selects one exact answer.

This is worth remembering as your binder grows. Names tell you what a page is about. The identifier tells you which page it is.

When you add a run or a checkpoint, MTRL commits it behind a boundary that freezes and protects the values. Read The commit boundary to see what happens at that moment, or revisit Your first record to see these three levels in working code.