End-to-end workflow#

This guide starts from YAML, constructs the data, theory, and likelihood, evaluates physical parameters, runs inference, and reloads the saved result. For the component diagram and repeated evaluation loop, see How cup1d works.

1. Build the analysis#

from cup1d import Analysis, Args

config = "configs/cm2026/cm2026_base.yaml"
args = Args.from_yaml(config, verbose=False)
analysis = Analysis(args)

Args.from_yaml resolves data, emulator, parameters, priors, sampler settings, and output paths. Analysis constructs analysis.data, analysis.theory, analysis.like, and analysis.fitter.

2. Inspect data and parameters#

data_label = next(iter(analysis.data))
data = analysis.data[data_label]
print(data.z)
print(data.k_ikms[0].shape)
print(data.P1D_kms[0].shape)
print(data.cov_P1D_kms[0].shape)

for parameter in analysis.like.free_params.values():
    print(
        parameter["name"],
        parameter["value"],
        parameter["min_value"],
        parameter["max_value"],
    )

At each redshift, wavenumber and power have shape (Nk,), while the covariance has shape (Nk, Nk). See Scientific conventions and data contracts.

3. Evaluate the likelihood#

Only the fitter converts between numerical unit-cube coordinates and physical parameter dictionaries:

initial_cube = analysis.fitter.sampling_point_from_parameters()
parameters = analysis.fitter.parameters_from_sampling_point(initial_cube)
chi2 = analysis.like.get_chi2(parameters)
P1D_by_dataset, extra = analysis.like.get_P1D_kms(parameters)
print(chi2)

The theory predicts P1D_Mpc, converts it to P1D_kms, applies contaminants and systematics, and returns predictions on the data grid.

4. Minimize and save#

analysis.run_minimizer(
    initial_cube,
    estimate_errors=False,
    make_plots=False,
)
print(analysis.fitter.mle)
print(analysis.fitter.mle_chi2)

estimate_errors=False prevents curvature estimation inside the optimizer. analysis.run_minimizer then saves the result automatically; if cosmological errors are absent at that save boundary, save_minimizer_results estimates them with Gauss–Newton. minimizer_results.npy records the YAML path and fit state; YAML remains the authoritative configuration.

5. Sample and save#

analysis.run_sampler()

The sampler starts from the MLE unless pini is supplied. It writes chain.npy, blobs.npy, lnprob.npy, and sampler_results.npy. Sampler and standalone minimizer results remain distinct because the best sampled point is minimized again and may differ from the earlier fit.

6. Reload and post-process#

from pathlib import Path

minimizer_file = (
    Path(analysis.fitter.save_directory) / "minimizer_results.npy"
)
restored = Analysis.from_results(minimizer_file)

from cup1d.postprocessing import Plotter

plotter = Plotter(restored.fitter)
plotter.plot_mle_cosmo(
    plot_errors=True,
    error_method="gauss_newton",
)

Analysis.from_results reloads the referenced YAML, rebuilds the data/theory/likelihood graph, and restores fitter state. A sampler result also restores its chain, blobs, and log probabilities.

Blinded compressed cosmological values remain blinded in inference state. Unblind only for authorized presentation or comparison, as demonstrated in notebooks/tutorials/dr1.py.

Use dr1.py for observations, forecast.py for forecasts, mock.py for simulations, and cobaya_likelihood.py for the external likelihood. See Tutorials for the full directory map.