partonmap
Results Registry

Every number, with its receipts

One card per registered result; IDs are immutable. Each card has four tabs: Results (what we produced and what you're looking at), Explanation (the physics and the method), Code (exactly how to reproduce it), Notes (the story of how it happened). Status: verified · provisional (caveats attached) · lesson (a failure that taught us something).

1 · Calibration — fitting planted protons whose true shape we know. Synthetic data, real machinery: these results test the instrument, not the proton.
PPDF-1verified · replication

Clean drill passed: fed noise-free synthetic data, the fit recovers the planted proton near-exactly.

1.96×10⁻⁴
min χ² per data point (total 0.127 over N=648)
−7.257 ± 0.13
evidence logZ; convergence budget 0.29 < 0.50 required
4.25 ≈ 4.12
posterior-avg χ² ≈ Bayesian complexity

What you're looking at: three numbers, no plot — this result is the numbers. The first says the best fit misses the 648 synthetic data points by 0.0002 of an error bar each: since the data carried zero noise, anything much larger would have signalled a bug. The paper we're replicating quotes χ² ~ 10⁻⁴–10⁻⁵ for this same test (Table 3.1) — we land in the same regime. The third number is a health identity (explained in the next tab) that only holds when the sampling is behaving; here it holds to 3%.

The physics. A proton's structure is encoded in PDFs — for each parton type, x·f(x) says how the proton's momentum is shared (wiki). Our synthetic "measurements" are deep-inelastic structure functions F₂(x, Q²): the rate of electrons scattering off the proton at momentum fraction x and resolution Q. Theory connects the two linearly: prediction = FK ⊗ f, where the FK table precomputes the QCD matrix element and DGLAP evolution (wiki).

The model being fitted: the Les Houches benchmark shape — per flavour combination, x·f(x) = A x^α (1−x)^β (1 + ε√x + γx) — 13 free parameters after sum rules. The truth was planted using this same shape, so exact recovery is possible.

The statistics. Misfit is χ²(θ) = [D − T(θ)]ᵀ C⁻¹ [D − T(θ)] with C the experimental covariance (t0 prescription, wiki). Bayes: posterior p(θ|D) ∝ e^(−χ²/2) π(θ), uniform prior boxes π. Nested sampling (UltraNest, 200 live points) explores the 13-dim posterior and computes the evidence Z = ∫ e^(−χ²/2) π dθ. On noiseless data the optimum is χ² = 0; the health identity ⟨χ²⟩ = χ²_min + complexity diagnoses honest sampling (wiki).

# environment (one-time)
micromamba create -n colibri-dev -f colibri/environment.yml
micromamba run -n colibri-dev pip install -e colibri/colibri/examples/les_houches_example
# run the fit (auto-downloads FK tables + PDF sets on first run)
micromamba run -n colibri-dev les_houches_exe lh_fit_closure_test.yaml
# lh_fit_closure_test.yaml — key blocks (full file linked below)
dataset_inputs:  # SLAC + BCDMS proton & deuteron F2
- {dataset: SLAC_NC_NOTFIXED_P_EM-F2, variant: legacy_dw}
- {dataset: BCDMS_NC_NOTFIXED_P_EM-F2, variant: legacy_dw}   # (+ D variants)
theoryid: 40000000
closure_test_level: 0            # noiseless pseudodata
closure_test_pdf: LH_PARAM_20250519
use_t0_covmat: True
t0pdfset: NNPDF40_nnlo_as_01180
ultranest_settings:
  Run_settings: {min_num_live_points: 200, min_ess: 50, frac_remain: 0.3}
  SliceSampler_settings: {nsteps: 106}
actions_: [run_ultranest_fit]

2 Jul, afternoon. First full flight of the machinery, and it flew on the first attempt — the env build was the only slow part. The 8m22s wall time included downloading four decades of experimental data. The moment we trusted the statistics was seeing posterior-avg χ² match the Bayesian complexity — that identity only holds when the posterior is behaving. Every later result stands on this card.

Provenance: theory 40000000 · truth PDF LH_PARAM_20250519 · artifacts output/lh_fit_closure_test/ · 2 Jul 2026, Apple-Silicon CPU.
PPDF-2verified · our own check

The full uncertainty band is honest: the planted truth stays inside it at 100% of checkpoints, in every fitted flavour.

posterior vs truth, four flavours

What you're looking at: four panels, one per fitted flavour combination (Σ = all quarks summed; g = gluon; V, V3 = valence combinations), each showing x·f versus momentum fraction x (log scale, 10⁻³ → 1). The teal band is our fit's 68% uncertainty; the dashed black curve is the planted truth. The test: the dashed line must stay inside the band — it does, everywhere. The grey region (x < 0.01) marks where our datasets carry no measurements. Note V/V3: enormous bands — the fit honestly admitting the data barely constrains valence separation, not a failure.

100%
of 120 x-points with truth inside the 1σ band, all four flavours
0.42σ
worst excursion anywhere (gluon)
0.6–0.7%
posterior-mean deviation from truth (Σ, g, median)

Why this check exists. PPDF-1 proved the best fit lands on the truth; this checks the stronger claim that the whole probability distribution is faithful. A fit can have a perfect central value and lying error bars — and in precision physics the error bar is the product.

The method. Each posterior sample θ becomes curves x·f(x) for all flavours. At each of 120 x-points we compute the pull = [mean(x) − truth(x)] / σ(x), with σ the band half-width (wiki). Faithful uncertainty means |pull| ≲ 1 nearly everywhere and truth-coverage near the Gaussian 68%. The truth curve is evaluated outside the fitting code — straight from its LHAPDF grid via validphys — so the check shares no code with the thing being checked.

The flavour basis. Curves live in the evolution basis (wiki): Σ and g dominate F₂ and come out tight; V and V3 barely enter electromagnetic DIS, so the posterior correctly widens toward the prior — the flat-direction phenomenon that becomes central in PPDF-4/6.

# reload fitted model + posterior samples, evaluate truth via validphys
micromamba run -n colibri-dev python scripts/verify_closure_truth.py
# core of the comparison:
model  = dill.load(open(f"{RUN}/pdf_model.pkl", "rb"))
curves = jax.vmap(model.grid_values_func(xgrid))(posterior_samples)  # (1715, 14, 120)
truth  = convolution.evolution.grid_values(pdf, FK_FLAVOURS, xgrid, [Q0])
pull   = (curves.mean(0) - truth) / curves.std(0)

This card exists because "min χ² is tiny" leaves a loophole: the central curve could be right while the band lies. The V/V3 panels were the day's teaching moment — enormous bands that are correct, because the data genuinely doesn't know. Honest ignorance vs false confidence became the theme of the whole three-method study (PPDF-6).

Provenance: script on the PPDF-1 posterior · outputs output/lh_fit_closure_test/verification/ · 2 Jul 2026.
PPDF-3verified · replication

Noisy drill passed: under realistic experimental noise the fit reaches χ²/N ≈ 1 — it fits the signal, not the noise.

0.977
posterior-avg χ²/N (min 0.971)
3.88
Bayesian complexity (PPDF-1 gave 4.12)
−321.8 ± 0.15
evidence logZ, converged

What you're looking at: the same fit as PPDF-1 but with realistic noise injected into the synthetic data — and the target inverts: 0.977 ≈ 1 is the pass. Perfection (χ² ≈ 0) would mean the fit memorized the noise; well above 1 would mean it missed real structure. The paper's benchmark is 1.00–1.01; a single noise throw scatters this number by ±0.056, so 0.977 is statistically on target.

The setup. Level-1 closure: pseudodata D = T(θ_truth) + η, with η drawn from the real experimental covariance matrix C — the same correlated systematics, normalizations and statistical errors the actual SLAC/BCDMS measurements carry. Statistically indistinguishable from real data, except the underlying truth is known.

Why χ²/N ≈ 1 is the target. If the model family contains the truth, the best fit removes the signal and what remains is noise: E[χ²_min] ≈ N − n_eff, so χ²/N ≈ 1 for N ≫ n_eff. Much below 1: the model absorbs noise (overfitting); above: underfitting or mis-modelled errors. Expected fluctuation of χ²/N is √(2/N) ≈ 0.056 at N = 648 — the yardstick for "consistent with 1".

Same machinery, opposite criterion — that's what makes L0+L1 a complete calibration: L0 catches bugs (demands perfection), L1 catches dishonest statistics (forbids perfection).

# identical runcard to PPDF-1, ONE line changed:
closure_test_level: 1            # noise drawn from experimental covariance

micromamba run -n colibri-dev les_houches_exe lh_fit_closure_test_L1.yaml

2 Jul, evening. The satisfying part was the direction of the number: 0.977, slightly under 1.00 and inside the noise scatter. At 0.5 we'd have caught noise-memorization; at 2.0, under-fitting. It landed exactly where an honest machine should. With both drills passed, we declared the machinery ready for real data.

Provenance: artifacts output/lh_fit_closure_test_L1/ · 2 Jul 2026.
PPDF-4verified · replication + finding

The Hessian method finds the same optimum as the Bayesian sampler — then fails exactly where theory predicts: on flat directions.

0.04%
Bayesian-vs-Hessian agreement on the L1 minimum (628.9 vs 629.2)
1.9×10⁻⁸
L0 total χ² — gradient descent polishes to machine-level recovery
~6σ
Hessian gluon band's worst miss of the truth at L1

What you're looking at: two validations and one failure, all quantified. The agreement numbers say two completely different algorithms (gradient descent vs nested sampling) found the same best fit — strong evidence neither is buggy. The 6σ says the Hessian's error band is nonetheless unfaithful in places: it under-covers the known truth on the gluon. Internally, the down-valence parameters ran to ~10⁹ with χ² unchanged — the smoking gun of a flat direction.

The Hessian method (used by the MSHT and CT groups): find the minimum θ₀, expand quadratically — χ²(θ) ≈ χ²₀ + ½ (θ−θ₀)ᵀ H (θ−θ₀) — and quote uncertainties along the eigenvectors of the curvature matrix H at Δχ² = T² (tolerance T = 1 here). The construction assumes the likelihood is a bowl.

Where it must fail. Electromagnetic F₂ measures flavour sums; the valence split barely affects predictions. Along such flat directions the curvature is ~0: H has near-zero eigenvalues, 1/√λ blows up, and the quadratic picture is meaningless — the minimizer's parameters drift to absurd values (10⁹) at constant χ², and the quoted band becomes an artifact. The Bayesian posterior has no such assumption: it simply widens to the prior. This is Sec. 2.4 of the Colibri paper, reproduced live.

Method note: gradient descent (Adam, 3 restarts × 20k epochs) with the same likelihood, data and t0 as the Bayesian fit — only the inference philosophy differs, which makes the comparison clean.

# gradient-descent methodology block (settings OURS — the paper publishes none)
optimizer_settings:
  optimizer: adam
  optimizer_hyperparams: {learning_rate: 2e-3}
max_epochs: 20000
param_initialiser_settings: {type: normal, random_seed: 0}   # means/stds: dicts by param
hessian_settings: {tolerance: 1.0, iter_init: 3, rng_seed: 1}
actions_: [run_hessian_fit]

The eigenvector members with entries of ±10⁹ looked like a bug for about ten minutes; then χ² came back identical along those directions and it clicked: not a bug — the phenomenon. Also root-caused en route: the initializer wants means/stds as dicts keyed by parameter name, not lists. Watching the failure mode live beat reading about it.

Provenance: output/crosscheck_methods/hessian_L0/L1_summary.json · 2 Jul 2026.
PPDF-5verified · replication

The Monte-Carlo replica method lands on its theoretical expectations to three decimals: loss/point 1.009 (clean) and 2.000 (noisy).

1.009
mean final training loss/pt over 100 replicas, L0 (theory ≈1)
2.000
same at L1 (theory ≈2 — two noise layers)
100/100
replicas passing post-fit selection at both levels

What you're looking at: a statistical bullseye. Each replica's final loss has a sharp theoretical expectation from pure noise arithmetic (next tab); measuring 1.009 and 2.000 against predictions of ≈1 and ≈2, over 200 independent fits, says the replica machinery is statistically faithful.

The replica method (NNPDF's approach): create K pseudo-datasets D_k = D + η_k with η_k drawn from the experimental covariance, fit each independently, and quote the spread of the K fits as the uncertainty — bootstrap in spirit. Each fit uses gradient descent with cross-validation early stopping (hold out 20% of points; stop when held-out loss stops improving).

The loss arithmetic. Fitting replica k, the best fit removes the signal; what remains is the replica noise → loss/pt ≈ 1 at L0 (one layer: the MC fluctuation η_k). At L1 the "data" already carries closure noise and the replica adds its own: two independent layers → loss/pt ≈ 2. Landing on both means the noise model, covariance handling and early stopping all behave.

The known limitation (why this lab exists): the replica ensemble provably matches the Bayesian posterior only for models linear in parameters (arXiv:2404.10056). These parametrizations are not linear — hence the three-method comparisons of PPDF-6 and the MSHT20 phase.

# 100 replicas, 6-way parallel, then post-fit selection
seq 1 100 | xargs -P 6 -I{} micromamba run -n colibri-dev \
    les_houches_exe lh_mc_L0.yaml -rep {} -o lh_mc_L0
micromamba run -n colibri-dev mc_postfit lh_mc_L0            # L0: default cut 1.5
micromamba run -n colibri-dev mc_postfit lh_mc_L1 -c 3.0     # L1: two noise layers

The L1 post-fit failure ("0 of 100 replicas pass") briefly looked like a broken campaign. The resolution was the two-layer arithmetic: expected loss ≈ 2 sits above the default cut of 1.5 by construction. Raising it to 3.0 is a documented consequence of the noise model, not tuning; the 5σ outlier rejection stayed on.

Provenance: output/crosscheck_methods/mc_L0/L1_result.csv · 2 Jul 2026.
PPDF-6verified · synthesis

Three inference engines on identical planted data: all agree where the data constrains — and split exactly where theory predicts.

three methods vs truth, L1

What you're looking at: the noisy-drill fits by all three methods, overlaid. Each panel: x·f versus x for one flavour; teal = Bayesian, orange = MC replicas, purple = Hessian (bands = 1σ), dashed = planted truth. Left and centre (Σ, gluon — well measured by F₂): the three bands nearly coincide and all cover the dashed line; small-x offsets are the shared noise throw, not disagreement. Right panel (V, the valence flat direction): the tell — the teal Bayesian band balloons (honest: the data doesn't know), while orange and purple stay thin and hug the truth largely by luck of where their fits started. Same data, same model — only the statistical philosophy differs.

Why they agree in the middle. Where data constrains, the likelihood is sharply peaked and nearly Gaussian; all three methods reduce to the same answer — the bowl assumption holds, the linear-model condition approximately holds, the posterior is Gaussian. Agreement there is the expected null result and validates all three implementations at once.

Why they split at the edges. On a flat direction there is no bowl (Hessian undefined), no linearization (replica equivalence broken, arXiv:2404.10056), and no data pull (posterior → prior). Each method's character shows: Bayesian = honest ignorance; Hessian/MC = accidental confidence. On planted data we can adjudicate — the truth is known — and the wide band is the correct answer.

Why it matters: real analyses quote these bands as "the proton's uncertainty". This picture is the cleanest demonstration of when the standard shortcuts are safe and when they quietly aren't.

# overlay all three posteriors/ensembles against the truth
micromamba run -n colibri-dev python scripts/compare_methods.py
# Hessian band from eigenvector +/- pairs:
plus, minus = members[0::2], members[1::2]
sigma = sqrt(sum(((plus - minus)/2)**2, axis=0))

The synthesis card — the picture that explains the project to a non-expert in ten seconds. Marked verified because every band traces to an independently verified card (PPDF-1, 3, 4, 5). Its real-data sibling — same three engines, no truth line to lean on — is the MSHT20 phase's final deliverable.

Provenance: inputs PPDF-1 PPDF-3 PPDF-4 PPDF-5 · output/crosscheck_methods/method_comparison_summary.csv · 2 Jul 2026.
2 · Toy models vs real measurements — the same machinery pointed at actual SLAC + BCDMS data (648 points, 1970s–80s experiments). No truth line exists here; models are judged by fit quality and by the Bayesian evidence.
PPDF-7verified · first real data

The 13-parameter toy meets real measurements and lands at χ²/N = 5.60 — a measurement of the model's rigidity, not a machinery failure.

5.60
min χ²/N on real data (3626.5 / 648)
−1835.1 ± 0.16
evidence logZ — the baseline all later models are judged against
~35 min
wall time, laptop CPU

What you're looking at: the first fit where nobody knows the right answer. 5.60 means the model misses the average data point by 2.4 error bars — far from the ≈1 of a good description. The calibration drills (PPDF-3 scored 0.977 on this exact machinery) exonerate the pipeline, so this number measures the model: a 2005-era benchmark shape is too stiff for 648 real measurements. The logZ became the incumbent for every challenger.

The data. Real F₂ structure-function measurements: SLAC (late 1970s) and BCDMS (1980s, CERN muon beam) on hydrogen and deuterium targets — 648 points after kinematic cuts, spanning roughly 0.01 < x < 0.75. The proton/deuteron pairing gives (weak) sensitivity to the u–d flavour split. Full correlated systematics via the NNPDF covariance implementation; t0 prescription for normalizations.

What a big χ² means here. Three suspects for χ²/N ≫ 1: (a) the model can't bend into the data's shape (rigidity), (b) internal data tensions, (c) theory settings (perturbative order, deuteron corrections, cuts). Calibration eliminated the machinery itself. Distinguishing (a) from (b)/(c) required a far better model — the arc that ends at PPDF-12, where (b) and (c) are acquitted too.

The evidence baseline. logZ = ∫ e^(−χ²/2) π(θ) dθ integrates fit quality over everything the prior allows (wiki). −1835.1 is meaningless alone; it exists to be compared against, at identical data/theory/t0, by every later model.

# identical to PPDF-1's runcard, ONE line changed:
closure_test_level: false        # REAL measurements, no pseudodata

micromamba run -n colibri-dev les_houches_exe lh_fit_realdata_dis.yaml

2 Jul, night. Sampling efficiency halved relative to closure runs — the first sign real data fights back. The correct reading of 5.6 took a beat: the drills prove the pipeline, so the misfit is a measurement of model rigidity. It took until PPDF-12 to prove that reading right.

Provenance: artifacts output/lh_fit_realdata_dis/ · 2 Jul 2026.
PPDF-8lesson · disqualified as model test

Grid model v1: a stalled sampler, then a model structurally blind to its own data — and an evidence referee that caught it immediately.

8.02
min χ²/N — worse than the 13-parameter toy despite 24 parameters
ΔlogZ ≈ −808
evidence penalty vs the toy baseline — missing physics, priced
290×
speed-up after configuring the slice sampler

What you're looking at: a disqualified result kept on the books. A more flexible model scoring worse than a rigid one is the anomaly; the diagnosis (next tab) found the model couldn't represent the physics the data measures. The −808 shows the evidence catching that within a single fit.

Lesson 1 — sampling. Nested sampling above ~10 dimensions needs a step (slice) sampler; without the config block, UltraNest falls back to region rejection sampling, whose acceptance collapses exponentially with dimension: 137M likelihood calls overnight at 0.003% efficiency. One config block restored healthy sampling — 290× faster.

Lesson 2 — flavour masking. The grid model's flavour_mapping zeroes unlisted flavours in the FK convolution. Among the masked: T3 = u⁺ − d⁺ — the combination that makes a proton differ from a neutron, hence proton F₂ differ from deuteron F₂. Our dataset is precisely p and d measurements: the model was structurally unable to describe the difference between its own data subsets, at any parameter values. Published grid examples are closure tests where truth and model share the mask (it cancels); real data was off-label.

Why the evidence caught it: logZ integrates fit quality — a model that cannot reach the data's structure has uniformly poor likelihood, and no parameter count compensates. The evidence prices missing physics, not complexity.

# the flaw (v1): masked flavours -> FK columns zeroed -> p/d degenerate
flavour_mapping: ["\Sigma", "g", "V"]       # no V3, T3, T8...

# the stall + the fix (REQUIRED at ndim >~ 10):
ultranest_settings:
  SliceSampler_settings: {nsteps: 100}   # 290x speedup

3 Jul, morning. The stall was root-caused in Colibri's ultranest_fit.py (no step sampler attached without the block), not guessed at. The masking flaw surfaced only after convergence, when χ²/N = 8.02 made no sense for a more flexible model; tracing the FK masking revealed the p–d blindness. Pedagogically the best failure the lab has produced.

Provenance: HEP-PBSP grid_pdf-model (24 params: Σ/g/V × 8 nodes) · output/gp_fit_realdata_dis/ · 3 Jul 2026.
PPDF-9provisional · first evidence verdict

First model contest on real data: the evidence prefers 13 honest parameters over 36 constrained ones by ΔlogZ ≈ −109 — verdict held loosely, caveats attached.

5.84
min χ²/N, 36-param grid with full flavours (toy: 5.60)
−1943.9 ± 0.28
logZ → ΔlogZ ≈ −109 vs the toy baseline
16.95
Bayesian complexity — the data uses ~17 of 36 parameters

What you're looking at: the flavour fix worked exactly as diagnosed (8.02 → 5.84), yet the flexible grid still can't match the rigid toy, and the evidence prefers the toy decisively. Both models flooring near χ²/N ≈ 5.6–5.8 — where global fits describe these same datasets at ≈1 — was the open question this card handed to the MSHT20 phase (answered in PPDF-12).

Bayes-factor logic. Two models on identical data: ΔlogZ is the odds update the data provides — ≈5 is already strong (~150:1), so −109 is overwhelming on its face. But the evidence integrates over the prior, and verdicts inherit prior choices (wiki).

The caveats that keep this provisional: (1) the grid's canonical prior confines it to a ±5σ band around the published NNPDF4.0 proton while the toy roamed free uniform boxes — an uneven field; (2) 6 x-nodes per flavour may be too coarse to bend where the data needs; (3) the grid carried no sum rules.

What survives the caveats: the workflow — two full posteriors and evidences on identical data/theory/t0, compared like-for-like. That machinery is the point, and it's what the MSHT20 phase then used to settle the floor question.

# v2: full flavour content, 6 nodes per flavour = 36 params
flavour_mapping: ["\Sigma", "g", "V", "V3", "T3", "T8"]
grid_pdf_settings:
  xgrids:  # per flavour
    \Sigma: [0.01, 0.03, 0.08, 0.2, 0.4, 0.7]
prior_settings:
  prior_distribution: uniform_pdf_prior
  prior_distribution_specs: {pdf_prior: NNPDF40_nnlo_as_01180, nsigma: 5}

3 Jul, afternoon. The verdict we hold loosely; what we don't: the evidence-comparison workflow ran end-to-end on real data (project goal 3), and the shared χ²/N floor became the question that shaped the MSHT20 phase — where it was answered: the floor was the models.

Provenance: baseline PPDF-7 · output/gp_fit_realdata_dis_v2/ · 3 Jul 2026.
3 · MSHT20 — porting a big-three, real-world parametrization into the Bayesian machinery: prove the port, drill it on planted data, then fit real measurements. Ends at Maria's goal: Hessian vs MC vs Bayesian uncertainties on the same real data.
PPDF-10verified · parity gate

The MSHT20 parametrization, ported to Colibri and proven exact: 96 parity checks against its reference implementation.

96 / 96
parity checks passed; worst gating deviation ≲10⁻⁹
52
free parameters after sum rules and ties
1.000025
numerical momentum sum on 3,000 grid points (analytic: exact)

What you're looking at: a software result with physics stakes. Four levels of checks — special-function integrals, every shape function, all four sum-rule computations, and the assembled flavours — each compared point-for-point against FPPDF's own code, at the published parameter values and five random ±10% perturbations. Everything the fits will ever call agrees to better than a part per billion. The random draws caught a hidden ×A_g factor invisible at publication values — the reason the gate exists.

The parametrization (MSHT20, Eqs. 2–8 of arXiv:2012.04684): each basis distribution is x·f(x) = A (1−x)^η x^δ (1 + Σᵢ aᵢ Tᵢ(y)) with Chebyshev polynomials Tᵢ in y = 1 − 2√x — a rigid but well-crafted shape whose Chebyshev terms add controlled wiggle room. Basis: u_V, d_V, sea S, s₊, s₋, d̄/ū, two-term gluon, charm (zero here: perturbative-charm convention). Four sum rules are imposed analytically — valence counting (∫u_V = 2, ∫d_V = 1), momentum (Σ ∫x·f = 1, fixing A_g), zero net strangeness (fixing the s₋ crossing x₀) — via closed-form Euler-Beta integrals, which keeps the model exact and fast.

The port method. Transcribe FPPDF's implementation function-by-function into JAX (differentiable, GPU-ready, what Colibri consumes), then refuse to run any fit until the transcription proves itself: parity at machine precision across parameter space, plus physics sanities (momentum sum, valence counting). Convention note: FPPDF's fitting basis uses S = 2(ū+d̄)+s₊ (NNPDF-style) vs the MSHT20 paper's S = ū+d̄+s+s̄ — we match the code, bit-for-bit.

# run the parity gate (FPPDF installed as reference)
micromamba run -n colibri-dev python analysis/msht20/parity_test.py
# PARITY REPORT — 96 checks, worst rel dev = 1.257e-05 (non-gating Ic8)
# RESULT: PASS — port is exact within tolerance

# the bug the jittered draws exposed (FPPDF pdfs.py, int_g1_msht):
out = out * agp   # multiplies by the A_g slot — 1.0 at publication values

7–8 Jul. Maria's email landed mid-build and confirmed the plan line-for-line — data, code source, and the sharpened final goal: Hessian vs MC vs Bayesian on MSHT20. Priors, charm convention and closure criteria were declared in the log before any fit launched (blind discipline). A port tested only at the publication point would have carried a silent bug into every fit that followed.

Provenance: analysis/msht20/ (port, parity harness, LOG.md) · reference github.com/FPPDF/fppdf @ 2026-07-07 · ledger PPDF-10 · 8 Jul 2026.
PPDF-11verified · closure passed

MSHT20 passes its own planted-proton drills at 52 dimensions — and reveals that our DIS data sees only ~1/5 of its shape.

0.0074
clean-drill min χ²/N — planted truth recovered
0.979
noisy-drill avg χ²/N (target ≈1 within ±0.056)
~11 / 52
Bayesian complexity — directions the data actually constrains

What you're looking at: the same two-drill calibration as the toy model, at 52 dimensions. Clean drill: near-zero recovery (residual = sampler resolution — nested sampling explores, it doesn't polish). Noisy drill: 0.979 ≈ 1, honest under realistic noise. Truth-coverage across five flavours: 65–100% against the 68% Gaussian ideal — calibrated bands, neither padded nor thin. The health identity ⟨χ²⟩ = χ²_min + complexity held exactly in both drills.

