instruments · curveset · 2 real calibrations, no model calls

The line they published, and the lines that fit.

A calibration is run forwards — known standards in, response out — and used backwards, response in, unknown out. Everyone reports the backwards number by fitting a curve and inverting it. The fit is an assumption, and it is never priced. This computes what the standards allow instead, under assumptions stated one at a time, and puts the published answer inside it.

the grammar this page is drawn in

Every mark says what it is standing on.

The envelope is decided: it is what the standards and the stated assumption force, in closed form, and it is drawn solid. The published curve is chosen — an argmin of a fitting criterion over a family nobody derived from the data — and it is drawn dotted. Where a reading is over range and no admissible curve bounds it, there is no mark at all and the void is drawn, because "over range" is a fact about the ladder rather than a number to interpolate.

decided
exact arithmetic backs it
computed
float; nothing decided it
chosen
one member of a set the data admits
refused
no mark — the void is drawn

Standing is not confidence. A dotted line here is not less precise — it is often far more precise, which is exactly the problem. It is precise because something other than the data chose it. Width is drawn separately, as an extent, so the two never collapse into one channel.

the instrument

Drag the assumption. Watch the answer pay for it.

The dial runs from monotone only — more analyte, more signal, which nobody disputes about a calibration and nobody uses either — through a local smoothness claim, to join the dots, which is linear interpolation between neighbouring standards and what a great many laboratories do by hand. The parametric fit sits past the end of the dial. The gap between the last rung and the fit is what the functional form is buying.

a load cell, calibrated at NIST20 standards · error budget measured · k = 2

NIST Statistical Reference Datasets — Pontius. 40 observations, 20 loads applied twice. Each load was applied twice, so repeatability is measured rather than asserted: pooled s = 2.147e-4.

0.0M0.6M1.3M1.9M2.5M3.2M-0.09540.5221.141.762.37 a measured deflection of 1.15reported ±568 lb — narrower than the dot drawing it load (lb) deflection
monotone only
what the standards allow
1,500,000 – 1,650,000
decided in closed form from the standards and the stated assumption — no optimiser, no sampling.
what was reported
1,580,781 ± 568.3
NIST certified quadratic. One member of the set on the left, chosen by a fitting criterion.
the price of the form
132.0×
how much wider the honest answer is than the reported ±, at this assumption.
10×25×50×100× monotone only132×wander ≤ ±200%88×wander ≤ ±100%67×wander ≤ ±50%45×wander ≤ ±25%27×wander ≤ ±10%13×wander ≤ ±5%7.1×wander ≤ ±2%3.5×join the dots1.0× vs the reported ±
a rat IL-6 assay, calibrated on a dilution ladder8 standards · error budget stated · k = 2

Published example standard curve, rat IL-6 sandwich ELISA (Abbexa abx155737). Absorbance at 450 nm, zero standard included. There are no replicates, so the error budget is an assertion — 8% CV with a 0.01 OD floor — and it stays a control on this page rather than a constant buried in the code.

101001.563.126.2512.525501000.01080.8661.722.583.43 a measured absorbance of 0.9reported ±0.797 pg/mL concentration (pg/mL), log scale absorbance (OD)
monotone only
what the standards allow
12.50 – 25.00
decided in closed form from the standards and the stated assumption — no optimiser, no sampling.
what was reported
18.37 ± 0.7966
four-parameter logistic. One member of the set on the left, chosen by a fitting criterion.
the price of the form
7.8×
how much wider the honest answer is than the reported ±, at this assumption.
monotone only7.8×wander ≤ ±200%7.0×wander ≤ ±100%6.5×wander ≤ ±50%6.1×wander ≤ ±25%5.7×wander ≤ ±10%4.5×wander ≤ ±5%4.1×wander ≤ ±2%3.8×join the dots3.6× vs the reported ±
the result, and it goes both ways

Two calibrations, two opposite verdicts.

132×the load cell, assuming only monotone

