Find a result and fix a mistake
In this lesson a colleague discovers that the film’s sharp peak came from a saturated detector. You will find the measurement and record corrected values without hiding the mistake. By the end you will see both versions and know why the earlier normalisation still points to the original. It takes about ten minutes.
Read Look underneath a result first if checkpoints and record versions are unfamiliar. The example then carries on from the session you built in lessons 1 and 3: it corrects the very spectrum you recorded and normalised.
Find the measurement you mean
Section titled “Find the measurement you mean”Corrections need a deliberate target. A readable name is convenient, but several
measurements can share one, and choosing the first match would hide that ambiguity.
sample.select returns active handles matching every supplied filter exactly;
sample.one asks for exactly one and refuses both missing and ambiguous selections.
Both accept name, run_id, checkpoint_id and record_id.
Here we first count the results named ftir-replicate-01, then narrow the request with
the original run’s identifier. In a larger archive, that extra filter lets you say which
measurement you intend rather than relying on its position in a list.
Correct the values, not the history
Section titled “Correct the values, not the history”Remember the distinction from lesson 4: the checkpoint names the logical result, while
the record names one version. sample.correct(result, data) keeps the active
checkpoint’s identity and commits a fresh record version in one revision. It fixes this
measurement rather than creating an unrelated measurement with a similar name.
The normalisation you committed in lesson 3 now earns its keep: it gives us an earlier analysis to inspect after the correction. The replacement peak below is synthetic, like the original; it stands in for the corrected values you would have accepted after investigating the detector problem.
print(f"matches by name: {len(sample.select(name='ftir-replicate-01'))}")target = sample.one(name="ftir-replicate-01", run_id=raw.run_id)
corrected_data = target.to_numpy()corrected_data["absorbance"] = 0.015 * (axis - 2000.0) / 1000.0corrected_data["absorbance"] += 0.6 * np.exp(-((axis - 2450.0) / 60.0) ** 2)corrected = sample.correct(target, corrected_data)print(f"same checkpoint: {corrected.checkpoint_id == raw.checkpoint_id}")print(f"new record version: {corrected.record_id != raw.record_id}")print(f"selection finds correction: {sample.one(checkpoint_id=raw.checkpoint_id) == corrected}")print(f"matches by original record: {len(sample.select(record_id=raw.record_id))}")print(f"original peak: {round(float(raw.to_numpy()['absorbance'].max()), 4)}")print(f"normalised peak: {float(normalised.to_numpy()['absorbance'].max())}")print(sample.summary())matches by name: 1same checkpoint: Truenew record version: Trueselection finds correction: Truematches by original record: 0original peak: 1.0075normalised peak: 1.0Sample 'polymer-film-01' — 2 active records; 0 active claimsRecords (commit order): [0] 'normalised' 101 values, shape=(101,) fields: wavenumber (cm^-1), absorbance (a.u.) [1] 'ftir-replicate-01' 101 values, shape=(101,) fields: wavenumber (cm^-1), absorbance (a.u.)The three True lines show the same checkpoint, a different record and an active
selection that now finds the correction. The 0 shows that active selection no longer
returns the original version. Yet the old handle still reads its original peak, and the
earlier normalisation still peaks at 1.0.
The summary the example prints recaps the state after the correction: its header counts two active records — the replaced version no longer inflates that count — and the listing shows the normalised result first and the corrected version last, in commit order. The superseded version stays in the stored history. The text carries no generated identifiers, so the same recorded work always prints the same summary.
Decide what needs doing again
Section titled “Decide what needs doing again”That last result can look reassuring until you ask which spectrum was normalised.
The normalised result from lesson 3 still names an analysis of the mistaken input
version. A correction does not retarget descendants or recompute a mean, because doing
so would rewrite what happened.
To analyse the accepted values, call transform again with the returned corrected
handle. The new result will record the corrected input version, leaving the earlier
normalisation available as part of the history. Deciding which analyses need repeating
is your scientific responsibility; MTRL keeps the inputs explicit so you can make it.
What just happened?
Section titled “What just happened?”You selected one active measurement, corrected it and kept a link back to the exact version it replaced. The old handle stayed pinned to its original values while active selection moved to the corrected version. Neither the mistaken measurement nor the normalisation derived from it disappeared.
This is why a correction is more useful than silently editing an array. You can explain what you first believed, what changed and which analyses still depend on the old values.
Where next
Section titled “Where next”One corrected measurement is a useful start. Combine replicates adds two more measurements beside it and records a mean with all three exact inputs.