In-family truth — the key design choice. The planted proton is the MSHT20 model itself at its published parameter values, not an external PDF set. With out-of-family truth, a nonzero L0 χ² could mean machinery bugs or model mismatch — conflated. In-family, any residual is machinery by construction: the drill isolates what it's meant to test.

The complexity finding. Bayesian complexity ≈ ⟨χ²⟩ − χ²_min counts the parameter directions the data pins down (wiki). 10–12 of 52 quantifies the information mismatch between a fixed-target DIS subset and a global-fit parametrization: F₂ on p/d constrains the singlet and gluon well, valence weakly, strangeness barely. Prediction made and kept: honest, wide posteriors in those directions on real data.

# closure truth generated FROM the model itself (in-family):
closure_test_pdf: colibri_model
closure_test_model_settings:
  model: msht20_model
  parameters: { uv_del: 0.3436, uv_eta: 3.7487, ... }   # 52 publication values

micromamba run -n colibri-dev msht20_exe msht_closure_L0.yaml   # then L1

8 Jul. An order of magnitude heavier than the toy's drills (~5M likelihood evaluations for L0 alone), but the PPDF-8 sampler lesson held: no stalls, clean convergence budgets. After the toy's over-conservative 100% coverage, seeing 65–100% around the 68% ideal was the posterior behaving exactly as statistics demands. Real-data fit launched the same hour both drills passed.

