Skip to content

Shared libraries

Two pure, DOM-free, dependency-free ES modules carry everything the apps compute.

lib/met-stats.mjs — the verification math (708 lines, 129/129 self-test)

Section titled “lib/met-stats.mjs — the verification math (708 lines, 129/129 self-test)”

The single source of truth for MET-style statistics, reconciled from the seven original apps. Conventions: a 2×2 cell is {a,b,c,d} = {FY_OY, FY_ON, FN_OY, FN_ON}; an SL1L2 line carries the means {fbar,obar,ffbar,oobar,fobar} + n exactly as MET writes them; every metric returns NaN (never throws, never Infinity) on degenerate denominators.

Group Exports
Categorical (2×2) baseRate fcstRate podRate far pofd sr csi fbias gss hss pss orss categoricalFromCTC
Continuous from SL1L2 me mse rmse bcrmseFromSL1L2 pearsonFromSL1L2 continuousFromSL1L2 sl1l2FromPairs
Continuous from pairs mePairs maePairs msePairs rmsePairs bcrmsePairs pearsonPairs continuousFromPairs maeFromSums
Vector wind (VL1L2) vectorContinuousFromVL1L2 (FBAR, OBAR, FS_RMS, OS_RMS, MSVE, RMSVE)
Aggregation sumCTC sumSL1L2 aggregateCategorical aggregateContinuous weightedMean — and the teaching demonstrator wrongMeanOfRatios
Ensemble rankOne rankHistogram classifyRankHist crpsOne crpsAggregate ensembleSpread ensembleEventProb perCaseSpreadSkill spreadSkill contingencyFromEnsemble
Probabilistic brierDecompFromBins (Murphy decomposition) reliabilityDiagram
Formatting fmt (NaN → em-dash, ±Infinity → ∞)

The aggregation contract is the lab’s core fidelity rule: sum raw counts / partial sums first, derive the metric second (ratio-of-sums). wrongMeanOfRatios exists only so apps can show the incorrect value next to the correct one.

lib/met-stat-parse.mjs — the .stat parser (490 lines, 97/97 self-test)

Section titled “lib/met-stat-parse.mjs — the .stat parser (490 lines, 97/97 self-test)”

Header-driven and version-tolerant: it reads the 24-column common header from the file (or recognizes headerless .stat), then applies per-line-type column schemas confirmed against the MET v12.2 source (not just docs).

Group Exports
Core parseStat parseMode columnNamesFor COMMON_HEADER
Line-type adapters ctcCell sl1l2Line vl1l2Line vcntStats pctBins pstdStats prcPoints rhistBins ecntStats orankRecord modeCtsCell modeObject

Contract: common-header fields come back as strings (they are untrusted display values); statistics are numbers or null (MET’s NA).

  • 6,329 .stat files, 88,456 records, 0 parse errors (full 62 GiB archive).
  • Independent oracles: 32,389/32,390 SL1L2→CNT and 7,038/7,038 VL1L2→VCNT recomputations equal MET’s own paired output lines.
  • The parser’s fixtures are real MET lines — a lesson from the N_THRESH incident, where hand-written fixtures shared the code’s wrong assumption and 76/76 tests passed over a bug.

lib/met-data-source.mjs — the data funnel (built)

Section titled “lib/met-data-source.mjs — the data funnel (built)”

The blueprint-§2 normalization + selection layer, now real: .stat text (or the compact public bundle) → normalized per-case records keyed by (model, var@lev, lead, obtype, desc, interp, mask, thresh, cycle) carrying raw aggregables, with select(), aggregateCTC/SL1L2/VL1L2() (ratio-of-sums), series() (optionally with per-point bootstrap CIs), and toBundle()/fromBundle() — the de-identified columnar wire format apps 02/04/12 stream from the site root (3.6 MB raw, ~0.8 MB gzipped, 44,228 cases).

Selftest: 65/65 including a full-archive pass where every sampled single-case aggregate reproduces MET’s own paired CNT line (471/471). That oracle pass caught two real data-model traps during development: MET emits lines distinguishable only by DESC (same OBTYPE, different obs source — pooling them is wrong, so desc is in the key), and one model’s upper-air lines carry FCST_LEAD=000000 with the true lead only in the filename (fromStatTexts(texts, {names}) repairs exactly that case).

De-identification note: the real-name→alias map is not in this public module — publishing the mapping would reveal what it hides. tools/build-real-bundle.mjs takes it as build-time CLI input and hard-fails if any source token survives in the output; cycle timestamps are always replaced by ordinal ids.

lib/met-mode.mjs — object-based verification (built)

Section titled “lib/met-mode.mjs — object-based verification (built)”

A faithful-core MODE engine: missing-aware circular-disc convolution, 8-connected object identification, single-object attributes (moments, convex hull, intensity percentiles), pair attributes, MET’s fuzzy-logic total-interest engine (MODEConfig_default weights, configurable piecewise maps), matching and union-find cluster merging. Selftest 42/42 (hand-worked geometry + invariants on the real case; no MODE oracle exists in this archive — stated honestly). Powers the MODE Lab.

bootstrapCI(items, statFn, {B, alpha, seed, method: 'percentile' | 'bca'}) — true case-level bootstrap with deterministic seeding and a jackknife-accelerated BCa option; the lib selftest grew to 140/140 (coverage against a known truth, reproducibility, degenerate inputs, BCa behavior on skewed statistics). Measured cost ~0.4 ms per CI at B=1000 — cheap enough that apps 02/04 recompute bands on every interaction.