Conversation
Remove the 0.x tests, notebooks, in-package samplers, drivers and the declaration classes. The eight modules the rewrite harvests stay in place for one commit so that git mv can carry their history into the new layout. The 0.x package remains at v0.1.0 and on legacy/0.x.
git mv only, no edits: likelihood_model -> likelihood, covariance -> terms, observation_from_measurement -> units, model_comparison -> diagnostics, the two reaction observation modules -> reactions/. Their bodies are rewritten in milestones 1, 5 and 6.
Minimal package init and smoke test; pytest fast/slow tiers (slow marker, deselected by default); py312 lint targets; pandas and scikit-learn out of the runtime requirements and into the examples extra with dill; docs reduced to the design and recipes pages; a README for the branch; CI with format, tests and docs jobs on main and rewrite plus a scheduled slow job; a trusted-publishing workflow on version tags.
…prior Frozen dataclass with eq=False, so sharing is by object; bounds validated and coerced; prior, unit and latex carried for Problem and plotting.
Drop the contextual flag, the context keyword and per_observation_scaling; scale() uses the new Parameter signature. Transform, composition, log/exp and the finite-difference derivative are unchanged.
The measurement adapters return inside from_measurement in milestone 5.
Gaussian, StudentT(nu=None) with a bounded default parameter, Chi2 and the log_likelihood helper; the Cholesky helper moves to covariance in milestone 3. Test helpers gain a dense reference assembly used by the term tests now and the structured covariance tests later.
Term is a frozen dataclass: fn, params, kind, on, coords, constant. No bind, no support indices, no caches; value() evaluates on a given support and compile resolves on= to rows. TermContext gains meta(key) for per-point dataset metadata. Factories keep their bodies with support= renamed on= and the _term suffix dropped; kernel() accepts params= to share hyperparameters between comparisons. Tests port TermKinds, Coords, Factories, Kernel and the alpha+Ca study forms against a hand-built dense reference, plus the term-level halves of recipes 19 and 27.
x4i3 converts every EXFOR cross section to barns while parsing and exfor_tools labels the result from a three-entry table, so measurement unit labels come from a small fixed vocabulary. parse_unit(label) maps that vocabulary (plus the obvious spellings) to a factor into the internal unit and a quantity kind, and rejects anything else loudly. The 0.x pint path could not parse the real labels (barns/ster, b/Sr); it only worked for hand-built measurements.
Frozen, identity-hashed; x is opaque beyond its first dimension; y_err validated; norm_err and offset_err stored as a float or an (n,) array; meta copied. No comparison transform, mask or solver state.
Model(fn, params) binds to a grid by closing over it; subclasses override bind() to build solvers from meta. Composition happens on the bound predictors: | applies a mean transform after the prediction, + and * are x-dependent corrections, parameters concatenated left to right. polynomial(order) is the generic example.
Comparison binds a model to a dataset in a parameter-free space, with the delta-method errors and the per-point log-Jacobian as constants; reported_terms() turns the dataset's offset and normalisation systematics into rank-one modes, propagated at the data and at the prediction respectively. Constraint holds the comparisons, terms, likelihood, weight and per-comparison masks; masked, masked_where and complement share every object with the original. Every term's on= is resolved eagerly and an array term's shape is checked against its support.
The study labels (L0, E0, L1, ...) meant nothing to a reader who had not seen the study. test/helpers.py now carries STUDY_LEGEND, one line per label, and study_form(label, x, y, ym) builds the terms, values and the hand-built dense reference; the term tests parametrise over it and the structured covariance tests will too. Recipe 18 and the design document point at the legend.
Sigma = diag(D) + blockdiag(M_b) + U U^T over the active rows of a constraint: diag terms into D, mode terms as columns of U (a mode across comparisons is one column with entries in several blocks), matrix terms into their block, and a matrix term that crosses blocks forces the dense path. Per-block Cholesky plus a rank-r correction gives (d2, logdet); constant pieces are evaluated once and a fully constant covariance is factored once, with a singular block reported by label at construction. Verified against the hand-built dense reference on every study form, across blocks, with masks, and on the dense fallback.
Recipe 18 now carries the full legend table; test/helpers.py keeps an identical copy and says so, and the design document cites the recipe. A docs reader never has to open the test suite.
ParameterIndex assigns each distinct Parameter a slot in first-seen order (predictors, terms, likelihood, constraint by constraint) and rejects duplicate names with a hint. The prior is assembled so every slot is covered exactly once: a marginal truncated to its bounds, the uniform on finite bounds, or one joint block; a frozen multivariate normal gets a whitening unit-cube map, other joints supply their own. Compiled constraints stack the comparisons, check finiteness on the active points, stack per-point metadata for terms, resolve every term's rows and gather, and build the structured covariance. Problem exposes log_prior, log_likelihood (weighted sum), log_posterior (prior first), prior_transform, sample_prior, predict, chi2, columns and the black-box-bayes aliases, and pickles with dill. Tests cover the index, the prior rules, compile errors, masked views, and emcee, dynesty and dill drivers.
One test file per recipe under test/recipes, docstring quoting the recipe's intent, assertions its expected-behaviour bullets that need no converged chain; a linear-Gaussian oracle supplies closed-form posteriors for the linear recipes. offset() and normalization() now take the nuisance parameter as their first positional argument, like every other nuisance factory and like the recipes spell them; magnitude= stays a keyword.
…heck Recipe tests for external samplers, custom terms, preprocessing, the singular-covariance error, shared hyperparameters, a GP across energies and the hyperprior block. Two library changes they exposed: a joint prior block may introduce a parameter no model or term uses (its hyperparameter), which now gets a slot after the constraints' parameters; and the block factor B is checked at construction whenever every diag and matrix term is constant, since modes never enter B, so a block covered only by modes fails by label before any likelihood call. Term is exported from the package.
SafeBayes prefix differences equal the Gaussian conditional; KDUQ deltas are linear fractions (log=False, also in the recipe); Peelle's puzzle is pinned by the two-point closed form and by the ordering data-built < live prediction-built < t0 across replicates, with the recipe text corrected to say the live mode keeps a log-determinant pull that the t0 refit removes; cut posteriors by closure and by module weights; an emulator term seeing the model's values; MAP + Laplace against the oracle; error scale and USU modes; energy-dependent parameters; Legendre modes; and the eight-schools model in its three spellings.
GLS with Sigma = sigma^2 I + s^2 y y^T collapses by Sherman-Morrison to t = ybar / (1 + (s/sigma)^2 sum (y_i - ybar)^2), exact per dataset and sampler-free; the test asserts it, that identical points give no bias, and that replicate means lie between the leading-order expectation 1/(1 + (n-1) s^2) and the truth. The recipe text now quotes that form instead of the 1/(1 + n s^2) factor it had copied unverified.
ElasticXS and IsobaricAnalogPN build their jitr workspace from the dataset's kinematics in bind() and return a Predictor closing over it; the elastic basis is cached per model and energy so a plotting grid or a held-out view reuses it, and the cache is dropped on pickling. The harvested set_up_solver functions take one grid; rutherford() is the closed form of the kinematics and momentum_transfer() a free function. No compound-correction hook. Real-solve tests with lmax=10 pin finiteness, units, the cache, composition, solver-setting forwarding, the Lane-term IAS, and a dill round trip of a reaction Problem.
Reads the exfor_tools fields, converts angles to radians and cross sections to b/sr through the fixed label table, converts dXS/dA to and from dXS/dRuth with the closed-form Rutherford cross section (a per-angle norm), scales the dimensionful errors with the data and leaves the fractional normalisation error alone, and fills meta with the kinematics a reaction model needs. Every failure names what is wrong.
Reported systematics become modes only when asked for; an EXFOR measurement lands in b/sr and radians with the Rutherford conversion as a per-angle norm; one elastic model serves the data grid and a plotting grid from one cached basis; a cross section and an analysing power from one measurement share an angle-calibration mode across comparisons. Recipe 37 now notes that a spanning basis sees the gathered stack and must split a finite difference at the seam by per-point metadata.
A term on several comparisons sees their rows gathered into one stack, so a basis that differentiates or smooths along the grid would straddle the seam. TermContext now carries segments (the slice of the support belonging to each spanned comparison, in constraint order), labels, and split(a); the covariance computes them once per entry from the block offsets. Outside a problem a term has one segment. Recipe 37 takes its angle-calibration slope per segment, and the design and recipe docs describe the new fields.
A kernel term closed over its sklearn kernel and nothing on the Term exposed it, but the predictive band promised by recipe 7 must condition the discrepancy from the term alone. KernelTerm is a Term subclass carrying the kernel, the count of free hyperparameter elements (so the log-theta and amplitude columns follow from params), the amplitude and the jitter; the covariance treats it as any matrix term.
… score predictive_draws and heldout_log_predictive take a compiled Problem and chain rows in problem.names order; coverage, sharpness, the log posterior predictive and the evidence bookkeeping are lifted from 0.x. A held-out problem built from fit.complement() scores the marginal of its rows, which is wrong when a term spans the split (a GP over several experiments); given=fit_problem computes the Gaussian conditional under the full covariance instead, and equals the marginal when nothing spans. split_samples and the module-level log_jacobian are gone: columns come from problem.columns and the Jacobian from problem.log_jacobian().
total_predictive_band(problem, term, predictor, x_pred, samples) locates the kernel term's constraint and covariance entry, takes its training rows, comparison space, kernel and amplitude columns from the problem, and conditions the discrepancy with the rest of the declared covariance as the regression noise, so a chain with nuisance columns needs no column arithmetic. The amplitude is evaluated at the prediction grid through a TermContext; physical=True maps draws back through the space's inverse. GP conditioning against sklearn is lifted from 0.x.
- given= held-out scores and draws compile the fit|held union against the held-out problem's own parameter index instead of a throwaway Problem, so every constraint reads its own columns, parameters with only a joint prior work, and rows masked out of both views stay out - Comparison rejects a dataset whose meta quantity differs from the model's - Joint prior blocks: the declared dimension is checked at compile, and a one-parameter block of a scipy univariate is that parameter's marginal (which also fixes log_prior on numpy >= 2.4); the rvs contract is documented as scipy's rvs(size=n, random_state=rng) - A prediction of the wrong length raises, naming the comparison - StudentT() defaults nu to Gamma(2, rate 0.1) truncated to nu >= 1, so the default compiles and nested-samples - A parametric covariance singular at theta is zero density, not an exception - Predictor keeps the meta it was bound with, so total_predictive_band amplitudes can read c.meta at the prediction points - predictive_draws under StudentT draw from the multivariate t - Problem.log_jacobian weights each constraint's Jacobian by its weight - Masks are copied, a scalar space derivative gives a per-point Jacobian, and a non-finite constraint weight is rejected - design.md's held-out example passes given= for the GP rung
- README, the docs index and installation pages and the package docstring no longer say 1.0 lives on the rewrite branch, and they say how to pin 0.x at tag v0.1.0 (branch legacy/0.x) - publish.yml publishes only v1 and later tags, and refuses a tag that does not name the version setuptools_scm builds
- Cell 13 passes given=p_fit to heldout_log_predictive and predictive_draws: the L2y normalisation and the Lgp process both span the 90-degree cut, so the honest held-out density is p(y_held | y_fit, theta) (review finding) - Fix the stale nested() call left when 39b7165 renamed it fit_nested() - Re-executed; the takeaway follows the new held-out scores and coverages
Silent wrong answers:
- A block whose covariance is constant is checked for singularity at
compile even when another block is parametric, instead of reading as a
zero density at every theta
- The eigen fallback of _psd_factor is lower-triangular, so held-out scores
and conditionals that treat it as a Cholesky factor are right
- Kernel jitter is relative to the block's mean variance, so it no longer
swamps small (b/sr) variances
- The finite-difference derivative step is relative to the data
- Marginals truncated far in the upper tail use sf/isf, and prior_transform
is clipped to the bounds
- A bounded frozen-MVN joint prior is renormalised by its in-bounds mass
(seeded, so compiles are deterministic); custom joints must be normalised
- A dataset whose rows are active in two weighted constraints warns
- compare_logz ties at the boundary; it and logz_summary reject NaN
- The Student-t Gamma ratio uses betaln, exact at huge nu
Crashes and misleading errors:
- kernel() with fixed hyperparameters and parametric coords constructs
- dataclasses.replace on a Term no longer duplicates the coords parameters
- Callable terms with the default coords see x as the dataset holds it
- Provenance tuples and 0-d arrays in meta stack at compile
- ElasticXS("dXS/dRuth") with a neutral projectile fails at bind, by name
- One bare callable used as the space of several comparisons is one space
- A kernel whose support is fully masked says so
- NaN or negative norm_err/offset_err and NaN angles are rejected
- from_measurement refuses LAB-frame angles
- A notebook listed in the index but missing fails instead of xfailing
- Delete examples/correlated_observations.ipynb and drop its cross-references in recipes 5 and 37; recipe 37 keeps its closed forms and its recipe test - Rename measurement_to_calibration to local_optical_model_calibration - New recipe 39, iterative outlier rejection: the outer loop of problems with the mask refit between runs, which the chain-dependent-masks entry of "What this API does not express" already named as the sanctioned workaround, with its recipe test - Recipe 4 gains the per-dataset spelling (one magnitude per comparison), for an experiment that reports no systematic uncertainty at all - examples/plotstyle.py: shared rcParams, a colourblind-safe palette, hatched predictive bands and corner defaults, and the CI format job now covers it
- Smaller cells: setup, the run, post-processing and each plot stand apart - LaTeX for every symbol, and no unicode greek - A colleague-style narrative with links: Bayesian inference, the prior, chi^2 and the Mahalanobis distance, MCMC, Goodman & Weare's ensemble sampler and Foreman-Mackey et al.'s emcee, the posterior predictive - Plots through examples/plotstyle.py, and .bind(x_fine) without the empty dict that the review asked about - Dropped the empty trailing cell - Same data, seeds and sampler settings, so the fit is the one it was
- examples/error_models.ipynb keeps the one-dataset covariance ladder (recipes 2, 4, 19); the two-dataset study moves out - examples/sharing_error_models.ipynb is new (recipe 5): sharing a parameter against sharing a mode, a normalisation mode per dataset, one mode spanning both, and the assembled covariance shown directly. It also takes over case A, which the deleted correlated_observations notebook used to carry - Both get the review's general pass: smaller cells, LaTeX, a colleague-style narrative with linked references (Peelle's Pertinent Puzzle, D'Agostini, Fruhwirth et al.), plots through plotstyle with hatched bands - The commentary now matches what the fits actually print: inferring the noise covers the truth but triples the slope error, and case A, declared for two experiments that drifted apart, inflates until the line says nothing
- robust_likelihoods keeps the Student-t study (recipe 9) and gains the
iterative rejection of recipe 39: fit, drop the points more than three pulls
away, refit until the mask settles. The first round over-rejects a good
point and the second puts it back, which is the argument for the loop
- examples/error_scale_and_usu.ipynb is new (recipe 34): the global scale on
the reported errors under both likelihoods, and the USU offset on the
technique we suspect, with Hanson and Capote et al. linked
- Includes the markdown you had rewritten in your working tree, with the three
typos fixed ("must the the same", "as a a unknown", "This could demo, i.e.")
- The general pass: smaller cells, LaTeX, plotstyle with hatched bands,
.bind(x) without the empty dict
- Both halves redraw their data in the original RNG order, so every number is
the one that was committed before
- a_0 = 0 and not inferred, as the review asks. That alone leaves the overall
scale unidentifiable, so one experiment is now absolutely normalised and the
rest are relative to it; the notebook says why
- A settings dict of five experiments, easy to comment in and out, with
hand-picked renormalisations: three consistent with what was quoted, one
quoted at 3 % that is really 15 % off and alone in its range, and one that
quoted 25 % it never needed
- Six cases in two groups. Correct: the quoted modes, an inferred
normalisation per dataset (recipe 6), an inferred systematic magnitude per
dataset (recipe 4). Wrong: Peelle's mode from the data, systematics
ignored, statistical errors inferred instead
- Believing the bad quote distorts the curve while its parameter pulls stay
innocent, because the coefficient errors explode: RMS 1.27 against 0.004 for
the best case. Both inferring cases recover it, and the inferred systematic
for the mis-quoted set comes out at 10 % against the 3 % quoted
- Peelle's puzzle gets the two-point panel where it actually bites, reproducing
D'Agostini's closed form exactly (0.8333)
- New test: a LaTeX macro in a plain string makes a control character
("$\rho$" is a carriage return), which is how the first rebuild of this
notebook broke. The guard walks the AST, so it sees f-strings too
- Only mean-zero GPs now, per the review: the sampled Legendre mean correction is gone, so this notebook teaches recipe 7 alone - Kennedy & O'Hagan framed at the top, with the distinction between learning the covariance of a mismatch and giving the mismatch its own parameters - Amplitudes grow with x through T.exp_growth_amplitude, which is the prior knowledge that the data stop looking like a line at large x - The toy is now a line plus a defect growing as 0.03 x^2, so (m, b) have true values and the corner shows what each error model does to them: statistics only is 60 sigma out and confident, a diagonal model error covers only by becoming useless, a constant-amplitude GP is still 2.6 sigma out, and the growing amplitude lands at 0.4 sigma - The optical-model half gets the same three rungs and its own random generator, so changing the toy no longer silently changes its data. The GP wins on evidence by 570 log units and recovers V_v, while W_v stays nine sigma out because volume and surface absorption are degenerate at one energy - The learned discrepancy is now read off total_predictive_band, which knows about the amplitude, rather than from the bare kernel, which does not - Registers the recipe sets for the two notebooks whose rebuilds are still executing (local_optical_model_calibration, alpha_ca_error_model_comparison)
- Theory is always drawn on a fine angle grid. The curve at theta_0 was evaluated at the downsampled data angles, which aliases the diffraction pattern and is the ragged plot the review flagged - Evidence and Bayes factors are introduced before the table, with links, and with the two caveats that matter: a Bayes factor depends on the priors, and evidences in different comparison spaces need the Jacobian first - New section (recipe 17): posterior predictive draws that carry the covariance, plus an empirical coverage curve. All three rungs over-cover in sample (0.79, 0.81, 0.78 against a nominal 0.68) while separating sharply out of sample (0.49, 0.60, 0.80) - The TODO intro is replaced, keeping the EXFOR, Oeschler, jitr and Kennedy-O'Hagan links - The general pass: smaller cells, LaTeX throughout, plotstyle with hatched bands. Every number is unchanged: Lgp still wins the evidence by 6.0 to 10.9 log units and the held-out score at -50.45
- Real data: EXFOR O1199007, p + 40Ca elastic at 35 MeV, ratio to Rutherford, 59 angles, 2.3 % statistical errors, committed as a CSV so the notebook runs anywhere. The exfor_tools query is shown in the narrative, including that EXFOR spells elastic (P,EL) and a product tuple silently returns nothing - The SimpleNamespace stand-in is now a dataclass, as the review asked, and it still exercises from_measurement: the unit contract, the CM-frame check, and the ratio-to-absolute conversion through the Rutherford closed form - This entry quotes no systematics at all, which changes the notebook's spine. Three error models are compared instead: the quoted errors alone, an inferred normalisation (recipe 4), and an inferred model error (recipe 26, which this notebook previously cited without ever demonstrating) - The result is worth the rewrite. A normalisation buys almost nothing (log Z -3361 against -3479) because it rescales every angle alike, while an inferred model error takes chi2/N from 122 to 0.9 at delta = 30 %: a seven-parameter local potential describes this measurement to 30 %, not to 2.3 % - Answers the review's question about the toy: the truth *is* covered, at 0.3 sigma; the old corner range squeezed the posterior into a dot. Tempered and untempered predictive posteriors are now compared by coverage as well - Charged projectile, so the potential gains a Coulomb term, and the quantity check keeps a ratio measurement from being fitted with an absolute model
The control-character map was written as a one-line dict that exceeded the line length; black splits it. No behaviour change.
- Eight schools now stands on its own: BDA3 cited and linked, the data explained, and no pooling / complete pooling / partial pooling laid out before the non-centred spelling, so a reader need not have read chapter 5 - The bumps are 65 % of their old size, chosen by an A/B at the notebook's real sampler settings rather than by eye. The misspecified fit still fails clearly (coverage error 0.52 in sample, 0.45 held out) while the hierarchy repairs both to 0.18 and wins the held-out score, 20.3 against 7.7 - New plot: y_true(x; E) and y_data(x; E) at several energies, colour-coded by energy, offset in y for legibility and labelled with plt.text - New plot: predictive draws after calibration in that same layout, with the three cases told apart by hatching rather than colour - The hierarchy ties the correct mapping on evidence (142.28 against 143.07) while both sit 230 log units above the misspecified fit, and pays for its held-out prediction in width: 0.202 against 0.062 - Fixes the narrative that called an absolute error of 0.03 "honest 3 % errors" - The general pass: the 81-line case builder is now three cells, LaTeX throughout, plotstyle, links
- rx.predictive.grid_draws draws the posterior predictive on any grid by re-evaluating each covariance term from its own definition at the new points: inferred noise, fractional noise, model error, normalisation and systematic modes, parametric matrix terms and GP kernels all carry over. Point-by-point terms (reported statistical errors, fixed arrays, per-point magnitudes) raise, naming the term and the ways out. At the measured points it matches predictive_draws, and it handles Student-t, physical=True and constraints spanning several comparisons - gp_predictive_draws replaces total_predictive_band: unconditioned grid_draws on the kernel's constraint, plus conditioned=True for GP regression on the residuals; n_draws becomes n_rep - predictive_draws gains terms= and statistical= to choose which parts of the error model a draw carries; combining them with given= raises - Breaking: all three draw functions return a percentile band by default and the draws with return_draws=True; every caller feeding coverage or sharpness now passes it - StructuredCovariance.matrix(entries=) and CompiledConstraint.entries_for build a covariance from a subset of terms - New TestGridDraws suite and recipe 40, "Predict on a new grid, error model included"; recipes 7, 15 and 17, design.md, groundup_design.md and api.rst updated - gp_discrepancy: rebuilt around mean-zero discrepancies with the three predictive objects written out, the band next to the data with its coverage, and the envelope of departures the data allow - alpha_ca: a fifth rung, Lgpn, whose GP amplitude grows with angle; it wins on evidence (dlogZ 3.5 +/- 1.3 over Lgp) and held-out log predictive (-47.8 against -50.5), and a new section shows where the potential fails - Both notebooks rewritten in the walkthrough voice with links (Gaussian process, Matern kernel, Bayes factor, nested sampling, Kennedy & O'Hagan, Skilling, Speagle, Vehtari et al.), calculation and printing split into separate cells, and the evidence verdict printed as words - The other notebooks draw model-only bands with grid_draws(model_only=True) - design.md runtimes re-measured solo: gp_discrepancy 483 s, alpha_ca 1280 s
… coverage - The narrative moves to the walkthrough voice with links to the Bayesian vocabulary, a note on Black Box Bayes, and typo fixes - The fit infers a constant noise sigma instead of trusting the reported errors (0.114 +/- 0.020 against a reported 0.1), so the error model is a function of x that can travel to a new grid - The posterior predictive on the fine grid contrasts the line's band with a new measurement's, and explains the predictive_draws / grid_draws split and why reported per-point errors cannot be forecast; a demo cell shows grid_draws refusing them - Coverage is shown for both: the model alone undercovers (55 % at a nominal 90 %) while the measurement band follows the diagonal - The chi2 cell also checks log_likelihood and explains the log-determinant - Walkers start in a small ball about the prior mean; prior draws stranded a walker at a huge sigma and inflated the posterior of b
Both factories built the same diagonal term scaled by a basis; the only difference was which basis. One factory with an `averaging` flag says it once: `z = ym`, or `z = 0.5 * (y + ym)` when `averaging`. Note the default changed. `model_error` defaulted to `averaging=True`; `proportional_error` defaults to `False`, the old `noise_fraction` behaviour. A caller porting `model_error(delta)` by name substitution silently moves to the `ym` basis and must pass `averaging=True` to keep the KDUQ spelling, as recipe 26 and the gp_discrepancy notebook now do. Renamed throughout the docs, the recipes, the tests, and gp_discrepancy.
`from_measurement` only ever read attributes off its argument, so an `exfor_tools` Distribution worked and a dict of the same fields did not. `_as_record` wraps a Mapping in a SimpleNamespace and checks the eight required fields up front, so a missing one raises naming itself rather than surfacing as an AttributeError halfway through the conversion. `x_units` and `subentry` stay optional. This is what the optical-model notebook needs to build a Dataset from the EXFOR entry it types out by hand.
`reported_terms()` built the normalisation mode from `_reported(norm_err, n)`, which broadcasts a scalar to a per-point array. An array has no value away from the measured points, so `grid_draws` had to drop the term and the predictive on a fine grid lost the reported normalisation. A scalar `norm_err` is a fraction of the prediction and nothing else, so it has a value anywhere: keep it scalar and the mode stays a function of `c.ym`, exactly like `T.normalization(magnitude=)`. An offset, or a per-point normalisation, is still defined only at the measured points.
State the model as `y_i + eps_i = eta(x_i) = y_m(x_i; m, b)` before the priors, so the likelihood that follows is read off the equation rather than asserted, and say which predictive to compare against the truth and which against data. The walker-ball paragraph stays: the code still starts from `theta0`. Re-executed end to end, so the execution counts are sequential again and the `%%time` on the sampler reports a real number. `_python` in test_notebooks_index strips magics before `ast.parse`, which otherwise fails on `%%time`.
The notebook jumped straight to the covariance ladder. Start instead from counts in a detector: binomial, Poisson in the small-bin limit, normal in the many-count limit, and a diagonal multivariate normal whose log is -chi^2/2 -- which makes plain what the three assumptions behind least squares are, and therefore what each rung of the ladder relaxes. Also drops a trailing empty cell.
With one normalisation mode spanning both experiments the posterior grows a long thin tail: the shared scale runs away and the line is barely constrained. emcee walkers that wander in stay in, and a few stuck ones move the means and widths the notebook reports. Nested sampling works inwards from the whole prior and does not get stuck that way, so this notebook now uses dynesty and says why. The comparison plot gets one panel per error model instead of four bands over each other.
Student-t and outlier rejection both answer "this point does not belong to the measurement". Tempering is reached for in the same spirit but answers something else, so the notebook now ends by trying it on a correctly specified 200-point line: the prior on the corner plot, the posterior widening with the weight, and what that does to predictive coverage. Recipe 12 joins the notebook's citation line and the design's table.
Both now compare in log space with the same error model the jitr quickstart uses -- reported statistics plus an inferred point-to-point and an inferred common relative error, written as custom terms -- rather than each inventing its own ladder. local_optical_model_calibration reads EXFOR O1199007 from a plain dict (no exfor_tools import), and scores the jitr model against linear residuals with the reported errors alone: by evidence with the Jacobian, by the predictive for the potential alone on a grid and the full predictive at the measured angles, and by three coverage curves each. alpha_ca_error_model_comparison keeps the Matern GP in angle, with its length-scale prior spanning one point spacing to the full range, and compares a constant amplitude against one growing as an inferred power of q. Its cut is shorter than the full study, which section 3 of the design still describes. Citation lines and the design's table follow the new contents.
`--ExecutePreprocessor.record_timing` writes an iopub timestamp block into every cell's metadata, which re-dates the whole file on each run and says nothing. The other notebooks carry none; these two now match.
One cell carried execution count 15 among cells 1-12, so it had been re-run after the ones below it and the stored outputs no longer provably came from the stored source. Executed end to end.
The rewrite cut the five experiments down to four and renamed them exp 0..4 -> exp P..S, but stopped before the end of the notebook, and the file was committed with the failure in it: the cell defining `free` was deleted while eight uses of it remained, so cell 24 carried a NameError and every cell after it was unexecuted. Past that break the covariance gallery still indexed `comps["exp 0"]`, `comps["exp 1"]`, `comps["exp 2"]` and `datasets["exp 0"]`, which raise KeyError, and a plot title still read "Five experiments, five normalisations". Every dataset has a non-zero quoted systematic here, so `free` is just `comps`. The prose that pointed at `exp 3`'s 3 % quote and `exp 4` needing none of its 25 % now points at `exp R`, 20 % off against a 5 % quote, and `exp Q`, 20 % off against a quote of 25 % -- the two the table below actually shows. The paragraph before the band plots says which of them draws residuals, since only the second one does now. Also drops an unused `minimize_scalar` import and a commented-out duplicate of the sampling line, and re-runs the notebook end to end: 23 cells, sequential, no errors.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Significant re-write, superseding #43 and #42