Provenance: output/msht_closure_L0/ · output/msht_closure_L1/ · ledger PPDF-11 · truth = msht20_model @ FPPDF publication values · 8 Jul 2026.
PPDF-12verified · headline result

The first Bayesian MSHT20 posterior on real data — and the χ²/N ≈ 5.6 mystery solved: the floor was the models, not the data.

1.002
min χ²/N on real data (toy: 5.60 · grid: 5.84)
−381.9 ± 0.29
logZ — ΔlogZ ≈ +1453 over the toy baseline
13.7 / 52
Bayesian complexity; identity exact (663.3 = 649.5 + 13.7)

What you're looking at: the number this arc was built toward. Same 648 real measurements, same theory, cuts and t0 as every real-data fit above — only the model changed, and the misfit collapsed from 5.6 error bars per point to statistically perfect. Two toy-era suspects (data tensions, theory settings) are acquitted in one stroke: the data was describable all along; the earlier models couldn't bend. A Bayesian posterior for MSHT20 now exists — posterior samples and corner plot in the artifacts.

Why MSHT20 succeeds where the others couldn't. Against the toy (13 params): Chebyshev terms give controlled mid-x flexibility exactly where BCDMS is most precise. Against the grid (36 params): flexibility placed by expertise — smooth shapes with physical small-/large-x behaviour x^δ(1−x)^η, analytic sum rules, correct flavour content — beats flexibility scattered on x-nodes. Parameter count was never the story; where the freedom lives is.

