Skip to content

Changelog

Release: uv version --bump patch|minor|major, move the "Unreleased" notes under the new version, commit, tag vX.Y.Z and create the GitHub release (publishes to PyPI).

Unreleased

Added

  • Registry operations:
  • class-e search -p NAME[=LO:HI] -o OBS --class NAME --kind emu|data [--json]: find published files by parameters (and prior range covered), observables and CLASS build. publish records the space's box and build and each file's observables. class-e list --json.
  • class-e release --registry-file F: one Zenodo record per registry release holding every file; later releases are new versions under one concept DOI (added to every space's cite); new files get a zenodo source; --sandbox, --dry-run. Replaces publish --to zenodo (one record per file).
  • class-e registry check FILE [--download emu|all] [--reachable] [--strict] and class-e registry init DIR (registry.json, README and a GitHub Actions workflow running the check on pull requests and weekly).
  • Cobaya: ClassE warns when the model is built if the prior reaches outside the bundle's box or constraints (prior_check: 1000 samples; 0 turns it off). class_e.cobaya.check.prior_coverage.
  • Library: class_e.hub.search, class_e.hub.release, class_e.hub.audit, class_e.hub.scaffold.
  • Published datasets, publish, lineage, reproduce:
  • Datasets in registries (kind: data, split, meta_sha256 for the sidecar), named name#split wherever a dataset path is accepted (class-e train --dataset lcdm#train).
  • class-e download data NAME [--split S], or --for BUNDLE for exactly the sets a bundle was trained and tested on (by sha256). Downloads over 100 MB are confirmed (--yes).
  • Hugging Face sources (host: hf, pinned to a commit; plain HTTPS, $HF_TOKEN for private repositories), Zenodo sources (host: zenodo, meta_url).
  • class-e publish FILE --space S --registry-file F --to file|github|hf: refuses files without a recorded space, from a CLASS build with uncommitted changes (--allow-dirty) or of another space than the registry's; numbers versions; --dry-run; confirms before uploading. Extra class-e[hf] for Hugging Face uploads.
  • class-e lineage NAME|PATH (bundle, training and test sets, their settings, CLASS build and where to get them) and class-e reproduce NAME|PATH (retrain from the recorded datasets and configuration, compare errors and predictions).
  • Library: class_e.hub.publish, class_e.hub.uploaders, class_e.hub.lineage.
  • Parameter space and CLASS build: datasets (sidecar) and bundles record meta["space"]. It holds the parameters (box, aliases, drop), to_class expressions, constraints, physics CLASS settings (not output selection such as output, l_max_scalars, z_pk), lensing, and the CLASS build (name, version, git commit, +dirty.<diff hash> for uncommitted changes), with a sha256 fingerprint. classy_info() now reports the build's name and git state from its checkout (e.g. AxiCLASS @ commit); theory.classy.name names a build. merge refuses chunks of different spaces, stitch refuses bundles of different spaces, and downloads whose fingerprint is not the registry's are refused. class-e info shows the space, the build and the training-set size; class-e list shows the registry's CLASS build. New: class-e diff A B (space, inputs, outputs, training, software) and class-e verify NAME|PATH (registry sha256 and space, array hashes, reference predictions). Library: class_e.core.provenance, class_e.hub.verify.
  • Fixed: a bundle trained with test_dataset recorded its path and sha256 from the configuration string; it now records the file actually read. class-e info showed a recorded CLASS build without its commit.
  • Published emulators by name: [registry/]name[@variant][:version] (lcdm, lcdm@jax, fzu/ede@sklearn:2) wherever a .cemu path is accepted (class-e info, sample, EmulatedCosmology.load, Cobaya bundle:); downloaded on first use, checked against the registry's sha256 and cached by content ($CLASS_E_CACHE). class-e list, class-e download emu NAME --backend jax, class-e registry list|add|remove|refresh, class-e cache path|remove|prune; offline use with --offline / $CLASS_E_OFFLINE=1 / Cobaya offline: true. Registries (registry.json, schema class-e-registry/1) are configured in ~/.config/class-e/registries.yaml; sources over HTTP(S) (resumed) or a file system, mirrors tried in order. Library: class_e.hub (resolve, lookup, install); see docs/published-emulators.md.
  • Cobaya theory class_e.cobaya.ClassE: a bundle in place of classy (theory: {class_e.cobaya.ClassE: {bundle: model.cemu}}), likelihoods unchanged. It provides lensed (or unlensed) Cl with classy's units and ell factors, Hubble, angular_diameter_distance(_2), comoving_radial_distance from the distance emulator (with its curvature), and derived parameters from the scalar observables (rdrag, H0, h, ...); only requested products are predicted. Parameters are mapped by name, the bundle's aliases, known conversions (logA from A_s, h from H0, theta_s_100 from 100*theta_s, ...) or input_map, with classy's renames; points outside the training box or its constraints get zero likelihood (out_of_bounds: reject). Unsupported requests, unread parameters and missing inputs fail when the model is built. Checked against classy on Planck plik lite, low-ell TT/EE, DESI DR2 and Union3. Extra class-e[cobaya]; see docs/cobaya.md.
  • class-e cobaya check INFO.yaml: a Cobaya input against its ClassE bundle, without likelihood data: errors that would stop the model from building, and the prior volume outside the emulators' domain, per input and constraint (Cobaya's own parameterization samples the prior). Exits 1 on errors. Library: class_e.cobaya.check.check.
  • class_e.theory: ParameterAdapter (sampler names to bundle inputs, differentiable) and EmulatedCosmology (a bundle's spectra, distances and scalars in CLASS units), with no sampler import.
  • Trained bundles store every grid of the dataset and meta["theory"] (parameter aliases, drop, to_class expressions, fixed CLASS settings, CLASS build, T_cmb, Cl convention).
  • class-e train CFG --learning-curve 64,128,256,512 [--plots DIR]: the test error (p50, p99) and the PCA compression floor of emulators trained on the first N points, for each N, with a one-line reading per observable (still improving with data / on the compression floor: raise n_pca / flat above the floor: the emulator is the limit), a log-log figure and the numbers as JSON. Library: class_e.commands.training.learning_curve.
  • class-e train CFG --pca-curve 6,12,24,40 [--plots DIR]: the same for the number of PCA components (full training set; n_pca forced in every observable and segment), with the gain of each step, a reading (more components still help / no gain beyond n: the GP or the data are the limit / levelling off), the recommended n_pca (smallest within 10% of the best p99, circled in the figure) and pca_curve.{json,pdf,png}. Library: class_e.commands.training.pca_curve.
  • sklearn GP fits no longer print sklearn's ConvergenceWarnings (noise at its 1e-8 floor, L-BFGS "ABNORMAL" line searches): they come from every optimizer start and are expected on noiseless simulator outputs. They are counted in FitResult.details["convergence_warnings"]; GaussianProcessPCA.hyperparameter_notes() reports the final kernel's hyperparameters at a bound (e.g. an input whose length scale hit its upper bound barely matters), and class-e train prints those as one GP: line per observable (report["fit_notes"]).
  • InputTransform (class_e.stats.inputs): train any emulator on expressions of the physical parameters, e.g. {"s": "w0 + wa", ...}, with the interface, bundles and gradients still in the physical parameters; no measurable prediction overhead. Bundle kind input-transform. SegmentedEmulator segments use the same machinery.
  • samples.seed in the YAML: compute_dataset and class-e generate use it, and the seed is recorded in .meta.json (seed= still overrides it).
  • merge_datasets(..., max_failure_fraction=).
  • CLI command groups as self-contained Typer apps in class_e.commands (importable functions, runnable on their own, merged into the flat class-e CLI):
  • class-e generate CFG --design train|test --seed S --chunk i --n-chunks K --checkpoint-every C: one chunk of a design, resumable from its checkpoint (generate_chunk);
  • class-e merge PREFIX -o out.npz [--max-failure-fraction F] (merge_chunks) and class-e status DIR [--json] (chunk_status);
  • class-e train [train.yaml] [flags]: YAML-driven training with shared defaults, per-observable settings, inputs (InputTransform) and ell segments; the flags override the YAML or replace it (load_train_config, build_emulator, train);
  • class-e evaluate BUNDLE --test TEST [--ell-ranges] [--by "EXPR:EDGES"] [--worst N] [--json]: errors per ell range and per bin of any parameter expression, compression floor, worst points (error_report, evaluate_bundle).
  • samples.designs in the generation YAML: several designs (e.g. train/test) sharing everything else; parse_config(path, design=).
  • reconstruct(Y) on the GP+PCA emulators (and the wrappers): the compression floor, i.e. the public way to apply a fitted emulator's output transform and PCA.

Changed

  • Dependencies live in pyproject.toml only; dev-requirements.txt is gone. Extras are user features: plot, ui, jax and the new classy (CLASS from PyPI; other builds are still selected with --classy). Development tools are uv dependency groups, never published: test, lint (ruff, codespell; black and flake8 dropped), docs (no longer an extra), notebooks, and dev = test + lint + docs, installed by default with uv sync. pytest-runner, build, wheel, twine and bump-my-version are dropped (uv build, uv version --bump).
  • class-e train and class-e generate moved to class_e.commands; class-e train no longer imports the marimo notebook, so it works without the ui extra (polars); class-e inspect and train -i say so when the extra is missing.
  • dev/cluster/ uses the CLI (generate_chunk.py, merge_chunks.py, status.py removed); configs/w0wacdm-mnu-theta-act.yaml defines its train/test designs.
  • With compute_dataset(rows=...) the CLASS failure limit is no longer applied per chunk (one failure in a small chunk aborted it, and again on every resume); merge_datasets checks it over the whole merged design, and chunks must share the design seed.
  • Failed points are recorded with their parameters and CLASS's full error message, meta["failed"][row] = {"theta": {...}, "error": ...}, keyed by row of the full design.

Fixed

  • The sklearn GP crashed in predict with n_pca: 1 (one component came back 1-D).
  • tests/test_class_loader.py ran CLASS loading at import and left a custom classy on sys.path for later tests; it is now an isolated test.

0.0.4

Fixed

  • Latin hypercube designs (lhc, and cov) ignored the seed: scipy's qmc.LatinHypercube does not use NumPy's global random state, so the seed now goes through rng=. Seeded LHC designs are reproducible, and chunked LHC generation (compute_dataset(rows=...), dev/cluster/) draws the same design in every chunk. LHC datasets generated before this fix cannot be redrawn from their seed (their stored theta is still valid).

0.0.3

Added

  • EmulatorBundle (.cemu): pickle-free save/load of emulators with checksums and a reference-prediction self-check (class-e info).
  • JAX VAE+GP emulator (GaussianProcessVAEJAX), true ARD kernels for the JAX GP, and output standardization (standardize_Y) for the sklearn and JAX GP+PCA backends.
  • ReparametrizedEmulator (learned input map, e.g. h -> 100*theta_s) and SegmentedEmulator + class-e stitch (emulators on separate ell ranges, blended).
  • Data generation: Sobol sampling, sampling constraints (samples.constraints), CLASS failure handling with retries, transfer-function observable (Tk), explicit observables: and stored theory.classy.ell_max in YAML, row chunks (compute_dataset(rows=...)), checkpoint/resume, merge_datasets, cluster scripts in dev/cluster/.
  • Configs for massive-neutrino LCDM and w0waCDM (Planck range and ACT/SPT-grade).

Fixed

  • Parameters sampled as 100*theta_s: class-e solves for h itself; CLASS v3.3's shooting silently returned a wrong h in much of the w0waCDM box.
  • Aliased parameters (omega_cdm, A_s from logA) not reaching CLASS.
  • P_k_max silently dropped with non-linear lensing.
  • Expressions stored in bundles are parsed, never eval-ed.

Changed

  • class_e.__version__ is read from the package metadata (pyproject.toml is the single source); bump-my-version replaced by uv version.
  • PyPI workflow: uv build and trusted publishing.

0.0.2