The honest interval is 150,000 lb wide — exactly the ladder spacing. Without a functional form you can say which two calibration points you are between, and nothing finer.

1.0×and joining the dots matches NIST

On a fine ladder with small noise the functional form buys nothing: linear interpolation lands on the reported precision. That precision was earned by the experiment, not by the model.

3.6×the assay, even joining the dots

The opposite conclusion. The tightest claim available without a functional form is still 3.6 times wider than the four-parameter fit reports. On a coarse ladder the model is doing the work.

That pair is the point. The method does not say everyone is overconfident. It says you can tell which case you are in, and by how much — and the two cases look identical until somebody computes the set. Both reports are competent, both are standard practice, and one of them is carried almost entirely by a choice of curve.

the mathematics, and why there is no optimiser

The envelope is closed form

A curve is admissible when it passes within the stated error of every standard and its slope stays in [m, M]. Every standard then bounds the curve from both sides through the slope limits, so the extreme admissible curves are a minimum and a maximum of straight lines:

U(x) = min i [ hi i + (x ≥ x i ?  M(x − x i) : −m(x i − x)) ]
L(x) = max i [ lo i + (x ≥ x i ?  m(x − x i) : −M(x i − x)) ]

Both are nondecreasing, so reading backwards is a bisection rather than a search, and it is exact to machine precision. No linear program, no sampling, nothing to tune.

A global slope band is the wrong assertion for a curve that bends. On the assay the secants between adjacent standards already span sixteen-fold, so "the slope lies between the smallest and largest secant" constrains nothing and tightening it changes nothing. The claim people actually make is local: between two adjacent standards the response does not wander far from the line joining them. At t = 0 that is linear interpolation. The bound used is an outer one — each endpoint taken with its own error bar independently — so it is conservative, wider than the truth and never narrower, which is the direction an argument like this has to err in.

The page runs the file the tests run. envelope.js is inlined verbatim behind a four-line require shim, so the curve the slider draws comes out of the same 8399 bytes that 24 tests exercise, and out of the same function that rendered this page on disk.

what this does not claim
  • It says nothing about whether either report is wrong. Both are competent and both are standard practice.
  • The error budget on the assay is asserted, not measured — there are no replicates — so that panel prices an assumption using another assumption, and says so.
  • The local bound is outer, so the intervals are conservative. A tighter envelope would only make the argument stronger.
  • Nothing here is certified in this repository's sense. It is exact arithmetic on floats, on the side of the site where nothing is gated.
assumingfromtowidthvs reported ±
a load cell, calibrated at NIST — reading 1.15
monotone only1,500,0001,650,000150,000 lb132×
wander ≤ ±200%1,526,7591,627,154100,396 lb88×
wander ≤ ±100%1,540,1381,615,73275,593 lb67×
wander ≤ ±50%1,553,5171,604,30950,791 lb45×
wander ≤ ±25%1,564,2211,595,17130,950 lb27×
wander ≤ ±10%1,572,9781,587,69414,715 lb13×
wander ≤ ±5%1,576,6071,584,7278120 lb7.1×
wander ≤ ±2%1,578,8531,582,8073954 lb3.5×
join the dots1,580,2761,581,4631187 lb1.0×
a rat IL-6 assay, calibrated on a dilution ladder — reading 0.9
monotone only12.5025.0012.50 pg/mL7.8×
wander ≤ ±200%13.1924.2811.09 pg/mL7.0×
wander ≤ ±100%13.5523.9310.37 pg/mL6.5×
wander ≤ ±50%13.9323.589.657 pg/mL6.1×
wander ≤ ±25%14.2323.319.079 pg/mL5.7×
wander ≤ ±10%14.4821.667.175 pg/mL4.5×
wander ≤ ±5%14.5821.046.456 pg/mL4.1×
wander ≤ ±2%14.6520.716.057 pg/mL3.8×
join the dots14.7020.505.802 pg/mL3.6×
node playground/curveset/envelope.test.js     # the mathematics
node playground/curveset/make-page-data.js    # the record
node playground/build.js