What χ²/N = 1.002 asserts. Goodness-of-fit is a pure likelihood statement — no prior involved: the best-fit MSHT20 curve misses the average point by exactly one error bar, matching what global fits achieve on these datasets. The prior caveat touches only the evidence comparison: our boxes are centered on MSHT's published values (from their global fit), which flatters logZ. But ΔlogZ ≈ +1453 is dominated by raw likelihood (Δχ²/2 ≈ 1488 alone) — no defensible prior re-design flips a gap that size.

What it sets up. This posterior is the Bayesian leg of Maria's three-method comparison; the MC-replica ensemble and Hessian eigenvector bands on the identical setup complete it (next card).

# identical to the closure runcard with one line changed:
closure_test_level: false        # REAL measurements

micromamba run -n colibri-dev msht20_exe msht_realdata_dis.yaml

8 Jul. The number came out almost embarrassingly clean: 1.002. Four days of χ²/N ≈ 5.6 across two models had made data tensions feel likely; the answer was simpler — neither model deserved the data. The phase's namesake deliverable exists: a Bayesian posterior for MSHT20. MC and Hessian legs running.

Provenance: output/msht_realdata_dis/ · ledger PPDF-12 · baseline chain PPDF-7 PPDF-9 · 8 Jul 2026.
PPDF-13verified · replica leg

