The registry¶
The registry is the single front door. Everything is addressed by a key
(property, gravity, redshift); there is exactly one artifact per key.
from haloemu import get_registry
reg = get_registry()
reg.predict(prop, gravity, z, theta, **kw) # the only call you usually need
Keys¶
The canonical key string is "<property>/<gravity>/z<z:.2f>", e.g.
"hmf/LCDM/z0.25". On disk:
indexed by haloemu/manifest.json. List everything:
Redshift snapping¶
Float redshifts are snapped to the nearest registered key within Z_TOL = 0.005
— there is no exact-float matching. Currently registered redshifts:
- z = 0.25 — all properties, both gravities.
- z = 0.00 — the matter sector only (
hmf,pk_mm,xi_mm×{LCDM, fRn1}). Clustering (xi_hh,r_ab), bias, and velocity at z = 0 are not yet registered.
A redshift with no registered artifact within tolerance raises FileNotFoundError.
Two kinds of entry¶
The registry treats two plugin kinds uniformly through predict():
trained— a pickled artifact carrying weights. Itsdependsare train-time data dependencies: if the upstreamhalocatproduct changes, you retrain.predict()callsartifact.predict(theta, **kw).derived— a recipe with no weights (b_diff,xi_hh). Itsdepends_onartifacts are resolved through the registry at predict time and combined byplugin.derive(). Predict-time recipe deps are pinned to the upstream artifact's content hash, so an upstream change forces a re-pin + re-validate.
MGBoostEmulator (the f(R) boosts) is a trained artifact that embeds and pins
its ΛCDM base artifact — see Representations.
External dependencies (e.g. colossus for the EH98 baseline of
pk_mm/xi_mm) are recorded in the manifest but never resolved by the registry;
you supply them in the env. b_diff no longer has any — its n̄ comes from the
in-suite hmf artifact (the gated freyja→hmf swap).
θ — parameter vectors¶
The theta argument is a raw parameter vector in a fixed order:
| Gravity | theta |
|---|---|
LCDM |
[Omega_m, h, n_s, S_8] |
fRn1 |
[Omega_m, h, n_s, S_8, logf_R0] |
Pass S_8, not σ_8
S_8 = sigma_8 * sqrt(Omega_m / 0.3). The GR fiducial σ₈ = 0.8159 gives
S_8 = 0.827914. Passing σ_8 silently produces a wrong (but plausible)
prediction.
logf_R0 is log10(|f_R0|) for the f(R) n = 1 model.
Design (validity) ranges¶
Predictions inside the design hull are validated; outside it the GP extrapolates and is unvalidated.
| Parameter | Range |
|---|---|
Omega_m |
[0.15, 0.445] |
h |
[0.596, 0.795] |
n_s |
[0.94, 0.989] |
S_8 |
[0.65, 0.945] |
logf_R0 |
[−7, −4.05] |
Known θ vectors¶
from halocat.cosmology import get_cosmology, theta_keys
keys = theta_keys("fRn1") # ordered parameter names
th_f5 = [get_cosmology("fRn1", 0)[k] for k in keys] # F5n1 fiducial (logf_R0=-5)
th_f6 = [get_cosmology("fRn1", -1)[k] for k in keys] # F6n1 fiducial (logf_R0=-6)
# LCDM fiducial: get_cosmology("LCDM", 0); design models: imodel 1..64.
The two f(R) fiducials (imodel 0 = F5n1, -1 = F6n1) each have 100 measured
boxes and serve as the sharp out-of-sample references.
Artifact introspection¶
art = reg.load(prop, gravity, z) # the unpickled trained artifact
art.coord # 1-D coordinate grid (log10M / k / r)
art.theta_keys # the parameter names this artifact expects
reg.entry(prop, gravity, z)["accuracy"] # the manifest accuracy block
reg.predict(prop, gravity, z, theta, return_var=True) # (mean, variance)
Surface artifacts carry extra axes: r_ab has art.thresholds (both matrix
axes); the vel_* moments have art.pair_keys and art.r.