The MC-replica ensemble for MSHT20 on real data: 83 of 100 replicas pass the pre-declared selection, statistics on theory.

83 / 100
replicas passing the pre-declared cut (one non-finite export dropped → 82 analysed)
≈ 2.05
mean final loss/pt (theory ≈2: one noise layer + χ²/N≈1 residual)
2m36s
per replica on laptop CPU, 6-way parallel

What you're looking at: the replica leg of the three-method comparison. The loss arithmetic landing on its prediction (≈2) says the ensemble machinery behaved; what the ensemble means as an uncertainty is exactly what PPDF-15 tests.

Same method as PPDF-5, now on real measurements: 100 jittered copies of the data (noise from the experimental covariance), one gradient-descent fit each, spread = uncertainty. On real data the expected final loss/pt is ≈1 (replica noise) + χ²/N of the model against the real data (≈1 from PPDF-12) ≈ 2 — the pre-declared selection cut (3.5) follows from that arithmetic plus the usual outlier rejection, fixed before results existed.

seq 1 100 | xargs -P 6 -I{} micromamba run -n colibri-dev \
    msht20_exe msht_mc_real.yaml -rep {} -o msht_mc_real
micromamba run -n colibri-dev mc_postfit msht_mc_real -c 3.5   # pre-declared

8 Jul. Ran while the Bayesian posterior was still being verified — the three legs of the comparison were produced independently, no leg saw another's results before PPDF-15 brought them together. The 17 rejected replicas are gradient-descent stragglers; one exported row was non-finite and is dropped with a note rather than silently.

Provenance: output/msht_threeway/mc_result.csv · ledger PPDF-13 · 8 Jul 2026.
PPDF-14verified · method-breakdown finding

The Hessian method structurally fails here: at 52 parameters on 648 DIS points, the curvature at the minimum is indefinite — there are no meaningful eigenvector bands to quote.

0.9845
χ²/N at the minimum — found identically four times (the fit itself is fine)
11 / 52
eigen-directions with negative (≈zero) curvature — no bowl to measure
±70,000
largest eigenvector member excursions in parameter space

What you're looking at: a clean minimum with unusable curvature. The best fit is excellent; the quadratic approximation around it is undefined along most directions — roughly 38 of 52 parameters are simply not constrained by this dataset (matching the Bayesian complexity ≈14 of PPDF-12). The purple explosion in the PPDF-15 plot is this table made visible.

Why it breaks. Hessian errors assume χ² is a bowl: H must be positive-definite, bands scale as 1/√λ. Where data leaves directions flat, λ → 0 (our finite-difference resolution measures them as consistent with zero, some marginally negative), and 1/√λ diverges — bands lose meaning. This is PPDF-4's finding taken to its extreme: at 13 parameters two directions were flat; at 52 parameters on the same data, most are. MSHT's published global fits avoid this by fitting ~4,600 points and freezing insufficiently-constrained parameters — our setup exposes the method's data-sufficiency requirement.

Computational note (its own lesson): three autodiff routes to this matrix hit pathological XLA compile times (>40 min each — fused jax.hessian, HVP columns, jitted-gradient FD). The working method: central finite differences of likelihood values in eager mode — zero compilation, ~5,600 evaluations, accuracy far beyond what T=1 bands need.

# eager value-FD Hessian (jax.hessian & friends: XLA compile pathology at 52d)
micromamba run -n colibri-dev python analysis/msht20/run_hessian_fdval.py msht_hessian_real.yaml
# [fdval] Hessian assembled: 52x52, f0=637.947800

8 Jul. Half a day of XLA fighting (three methods, all compile-bound — each attempt logged) ended with the least glamorous method winning: plain finite differences, no compiler involved. The indefiniteness then turned a computational chore into the sharpest finding of the comparison. Worth reporting upstream to Colibri: their Hessian path will bite anyone past ~20 parameters on CPU.

Provenance: output/msht_threeway/hessian_fit_summary.json · ledger PPDF-14 · 8 Jul 2026.
PPDF-15verified · the phase deliverable

Hessian vs MC vs Bayesian on the same real data: they agree only where data constrains — and only the Bayesian bands carry a calibration certificate.

three methods on MSHT20 real data

What you're looking at: five flavour panels, x·f vs x at Q₀; teal = Bayesian, orange = MC replicas, purple = Hessian, bands = 1σ. Grey: x < 0.01, outside our data. Panels are y-clipped to the Bayes/MC scale — the purple Hessian band exceeds every frame (that's the PPDF-14 breakdown, visible). In the gluon panel at mid-x — the direction this data genuinely measures — teal and orange agree closely. In Σ and T8 the orange replica band runs ~8–10× wider than teal with centrals up to ~7σ apart: in unconstrained directions the replica spread reflects initialization luck, not information.

1.8× · <1σ
MC vs Bayes on the gluon: width ratio and central offset — agreement where constrained
0.6–10×
MC/Bayes width ratios across flavours — no consistent rule off-constraint
50–10⁷×
Hessian/Bayes width ratios — undefined curvature, unusable

What this tests. Maria's stated final goal: same model (MSHT20), same 648 real measurements, same theory and covariance — only the uncertainty philosophy differs. Real data allows no truth line, so methods are judged against each other plus one external fact: the Bayesian machinery holds a closure certificate at exactly this dimensionality (PPDF-11: calibrated coverage), which neither alternative has here.

The pattern, and why. Where the likelihood is sharply peaked (gluon at mid-x), all honest methods converge — Gaussian likelihood makes replica-equivalence and posterior-Gaussianity approximately true. Where directions go flat, each philosophy shows its failure mode: Hessian bands diverge (no curvature), replica bands land wherever gradient descent starts and stops (initialization-shaped), Bayesian bands widen to the declared prior (honest, but prior-dependent — stated on the tin). The practical conclusion: at this dataset-to-parametrization information ratio, only the Bayesian answer is defensible — and the fix for the others is more data, which is exactly the full-DIS run in flight.

Scope caveat: this is a statement about methods at THIS information ratio — not about MSHT20's published errors, which come from a global dataset with parameter freezing.

# one function turns any parameter set into PDF curves at Q0 (same model for all three)
f = model.grid_values_func(xgrid)                     # theta -> (14 flavours, 120 x-points)
curves_of = lambda P: np.array(jax.vmap(f)(P))

# the three uncertainty objects, from each method's own output
bay = curves_of(posterior_samples)                    # 17,496 Bayesian samples (PPDF-12)
mc  = curves_of(replica_params[finite])               # 82 MC replicas (PPDF-13; 1 non-finite dropped)
plus, minus = curves_of(eig_members[0::2]), curves_of(eig_members[1::2])
h_sig = np.sqrt(np.nansum(((plus - minus) / 2)**2, axis=0))   # Hessian: quadrature over eigen-pairs (PPDF-14)

bands = {"Bayesian": (bay.mean(0), bay.std(0)),
         "MC replicas": (mc.mean(0), mc.std(0)),
         "Hessian": (h_central, h_sig)}

# the two comparison metrics, per flavour, in the data region x > 0.01
width_ratio = np.nanmedian(s_method / s_bayes)        # how wide vs the calibrated band
offset      = np.nanmax(|m_method - m_bayes| / s_bayes)  # central drift in Bayesian sigmas
micromamba run -n colibri-dev python scripts/compare_msht_methods.py
# summary CSV: output/msht_threeway/threeway_summary.csv

8 Jul. The deliverable Maria named in her email, produced ~30 hours after the email arrived. The expected result was "three bands, mild differences"; the actual result is starker and more useful — a live demonstration of when each standard method can and cannot be trusted, with the Bayesian calibration certificate as the differentiator. The full-DIS rerun of this comparison (5× the data) will show whether the alternatives recover.

Provenance: inputs PPDF-12 PPDF-13 PPDF-14 · output/msht_threeway/ · 8 Jul 2026.