- The des_cluster project
- Running Cosmolike projects (Basic instructions)
- Running Hybrid Cosmolike-ML emulators
- Exploring notebooks
- The plotting functions
- The notebook wrappers
- Likelihood options and nuisance parameters
- Cluster options
- Nuisance parameters
- Synthetic data
- Files
- Regenerating the data
- Unit tests and validation tools
- Status and known limitations
- Computing covariances
- Appendix: Which accuracy settings are available?
This project runs the DES Y6-style joint analysis of galaxy clusters, galaxy clustering, and weak lensing of arXiv:2503.13631 in Cocoa. The cluster code is a port of the original CosmoLike cluster code (arXiv:2008.10757) into Cocoa's cosmolike_core, where it lives in the files ending in _cluster. The file PORT_PLAN.md records the model, the design decisions, the validation, and the status of the port.
The project provides two likelihoods:
| likelihood | name in the paper | blocks |
|---|---|---|
des_cluster.combo_4x2pt_N |
CL+GC = 4x2pt + N | cluster counts, cluster lensing, cluster clustering, cluster x galaxy clustering, galaxy clustering (MagLim lens bins 1-3) |
des_cluster.combo_6x2pt_N |
CL+3x2pt = 6x2pt + N | the blocks above plus cosmic shear, galaxy-galaxy lensing, and galaxy clustering of all six MagLim lens bins |
Both likelihoods read one joint data vector of 2812 entries and one covariance; they differ only in the scale-cut mask. The blocks are stored in the order ss, gs, gg, cg, N, cc, cs:
| block | content | layout | entries | kept by the 4x2pt + N mask | kept by the 6x2pt + N mask |
|---|---|---|---|---|---|
ss |
cosmic shear, |
[source pair][$\theta$] | 400 | 0 | 190 |
gs |
galaxy-galaxy lensing |
[(lens, source) pair][$\theta$] | 480 | 0 | 312 |
gg |
galaxy clustering |
[lens bin][$\theta$] | 120 | 31 | 69 |
cg |
cluster x galaxy clustering |
[(cluster z bin, lens bin) pair][richness bin][$\theta$] | 240 | 128 | 128 |
N |
cluster counts | [cluster z bin][richness bin] | 12 | 12 | 12 |
cc |
cluster clustering |
[cluster z bin][richness pair][$\theta$] | 600 | 230 | 230 |
cs |
cluster lensing, |
[(cluster z bin, source bin) pair][richness bin][$\theta$] | 960 | 488 | 488 |
| total | 2812 | 889 | 1429 |
The binning is the one of the paper: three cluster redshift bins with
Warning
All data in this project are synthetic. No public DES cluster data vectors or covariances exist (neither for Y1 nor for Y3), so the project ships a DES Y6-like stand-in: the data vector is the model itself, computed at the fiducial point of Table I of arXiv:2503.13631, and the covariance is an analytic Gaussian covariance. Nothing here is a DES measurement, and no chain run on these files is a DES result. The section Synthetic data describes the files and how to regenerate them.
Warning
The code and examples of this project are in alpha stage. Read Status and known limitations before using the results.
From Cocoa/Readme instructions:
Note
Cocoa provides several cosmolike projects that can be loaded and compiled using setup_cocoa.sh and compile_cocoa.sh scripts. Cocoa skips the project des_cluster by default. To activate it, comment the line export IGNORE_COSMOLIKE_DES_CLUSTER_CODE=1 on set_installation_options.sh
[Adapted from Cocoa/set_installation_options.sh shell script]
(...)
# ------------------------------------------------------------------------------
# The keys below control which cosmolike projects will be installed and compiled
# ------------------------------------------------------------------------------
#export IGNORE_COSMOLIKE_LSST_Y1_CODE=1
export IGNORE_COSMOLIKE_DES_Y3_CODE=1
(...)
export IGNORE_COSMOLIKE_DES_CLUSTER_CODE=1
(...)
# URL of Cosmolike projects below ----------------------------------------------
(...)
# WARNING: des_cluster is not production ready.
export DES_CLUSTER_URL="https://github.com/CosmoLike/cocoa_des_cluster.git"
export DES_CLUSTER_NAME="des_cluster"
export DES_CLUSTER_GIT_TAG="v5.06"
Note
The covariance data/des_cluster_y6_cov.npy (32 MB) is stored with Git LFS. A clone without git lfs pull holds a small pointer file in its place, and the likelihoods cannot load it.
Note
If users want to recompile cosmolike, there is no need to rerun the Cocoa general scripts. Instead, run the following three commands:
source start_cocoa.sh
and
source ./installation_scripts/setup_cosmolike_projects.sh
and
source ./installation_scripts/compile_all_projects.sh
or (in case users just want to compile des_cluster project)
source ./projects/des_cluster/scripts/compile_des_cluster.sh
Tip
Assuming Cocoa is installed on a local (not remote!) machine, type the command below after step 2 to run Jupyter Notebooks.
jupyter notebook --no-browser --port=8888
The terminal will then show a message similar to the following template:
(...)
[... NotebookApp] Jupyter Notebook 6.1.1 is running at:
[... NotebookApp] http://f0a13949f6b5:8888/?token=XXX
[... NotebookApp] or http://127.0.0.1:8888/?token=XXX
[... NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
Now go to the local internet browser and type http://127.0.0.1:8888/?token=XXX, where XXX is the previously saved token displayed on the line
[... NotebookApp] or http://127.0.0.1:8888/?token=XXX
The project des_cluster contains three jupyter notebook examples located at projects/des_cluster (see Exploring notebooks).
To run the example
Step 1️⃣: activate the cocoa Conda environment, and the private Python environment
conda activate cocoa
and
source start_cocoa.sh
Step 2️⃣: Select the number of OpenMP cores (the commands below set it to 8).
-
Linux
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=close; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1 -
macOS (arm)
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=disabled; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 3️⃣: The folder projects/des_cluster contains examples. So, run the cobaya-run on the first example following the commands below.
The examples numbered 1 run 4x2pt + N, and the examples numbered 2 run 6x2pt + N. The examples of this section compute the Boltzmann inputs with CAMB (Takahashi Halofit).
Warning
(Linux only) In some HPC nodes, numa can cause you problems. If that is the case,
replace numa with slot
-
One model evaluation:
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 1 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ cobaya-run ./projects/des_cluster/EXAMPLE_EVALUATE1.yaml -f -
macOS (arm)
mpirun -n 1 --oversubscribe \ cobaya-run ./projects/des_cluster/EXAMPLE_EVALUATE1.yaml -f
EXAMPLE_EVALUATE1.yamlandEXAMPLE_EVALUATE2.yamlevaluate the likelihood at the point of the synthetic data vector (Table I of arXiv:2503.13631), so they return$\chi^2 = 0$ : the data vector is the model at that point, and the frozen copies of these examples in the unit tests record exactly 0. -
-
MCMC (Metropolis-Hastings Algorithm):
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 4 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ cobaya-run ./projects/des_cluster/EXAMPLE_MCMC1.yaml -f -
macOS (arm)
mpirun -n 4 --oversubscribe \ cobaya-run ./projects/des_cluster/EXAMPLE_MCMC1.yaml -f
EXAMPLE_MCMC1.yamlandEXAMPLE_MCMC2.yamlsample $\Lambda$CDM, as in the paper, with the neutrino mass free (wandw0pwaare fixed at -1; to sample$w_0$ -$w_a$, give them a prior as in the evaluate examples). No proposal covariance is shipped for the cluster combinations, so the first run learns it. -
The outputs are written to projects/des_cluster/chains/.
Note
These hybrid examples remain experimental. The checks below verify the workflow; assess emulator accuracy and posterior convergence for your analysis.
The EXAMPLE_EMUL2 examples emulate the background expansion and matter
power spectra. CosmoLike still computes the survey projections, bias and
intrinsic-alignment contributions. Changing n(z) or nuisance parameters does
not require retraining a survey data-vector network.
The shared theory networks live in external_modules/data/emultrf. Install
them through the main Cocoa emulator recipe.
These networks assume mnu = 0.06 eV; do not sample neutrino mass. Their
cold-matter power approximation is not a calibrated massive-neutrino halo
model. Check their training range before widening cosmological priors.
Important
The supplied likelihood data are synthetic. Sampling examples demonstrate the workflow; they do not yield DES measurements.
Note
The emulators are fixed at a neutrino mass of 0.06 eV. The EMUL2 examples set mnu to 0.06 eV and do not sample it, while the synthetic data vector was generated with CAMB at mnu = 0.077 eV). The EXAMPLE_EMUL2_EVALUATE1.yaml and EXAMPLE_EMUL2_EVALUATE2.yaml at the fiducial point is therefore not zero. At equal neutrino mass, the emulated inputs differ from CAMB by
This project does not distribute a full data-vector emulator: cluster
likelihoods reject use_emulator: 1. These examples use use_emulator: 2.
These steps assume Cocoa and this project are installed, the Cocoa Conda environment
is active, the shell is Bash, and the current folder is cocoa/Cocoa/.
Step 1️⃣: activate Cocoa.
source start_cocoa.shStep 2️⃣: Select the number of OpenMP cores (below, we set it to 4).
-
Linux
export OMP_NUM_THREADS=4; export OMP_PROC_BIND=close; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1 -
macOS (arm)
export OMP_NUM_THREADS=4; export OMP_PROC_BIND=disabled; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 3️⃣: remove GPU access on Linux; these examples use the CPU.
export CUDA_VISIBLE_DEVICES=""Step 4️⃣: evaluate the first hybrid example.
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 1 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ cobaya-run ./projects/des_cluster/EXAMPLE_EMUL2_EVALUATE1.yaml --force -
macOS (arm)
mpirun -n 1 --oversubscribe \ cobaya-run ./projects/des_cluster/EXAMPLE_EMUL2_EVALUATE1.yaml --force
The YAML selects the CPU for the distance emulator. Keep BLAS at one thread
per MPI rank (OPENBLAS_NUM_THREADS=1, MKL_NUM_THREADS=1); on macOS also
use VECLIB_MAXIMUM_THREADS=1. The Python sampler entry points set these
BLAS limits before importing numerical libraries.
| Example | Configuration 1 | Configuration 2 |
|---|---|---|
| Fixed evaluation | EXAMPLE_EMUL2_EVALUATE1.yaml | EXAMPLE_EMUL2_EVALUATE2.yaml |
| Cobaya MCMC | EXAMPLE_EMUL2_MCMC1.yaml | EXAMPLE_EMUL2_MCMC2.yaml |
| Annealed minimization | EXAMPLE_EMUL2_MINIMIZE1.py | EXAMPLE_EMUL2_MINIMIZE2.py |
| Parameter profile | EXAMPLE_EMUL2_PROFILE1.py | EXAMPLE_EMUL2_PROFILE2.py |
| Nautilus sampling | EXAMPLE_EMUL2_NAUTILUS1.py | EXAMPLE_EMUL2_NAUTILUS2.py |
| Repeated evaluations | EXAMPLE_EMUL2_BENCHMARK1.yaml | EXAMPLE_EMUL2_BENCHMARK2.yaml |
| PolyChord | EXAMPLE_EMUL2_POLY1.yaml | EXAMPLE_EMUL2_POLY2.yaml |
Configuration 1 uses des_cluster.combo_4x2pt_N, NLA, and des_cluster_y6_4x2ptN.dataset.
Configuration 2 uses des_cluster.combo_6x2pt_N, NLA, and des_cluster_y6_6x2ptN.dataset.
The minimization, profile and Nautilus scripts read the corresponding
EXAMPLE_EMUL2_EVALUATE1.yaml or 2.yaml; --input selects another evaluate
YAML. They require cocoa_hybrid_sampling.py from the matching shared core
revision. They do not maintain separate embedded cosmologies. --check evaluates
the specified fiducial and prints the sampled parameter order without sampling.
Use a new --outroot for each run; these scripts refuse to overwrite results.
With Cocoa activated in Bash from cocoa/Cocoa/, run the first MCMC
example. Use configuration
2 for the second likelihood listed above. Check chain convergence before
interpreting posterior constraints.
Step 1️⃣: Select the number of OpenMP cores (below, we set it to 8).
-
Linux
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=close; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1 -
macOS (arm)
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=disabled; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 2️⃣: remove GPU access on Linux; these examples use the CPU.
export CUDA_VISIBLE_DEVICES=""Step 3️⃣: start Cobaya's hybrid MCMC.
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 4 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ cobaya-run ./projects/des_cluster/EXAMPLE_EMUL2_MCMC1.yaml -
macOS (arm)
mpirun -n 4 --oversubscribe \ cobaya-run ./projects/des_cluster/EXAMPLE_EMUL2_MCMC1.yaml
Additional YAML workflows above retain their own parameter choices; inspect which parameters are fixed or sampled rather than assuming the evaluate and MCMC configurations have identical priors. PolyChord requires its optional Cocoa installation component.
The benchmark YAML repeats model evaluations for profiling.
Step 1️⃣: Select the number of OpenMP cores (below, we set it to 8).
-
Linux
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=close; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1 -
macOS (arm)
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=disabled; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 2️⃣: remove GPU access on Linux; these examples use the CPU.
export CUDA_VISIBLE_DEVICES=""Step 3️⃣: run the first benchmark configuration.
cobaya-run ./projects/des_cluster/EXAMPLE_EMUL2_BENCHMARK1.yaml --forceFor the separate PolyChord example:
Step 1️⃣: Select the number of OpenMP cores (below, we set it to 8).
-
Linux
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=close; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1 -
macOS (arm)
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=disabled; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 2️⃣: remove GPU access on Linux; these examples use the CPU.
export CUDA_VISIBLE_DEVICES=""Step 3️⃣: start the first PolyChord configuration.
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 90 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ -x PATH -x LD_LIBRARY_PATH -x PYTHONPATH -x CONDA_PREFIX -x ROOTDIR \ -x OMP_NUM_THREADS -x OMP_PROC_BIND -x OMP_PLACES -x OMP_DYNAMIC \ -x OPENBLAS_NUM_THREADS -x MKL_NUM_THREADS -x CLIK_PATH -x CLIK_DATA \ -x CLIK_PLUGIN -x CUDA_VISIBLE_DEVICES --mca mpi_yield_when_idle 1 \ --mca btl_tcp_if_exclude lo,docker0,virbr0,ib0 \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ cobaya-run ./projects/des_cluster/EXAMPLE_EMUL2_POLY1.yaml -
macOS (arm)
mpirun -n 12 --oversubscribe \ cobaya-run ./projects/des_cluster/EXAMPLE_EMUL2_POLY1.yaml
These steps assume Cocoa and this project are installed, the Cocoa Conda environment
is active, the shell is Bash, and the current folder is cocoa/Cocoa/.
Step 1️⃣: Select the number of OpenMP cores (below, we set it to 8).
-
Linux
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=close; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1 -
macOS (arm)
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=disabled; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 2️⃣: remove GPU access on Linux; these examples use the CPU.
export CUDA_VISIBLE_DEVICES=""Step 3️⃣: check the hybrid setup before a long run.
python ./projects/des_cluster/EXAMPLE_EMUL2_MINIMIZE1.py --checkStep 4️⃣: search for a minimum.
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 21 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ -x PATH -x LD_LIBRARY_PATH -x PYTHONPATH -x CONDA_PREFIX -x ROOTDIR \ -x OMP_NUM_THREADS -x OMP_PROC_BIND -x OMP_PLACES -x OMP_DYNAMIC \ -x OPENBLAS_NUM_THREADS -x MKL_NUM_THREADS -x CLIK_PATH -x CLIK_DATA \ -x CLIK_PLUGIN -x CUDA_VISIBLE_DEVICES --mca mpi_yield_when_idle 1 \ --mca btl_tcp_if_exclude lo,docker0,virbr0,ib0 \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ python ./projects/des_cluster/EXAMPLE_EMUL2_MINIMIZE1.py --nstw 200 --outroot hybrid_min1 -
macOS (arm)
mpirun -n 12 --oversubscribe \ python ./projects/des_cluster/EXAMPLE_EMUL2_MINIMIZE1.py --nstw 200 --outroot hybrid_min1
Step 5️⃣: profile the first sampled parameter using that saved minimum.
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 21 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ -x PATH -x LD_LIBRARY_PATH -x PYTHONPATH -x CONDA_PREFIX -x ROOTDIR \ -x OMP_NUM_THREADS -x OMP_PROC_BIND -x OMP_PLACES -x OMP_DYNAMIC \ -x OPENBLAS_NUM_THREADS -x MKL_NUM_THREADS -x CLIK_PATH -x CLIK_DATA \ -x CLIK_PLUGIN -x CUDA_VISIBLE_DEVICES --mca mpi_yield_when_idle 1 \ --mca btl_tcp_if_exclude lo,docker0,virbr0,ib0 \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ python ./projects/des_cluster/EXAMPLE_EMUL2_PROFILE1.py --profile 0 --nstw 200 --numpts 11 --factor 1 --minfile ./projects/des_cluster/chains/hybrid_min1.json --outroot hybrid_profile1 -
macOS (arm)
mpirun -n 12 --oversubscribe \ python ./projects/des_cluster/EXAMPLE_EMUL2_PROFILE1.py --profile 0 --nstw 200 --numpts 11 --factor 1 --minfile ./projects/des_cluster/chains/hybrid_min1.json --outroot hybrid_profile1
Step 6️⃣: run Nautilus as an independent sampling example.
-
Linux
"${CONDA_PREFIX}"/bin/mpirun -n 90 --oversubscribe \ --mca pml ob1 --mca btl vader,tcp,self \ -x PATH -x LD_LIBRARY_PATH -x PYTHONPATH -x CONDA_PREFIX -x ROOTDIR \ -x OMP_NUM_THREADS -x OMP_PROC_BIND -x OMP_PLACES -x OMP_DYNAMIC \ -x OPENBLAS_NUM_THREADS -x MKL_NUM_THREADS -x CLIK_PATH -x CLIK_DATA \ -x CLIK_PLUGIN -x CUDA_VISIBLE_DEVICES --mca mpi_yield_when_idle 1 \ --mca btl_tcp_if_exclude lo,docker0,virbr0,ib0 \ --bind-to core:overload-allowed --report-bindings \ --rank-by slot --map-by numa:pe=${OMP_NUM_THREADS} \ python ./projects/des_cluster/EXAMPLE_EMUL2_NAUTILUS1.py --nlive 1000 --neff 10000 --maxfeval 100000 --outroot hybrid_nautilus1 -
macOS (arm)
mpirun -n 12 --oversubscribe \ python ./projects/des_cluster/EXAMPLE_EMUL2_NAUTILUS1.py --nlive 1000 --neff 10000 --maxfeval 100000 --outroot hybrid_nautilus1
The annealed Emcee search follows the DES × Planck template. Its objective
is −2 log posterior, including nuisance and cosmological priors; the
profile is therefore a penalized profile, not a pure likelihood profile.
--nstw sets steps per walker per temperature. More steps and independent
starts are needed to assess whether a minimum is reliable.
--profile accepts a sampled-parameter name or its printed zero-based index.
--factor gives the half-width in proposal standard deviations, clipped to
the prior bounds. --cov accepts a covariance whose header lists the sampled
parameters in order; without it, the prior covariance sets the proposal.
The minimum JSON must come from the same evaluate YAML and parameter order.
Older plain-text minimum files are not accepted. Set any additional priors
in the input YAML; these scripts do not insert hidden cosmological priors.
Nautilus writes weighted GetDist-compatible rows and a JSON convergence
record. Reaching --maxfeval is not convergence. If the budget ends before
any posterior samples are retained, only the checkpoint and a JSON record
with converged: false are saved. Its prior transform uses
Cobaya's one-dimensional prior distributions; external prior factors enter
once as additional log weight. Evidence with unnormalized external priors
has that normalization limitation. These examples do not certify emulator
accuracy or posterior convergence.
Details on the matter power spectrum emulator designs will be presented in the emulator_code repository.
The emulators apply standard neural network techniques to generalize
the syren-new Eq. 6 of arXiv:2410.14623
formula for the linear power spectrum (w0waCDM with a fixed neutrino mass of
Note
Running on more than one node.
- Network interface. TCP must use an interface routable between compute
nodes. A common exclusion list is
--mca btl_tcp_if_exclude lo,docker0,virbr0,ib0; adapt it to the cluster. Keepib0if routable IP-over-InfiniBand is the intended network. These examples exchange parameter vectors and scalar scores, so communication volume is small; actual scaling still depends on the machine. - Environment. Remote ranks need the same Cocoa paths and libraries:
ROOTDIR,PATH,LD_LIBRARY_PATH,PYTHONPATH,CONDA_PREFIX, OpenMP and BLAS settings, andCLIK_PATH/CLIK_DATA/CLIK_PLUGINwhen used. Slurm normally exports the submitting environment (--export=ALL). Explicit-xoptions also forward these variables with SSH launchers. Activate Cocoa before launching; build/download flags do not replace runtime paths. All nodes must see the same files at the same paths. - Slurm geometry. Keep
ntasks-per-node × cpus-per-taskwithin the allocated physical cores per node. SetOMP_NUM_THREADStoSLURM_CPUS_PER_TASKand use--map-by numa:pe=${OMP_NUM_THREADS}. The minimization, profile and Nautilus pool reserves one MPI rank as coordinator; the remaining ranks evaluate the model.
Within a Slurm allocation, first activate Cocoa in Bash on the launch node. The following steps assume Open MPI 4 and shared installation/data paths. Omit optional CLIK exports if those variables are not set.
Step 1️⃣: match OpenMP threads to the scheduler allocation.
export OMP_NUM_THREADS="${SLURM_CPUS_PER_TASK}"; export OMP_PROC_BIND=close; \
export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \
export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 2️⃣: launch the hybrid minimizer across the allocated ranks.
"${CONDA_PREFIX}"/bin/mpirun -n "${SLURM_NTASKS}" \
--mca pml ob1 --mca btl vader,tcp,self \
--mca btl_tcp_if_exclude lo,docker0,virbr0 \
--map-by numa:pe=${OMP_NUM_THREADS} --bind-to core --report-bindings \
-x ROOTDIR -x PATH -x LD_LIBRARY_PATH -x PYTHONPATH -x CONDA_PREFIX \
-x OMP_NUM_THREADS -x OMP_PROC_BIND -x OMP_PLACES -x OMP_DYNAMIC \
-x OPENBLAS_NUM_THREADS -x MKL_NUM_THREADS -x CUDA_VISIBLE_DEVICES \
python ./projects/des_cluster/EXAMPLE_EMUL2_MINIMIZE1.py --nstw 200 --outroot hybrid_multinodeFor a Planck likelihood add -x CLIK_PATH -x CLIK_DATA -x CLIK_PLUGIN when
those variables are defined. Follow the cluster's MPI module and Slurm
launch policy; do not oversubscribe a production allocation. Outside Slurm,
supply the hosts and slots with the cluster's --hostfile or --host recipe.
Armadillo was chosen to make a convenient Python API for notebook exploration. This C++ library provides vectors, matrices and three-dimensional arrays called cubes. A small interface layer connects them to NumPy through pybind11, with CARMA handling array conversion. The notebooks expose intermediate quantities; production calculations use the CLI interfaces.
These steps assume Cocoa and this project are installed, the Cocoa Conda environment
is active, the shell is Bash, and the current folder is cocoa/Cocoa/.
Compile the project first; the covariance notebook also needs the optional covariance build described below.
Step 1️⃣: activate Cocoa.
source start_cocoa.shStep 2️⃣: Select the number of OpenMP cores (below, we set it to 8).
-
Linux
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=close; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1 -
macOS (arm)
export OMP_NUM_THREADS=8; export OMP_PROC_BIND=disabled; \ export OMP_PLACES=cores; export OMP_DYNAMIC=FALSE; \ export OPENBLAS_NUM_THREADS=1; export MKL_NUM_THREADS=1
Step 3️⃣: start Jupyter.
jupyter notebook --no-browser --port=8888Step 4️⃣: open the printed URL and choose a notebook below.
Step 5️⃣: select Kernel → Restart Kernel and Run All Cells.
| Notebook | Contents |
|---|---|
| EXAMPLE_EVALUATE1.ipynb | The 4x2pt + N cluster observables at the fiducial point, their halo-model ingredients, and their response to the mass-observable relation, through the project wrappers; inspect the setup cells before running. |
| EXAMPLE_EVALUATE2.ipynb | 6x2pt + N parameter sweeps, the baryonic-feedback study with the bfmt theory block (six methods, a |
| EXAMPLE_EVALUATE_COVARIANCE.ipynb | G, SSC, cNG, total, separate 1h–4h matter trispectra and matrix diagnostics. |
flowchart TD
A["Compile the project, start Jupyter"] --> B["EXAMPLE_EVALUATE1.ipynb: 4x2pt + N observables"]
B --> C["EXAMPLE_EVALUATE2.ipynb: 6x2pt + N sweeps and bfmt feedback"]
A --> D["Covariance build"]
D --> E["EXAMPLE_EVALUATE_COVARIANCE.ipynb: joint forecast"]
W["Notebook wrappers: interface/"] --> B
W --> C
P["Plotting functions: plot_datavectors_cluster and cnu"] --> B
P --> C
F["bfmt block and its emulators"] --> C
E --> G["Covariance guide: covariance/README.md"]
Read EXAMPLE_EVALUATE1.ipynb first: it introduces each cluster observable
that EXAMPLE_EVALUATE2.ipynb then varies. The covariance notebook needs
the optional covariance build and continues in the covariance guide.
Choose the Python kernel from the activated Cocoa environment and restart it after recompiling. The covariance guide explains the forecast files, figures and refinement workflow.
The notebook EXAMPLE_EVALUATE1.ipynb computes the cluster observables at the fiducial point with the options of EXAMPLE_EVALUATE1.yaml (4x2pt + N) and compares them with the synthetic data where the scale cuts keep them. It covers, in this order: the cluster counts per richness and redshift bin; the halo-model ingredients (the probability of a richness bin given the halo mass, the number density and the bias of each richness bin, the redshift selection kernels, the one-halo cluster-matter power spectrum); cluster lensing, both as
The notebook EXAMPLE_EVALUATE2.ipynb runs 6x2pt + N with the options of EXAMPLE_EVALUATE2.yaml, in the form of parameter sweeps. It computes a reference model at the fiducial point, then varies one parameter at a time (five values each) and shows every block as a ratio to the reference, with the curves colored by the parameter value. The sweeps cover
The section Baryonic feedback from the bfmt theory block follows. For six methods (the three SP(k) relations, BCEmu, Flamingo and BCemu2025) it computes the suppression get_baryon_suppression and the joint data vector with compute_probes, and prints two tables over the 1,429 entries the 6x2pt + N mask keeps. The first gives each method's bfmt block and the SP(k), BCEmu and FLAMINGO emulators, which Cocoa's setup installs unless IGNORE_BFMT_CODE, IGNORE_PYSPK_CODE, IGNORE_BCEMU_CODE or IGNORE_FBRE_CODE is set in set_installation_options.sh.
The notebook then changes the number of angular bins and the accuracy setting of cosmolike, and ends with the
Note
The notebooks load their support functions from two places. The functions shared by
all projects (the CAMB run packaged for cosmolike, the plotting functions) come from
Cocoa/external_modules/code/cosmolike_core/cosmolike_notebook_utils/. The
functions specific to this project (fiducial values, the compiled-interface calls,
the cluster observables) come from
interface/cosmolike_des_cluster_notebook_wrappers.py.
Every data-vector figure of the two notebooks comes from a plotting function. The cluster blocks use plot_datavectors_cluster.py of cosmolike_notebook_utils, the cluster version of the functions the other projects use for the galaxy blocks. The module is imported on its own:
from cosmolike_notebook_utils import plot_datavectors_cluster as pdc
| function | panels | curves inside a panel |
|---|---|---|
plot_N_cluster |
one per cluster z bin; the x axis is the richness | one staircase per model |
plot_gammat_cluster_tomo, plot_sigma_cluster_tomo, plot_C_cs_tomo_limber |
one per (cluster z bin, source bin) pair: columns are cluster z bins, rows are source bins | the richness bins |
plot_wcc_tomo, plot_C_cc_tomo_limber |
one per cluster z bin | the richness pairs (by default the auto pairs) |
plot_wcg_tomo, plot_C_cg_tomo_limber |
one per (cluster z bin, lens bin) pair of the dataset | the richness bins |
The functions follow the conventions of the galaxy functions. They take a list of models; param and colorbarlabel color the list by a parameter value; a reference (the *_ref argument) turns every panel into the fractional difference to it; rescale = 1 joins the panels on one y axis, with one power of ten per panel; and show = None returns the figure. The cluster blocks have one more index than the galaxy blocks, the richness bin. The richness bins are curves inside each panel: the color follows the model and the line style follows the richness bin. The argument richness (pairs for data overlays the data vector with its errors and leaves out the points the scale cuts remove. The 3x2pt blocks use the galaxy functions cnu.plot_xi, cnu.plot_gammat_tomo_limber, and cnu.plot_wtheta_tomo. The docstrings of the module document every argument.
The wrappers module drives the compiled interface through the same steps as the likelihoods: it runs CAMB once, pushes the power spectra, growth, and distances into the interface, sets the nuisance parameters, and reads off an observable. Its usage is
import cosmolike_des_cluster_notebook_wrappers as nw
nw.configure(cluster_ytransform=1) # optional: the yaml options, before init_cosmolike
nw.init_cosmolike(CLprobe="6x2pt_N", with_data=True)
N = nw.N_cluster() # (richness bin, z bin)
theta, gammat = nw.gamma_t_cluster() # (theta, richness, z, source)
nw.get_chi2(omegam=0.31)
| function | returns |
|---|---|
configure(**overrides) |
nothing; sets the values that mirror the likelihood yaml (lmax, integration_accuracy, the cluster_* switches, the data path). Call it before init_cosmolike
|
init_cosmolike(CLprobe, with_data, lmax) |
the parsed dataset file; runs the init sequence of the likelihood. with_data=True also loads the mask, the data vector, and the covariance, which get_datavector and get_chi2 need |
dataset_info() |
the binning and the bin edges of the loaded dataset |
N_cluster() |
cluster counts, array (richness bin, cluster z bin) |
gamma_t_cluster() |
(theta, gammat): cluster tangential shear before the Y transform, the selection bias, and the shear calibration; array ( |
sigma_cluster() |
(theta, sigma): cluster lensing as the data vector holds it, without the mask; same array layout |
w_cc(selection_bias) |
(theta, wcc): array ( |
w_cg(selection_bias) |
(theta, wcg): array ( |
C_cs_tomo_limber(ell), C_cc_tomo_limber(ell), C_cg_tomo_limber(ell)
|
the Limber spectra at the multipoles ell, with the layouts above and |
xi(), gamma_t(), w_theta()
|
the 3x2pt blocks in real space: (theta, xi_plus, xi_minus), (theta, gammat), and (theta, wtheta), in the array layouts of the galaxy plotting functions |
prob_richness_bin_given_m(M, z) |
probability of each richness bin given the halo mass (M200m, in |
ncl_richness(z), bcl_richness(z)
|
comoving number density, in |
pcm_1h_richness(k, z) |
one-halo cluster-matter power spectrum of each richness bin, in k in |
phi_cluster(z) |
the selection kernels |
nz_cluster(z), W_cluster(z)
|
the normalized true-redshift distribution and the radial kernels of the cluster bins |
get_datavector(), get_chi2()
|
the masked joint theory vector and its |
cluster_blocks(vector), data_cluster_blocks()
|
the cluster blocks (counts, cluster lensing, |
get_baryon_suppression(theory_options, point, z_grid, log10k_grid) |
the suppression bfmt theory block as {z: S}, one array over bfmt, and the one likelihood) at the fiducial cosmology |
compute_probes(sup=None) |
every block at the fiducial point in the layouts above (N, sigma, gammat_cluster, wcc and wcg with the selection bias, xi, gammat, wtheta), the masked joint vector dv, its chi2, and the grids z_grid and log10k_grid (sup, init_cosmolike(with_data=True)
|
get_baryon_suppression and compute_probes run at the fiducial point only. Every other wrapper that computes a model takes the cosmology (omegam, omegab, H0, ns, As_1e9, w, w0pwa, mnu), the accuracy settings, and the nuisance vectors (M, A1, B1, MOR, SEL, ...) as keyword arguments, and falls back to the project fiducial point, which the module holds as plain constants. For example, nw.N_cluster(MOR=[4.3, 0.943, 0.15, 0.207]) changes the mass-observable relation for one call. Each wrapper sets the complete state of the interface on every call, so no call depends on which wrapper ran before it; the module keeps the last CAMB run, so repeated calls at one cosmology cost one CAMB run. The docstrings of the module document every argument and array layout.
The defaults of the two likelihoods are in likelihood/combo_4x2pt_N.yaml and likelihood/combo_6x2pt_N.yaml; the examples repeat the keys discussed below. The model follows arXiv:2503.13631 (the equation numbers below are those of that paper):
- The counts (eq. 16) use the Tinker mass function and halo bias (M200m) and a lognormal mass-observable relation (eqs. 18-19, pivot mass
$5\times10^{14},M_\odot/h$ ). - The cluster-lensing spectrum is the sum of a two-halo term (richness-weighted cluster bias times the nonlinear matter power spectrum) and a one-halo NFW term (eq. 22). The data vector holds
$\Sigma = Y\gamma_t$ , the Y transform of eq. 15, which involves no critical surface density. The last angular bin of every cluster-lensing row vanishes by construction and is always masked. -
$w_{cc}$ and$w_{cg}$ use a linear cluster bias times the nonlinear matter power spectrum. Below$\ell = 150$ they are computed without the Limber approximation and with redshift-space distortions, as the original CosmoLike code (lighthouse) and the DES analyses compute them (cluster_adopt_limber_cc: 0,cluster_adopt_limber_cg: 0). - The selection bias (eq. 23) multiplies the data vector:
$\Sigma$ and$w_{cg}$ by$b_{s1} + b_{s2}\exp(-\theta\chi(\bar z)/r_0)$ , and$w_{cc}$ by its square. - The real-space statistics are full-sky, bin-averaged Legendre projections.
| key | default | meaning |
|---|---|---|
cluster_kernel_mode |
0 | radial kernel of the clusters in the two-point functions: 0 = volume only, |
cluster_selection_model |
2 | selection bias: 0 = none; 1 = Y1, mass dependent, inside the bias mass integral; 2 = Y6, scale dependent, on the data vector (eq. 23) |
cluster_ytransform |
1 | cluster lensing: 1 = |
cluster_include_ia |
1 | 1 = intrinsic alignment of the sources in the two-halo cluster-lensing term |
cluster_magnification |
-2.0 | cluster magnification coefficient |
cluster_hmf_alpha_mode |
0 | amplitude of the Tinker 2010 mass function: 0 = 0.368 at every redshift (what DES ran); 1 = the redshift-dependent amplitude of halo.c (3-9% fewer clusters at z = 0.2-0.6) |
cluster_adopt_limber_cc, cluster_adopt_limber_cg
|
0 |
|
All halo statistics use cold dark matter plus baryons (cb). Massive neutrinos free-stream out of halos, so the variance integrates CAMB's delta_nonu spectrum at the requested redshift, and the Lagrangian smoothing radius and mass-function density use
The NFW truncation radius still defines an M200m halo relative to the total mean density. The lensing mass weight
The shipped synthetic data and covariance were computed with this cb-variance calculation (regenerated on 2026-11-04), so the model reproduces the data vector at the fiducial point.
The EMUL2 path has no separate cb spectrum and retains the approximation
Three more keys matter for the cluster combinations:
-
integration_accuracy: 1. The cluster combinations run with 1, while the value 0 is not accurate enough for the Y6-like inputs: the tails of the MagLim lens redshift distributions reach z = 2.99. The accuracy sweeptests/validation/knob_sweep.pymeasured$\Delta\chi^2 = 1.65$ against high-accuracy settings at 0 (galaxy-galaxy lensing 0.92, galaxy clustering 0.47) and$\Delta\chi^2 = 0.048$ at 1, for about 30% more cosmolike time. The cluster blocks contribute$\Delta\chi^2 = 6\times10^{-3}$ either way. -
accuracyboost. Keep it at 3 or below, as the warning in the likelihood files says: the accuracy sweep reaches boost 2, and larger values have not been measured on the cluster combinations. -
IA_model: 0. The intrinsic-alignment model is NLA: the cluster lensing code has no TATT.
Galaxy clustering is non-Limber below adopt_limber_gg: 0), and galaxy-galaxy lensing is Limber (adopt_limber_gs: 1). The likelihoods refuse baryon PCAs with clusters.
The nuisance parameters and their priors come from the likelihood defaults likelihood/params_cluster.yaml, likelihood/params_lens_maglim.yaml, and likelihood/params_source_y6.yaml, so the examples do not list them in their params block. The fiducial values are those of Table I of arXiv:2503.13631, the point of the synthetic data vector.
Clusters (params_cluster.yaml):
| name | meaning | fiducial | prior |
|---|---|---|---|
DES_CL_LNLAMBDA0 |
|
4.26 | flat [2, 5] |
DES_CL_A_LAMBDA |
|
0.943 | flat [0.1, 1.5] |
DES_CL_B_LAMBDA |
|
0.207 | flat [-5, 5] |
DES_CL_SIGMA_INT |
|
0.15 | flat [0.1, 1] |
DES_CL_BS1 |
|
1.1 | flat [1, 2] |
DES_CL_BS2 |
|
0.2 | flat [-1, 1] |
DES_CL_R0 |
|
30 | flat [10, 60] |
DES_CL_BSZ |
power of |
0 | fixed |
Sources (params_source_y6.yaml):
| name | meaning | fiducial | prior |
|---|---|---|---|
DES_DZ_S1 ... DES_DZ_S4
|
photo-z shift of each source bin | 0.034, 0.028, 0.011, -0.010 | Gaussian, width 0.018, 0.013, 0.006, 0.013 |
DES_M1 ... DES_M4
|
shear calibration of each source bin | 0 | Gaussian, width 0.008, 0.013, 0.009, 0.012 |
DES_A1_1 |
NLA amplitude |
0 | flat [-5, 5] |
DES_A1_2 |
NLA redshift power |
0 | Gaussian, width 3 |
DES_A2_1, DES_A2_2, DES_BTA_1
|
TATT terms, unused under NLA | 0, 0, 1 | fixed |
MagLim lenses (params_lens_maglim.yaml):
| name | meaning | fiducial | prior |
|---|---|---|---|
DES_DZ_L1 ... DES_DZ_L6
|
photo-z shift of each lens bin | 0.005, 0.003, 0.001, -0.002, 0.001, 0.008 | Gaussian, width 0.007, 0.011, 0.006, 0.006, 0.01, 0.01 |
DES_B1_1 ... DES_B1_6
|
linear galaxy bias of each lens bin | 1.42, 1.66, 1.70, 1.62, 1.78, 1.75 | flat [0.8, 3] |
DES_PM1 ... DES_PM6
|
point mass of galaxy-galaxy lensing, in units of |
0 | flat [-100, 100] |
DES_BMAG_1 ... DES_BMAG_6
|
magnification coefficient of each lens bin | -1.57, -1.70, -0.25, 1.50, 2.22, 2.80 | fixed |
DES_DZ2_L1 ... DES_DZ2_L6
|
photo-z stretch of each lens bin | 1 | fixed |
DES_B2_1 ... DES_B2_6
|
nonlinear galaxy bias (the model is linear bias) | 0 | fixed |
4x2pt + N uses lens bins 1-3 only and has no galaxy-galaxy lensing block, so combo_4x2pt_N.yaml fixes the bias and the photo-z shift of lens bins 4-6 at their fiducial values and the six point masses at zero (its fixed_params block): these parameters enter only blocks that the 4x2pt + N mask removes. 6x2pt + N samples the bias and the photo-z shift of all six bins and the six point masses. The clusters have no photo-z nuisance parameter: their redshift selection enters through the fixed kernels data/des_y6_cluster.nz.
likelihood/README.md lists, for every likelihood of this project, what its fixed_params block fixes and which parameters it must not vary, with the reason for each.
The fiducial cosmology of the synthetic data is As_1e9 = 2.19, ns = 0.96859, H0 = 69, omegab = 0.048, omegam = 0.3, mnu = 0.077 eV), and
The synthetic data set is Y6-like in the following sense: the lens and source redshift distributions are the n(z) files of the DES Y6 code comparison kept in the repository of the original CosmoLike cluster code (lighthouse), the binning and the scale cuts are those of arXiv:2503.13631, the parameters are those of its Table I, and the survey area is 4143 deg$^2$ (the DES Y3 cluster footprint of arXiv:2503.13632). The data vector is the model of this code at that point, without noise. The covariance is Gaussian: for the two-point blocks, the full-sky, bin-averaged Gaussian term with shape and shot noise (with the Y transform applied to the cluster-lensing rows); for the counts, Poisson plus sample variance. Its spectra are those of the likelihood: below
The files of data/ that the cluster likelihoods read:
| file | content |
|---|---|
des_cluster_y6.dataset |
the base dataset descriptor: file names, binning, cluster redshift and richness edges, survey area, and the lens bin paired with each cluster redshift bin in |
des_cluster_y6_4x2ptN.dataset, des_cluster_y6_6x2ptN.dataset
|
the descriptors the likelihoods load: the base descriptor with the mask of each combination |
des_cluster_y6.datavector |
the joint synthetic data vector (2812 entries; columns: index, value) |
des_cluster_y6_cov.npy |
the joint covariance: the upper triangle with the diagonal, row by row, as a binary float64 NumPy array (32 MB; cosmolike reads it directly, and numpy.load returns the packed triangle). Stored with Git LFS |
des_cluster_y6_4x2ptN.mask, des_cluster_y6_6x2ptN.mask
|
the scale-cut masks of the two combinations |
des_y6_maglim.nz, des_y6_source.nz
|
redshift distributions of the six MagLim lens bins and of the four source bins. The z column holds left bin edges (photoz_zmid_convention: 0) |
des_y6_cluster.nz |
the selection kernels cluster_zmid_convention = 1. A table that lists left cell edges instead, as the DES and lighthouse tables do, needs cluster_zmid_convention = 0, and each value then belongs half a cell higher |
y3_redmapper_counts.txt |
the DES Y3 redMaPPer counts per redshift and richness bin, from the public Y3 catalog. The model does not read it: make_synthetic_data.py compares the model counts with it, and make_cluster_mask.py reads it for an optional cut on |
Two dataset keys are optional:
-
cluster_area_file: a table of the survey area of the cluster sample (columns z and deg$^2$). A volume-limited cluster sample loses the parts of the footprint that are too shallow to detect clusters at redshift z, so its area falls at high z; with the key, the counts integrate that area. Without it, the counts usesurvey_area_deg2at every redshift, the setting of the synthetic data and of forecasts. In the Cardinal simulation of the DES Y6 analysis the area falls to 69% at z = 0.65 and 8% at z = 0.75, and the constant area overestimates the counts of the 0.55-0.65 bin by 15%. -
cluster_zmid_convention: what the z column ofnz_cluster_filemeans (default 1, sample points; 0, left cell edges), with the encoding of the galaxyphotoz_zmid_convention.
The remaining files (des_y3_real.dataset, des_y3_unblinded_final.txt, des_y3_cov_unblinded_final.txt, des_y3_lens.nz, des_y3_source.nz, 3x2pt_baseline.mask, ones.mask, pca.txt, baryons_logPkR.h5) are a copy of the DES Y3 3x2pt data set of the project des_y3. The galaxy-only likelihoods of this project (cosmic_shear, combo_3x2pt, combo_2x2pt) point at it, as do their examples EXAMPLE_EVALUATE3.yaml (cosmic shear) and EXAMPLE_EVALUATE4.yaml (3x2pt) and their unit tests; the cluster likelihoods do not use it.
The scale cuts are defined at the mean redshift of each bin, at the fiducial cosmology: a point survives when its angle exceeds
The scripts are in scripts/. The commands below assume the Conda cocoa environment is active, start_cocoa.sh was sourced, and the current folder is the cocoa main folder cocoa/Cocoa. Each script documents its options in its header.
| step | script | writes | notes |
|---|---|---|---|
| 1 | make_des_y6_nz.py |
des_y6_maglim.nz, des_y6_source.nz
|
converts the lens and source n(z) of the DES Y6 code comparison of the lighthouse repository to the cosmolike n(z) format. The default input path is a local checkout of that repository: pass --lens-in and --source-in
|
| 2 | make_cluster_zdist.py |
des_y6_cluster.nz |
tabulates the selection kernels for a Gaussian cluster photo-z of width --edges, --sigma0, --sigma-per-bin, --tophat) |
| 3 | make_y3_redmapper_counts.py |
y3_redmapper_counts.txt |
tabulates the counts of the public DES Y3 redMaPPer catalog (--h5 or --npz) |
| 4 | make_cluster_mask.py |
the two masks | applies the scale cuts above; the radii, the rule for the bin angle, and the choice of |
| 5 | make_synthetic_data.py |
des_cluster_y6.datavector, des_cluster_y6_cov.npy
|
computes the data vector with the compiled code and the covariance with the Python reference (tests/reference/ref_covariance_full.py), checks the layout, the positive definiteness of the covariance under each mask, and the signal-to-noise per block, and asserts |
| 6 | make_example_files.py |
the MCMC and EXAMPLE_EMUL2 YAML examples |
see below |
For example, steps 4 and 5 are
python ./projects/des_cluster/scripts/make_cluster_mask.py
and
python ./projects/des_cluster/scripts/make_synthetic_data.py --threads 3
The two evaluate examples EXAMPLE_EVALUATE1.yaml and EXAMPLE_EVALUATE2.yaml are written by hand and are the source of the cluster examples. The script make_example_files.py derives the YAML examples from them (EXAMPLE_MCMC1.yaml, EXAMPLE_MCMC2.yaml, and the EXAMPLE_EMUL2 evaluate, MCMC, PolyChord and benchmark files), so these files cannot drift apart. Run its steps one at a time:
python ./projects/des_cluster/scripts/make_example_files.py evaluate
python ./projects/des_cluster/scripts/make_example_files.py samplers
python ./projects/des_cluster/scripts/make_example_files.py bench
It reads the emulator and sampler blocks from the projects des_y3 and desy1xplanck, which must be installed. The script examples EXAMPLE_EMUL2_{MINIMIZE,PROFILE,NAUTILUS}{1,2}.py are short launchers of cocoa_hybrid_sampling.py that read EXAMPLE_EMUL2_EVALUATE<n>.yaml when they run, so they follow the derived YAML without being rewritten; the script's scripts step stops with a ValueError on such launchers, and its default step, all, therefore stops before the benchmark files (the docstring of the script describes each step). EXAMPLE_EVALUATE3.yaml, EXAMPLE_EVALUATE4.yaml and EXAMPLE_EVALUATE_COVARIANCE.yaml are hand-written, and the script does not touch them.
Note
A change to the data vector, the n(z), the covariance, the examples, or the likelihood defaults also requires refreshing the snapshot of the unit tests (see tests/data_vector/README.md).
The tests/ folder compares likelihood predictions against stored reference
values, checks for race conditions from OpenMP threading, and measures the
numerical error of the default accuracy settings.
tests/README.md describes the checks, how to run them,
the input data snapshots, and how to refresh them.
The port is complete for the model described above: the two likelihoods run, the compiled code is validated against an independent Python reference, and the unit tests cover both combinations. PORT_PLAN.md (section 7) holds the detailed status. The items below are open.
- The data are synthetic. The supplied data vector is a noiseless fiducial model, and its covariance is analytic Gaussian: it has no count–two-point cross block, SSC or trispectrum term. The separate covariance notebook computes a joint forecast with SSC and a biased-tracer cNG approximation. It does not replace the supplied likelihood covariance or include every discrete-halo term.
-
Non-Limber
$w_{cc}$ and$w_{cg}$ differ from the original CosmoLike code in one approximation. That code computes the non-Limber spectrum of the first richness pair of each cluster redshift bin and rescales it by a ratio of cluster biases at the bin midpoint for the other pairs; this code computes every pair from its own radial kernels. Against it, in the Cardinal setup of arXiv:2503.13631, the pair both codes compute exactly agrees to 0.2-1.0%, and the rescaled pairs differ by up to 7% for the richest pair of the highest redshift bin. - Cluster lensing has NLA intrinsic alignment only. There is no TATT in the cluster lensing code, and the examples run NLA in every block.
-
Neutrinos in the halo mass function. The cluster combinations use the cold dark matter + baryon prescription described in Cluster options with one massive neutrino state in CAMB, while DES ran three degenerate ones; the two differ by up to 2.6% in the counts at the same
$\Omega_\nu h^2$ . One state is the convention of the Cosmolike projects. On the emulator path, whose matter power spectrum emulator has no neutrino input, the likelihood approximates the cb spectrum as$P_{lin}/(1 - f_\nu)^2$ . -
Emulated Boltzmann inputs. The emulators of the EMUL2 examples are fixed at a neutrino mass of 0.06 eV. At equal neutrino mass they differ from CAMB by
$\Delta\chi^2 = 1.6$ on 6x2pt + N (the cluster counts differ by 1.5% in the median). -
The Y1 switches are not validated end to end. The options that reproduce the DES Y1 choices (
cluster_selection_model: 1,cluster_ytransform: 0, and the magnification and intrinsic-alignment switches) exist, but only the defaults have been validated. - No parameter-recovery chain. No MCMC recovers the input parameters from the synthetic data, and no independent review checks the model against the paper.
-
Thread scaling. Going from 4 to 8 threads gains only a factor of 1.4 on 6x2pt + N; the cause has not been measured. Two optimizations of the cluster tables are left (the one-halo table, and the
$w_{cc}$ and$w_{cg}$ spectra tables). -
Angular binning in the compiled interface. cosmolike caches the bin-averaged Legendre kernels by the number of angular bins and the table key, not by the angular range, so a call to
init_binningwith a new range and the same number of bins returns the values of the old range. The notebook wrappers avoid this by drawing a new table key on every call. -
No response functions for the cluster blocks. The data-vector plotting functions of
cosmolike_notebook_utilshave a cluster version (plot_datavectors_cluster.py); the response helpers (plot_response.py) do not.
The covariance tools compute Gaussian (G), super-sample (SSC), connected non-Gaussian (cNG) and total matrices before scale cuts. The example is a joint 6×2pt + counts forecast whose Gaussian spectra are non-Limber with redshift-space distortions at low multipoles for every pair with a galaxy or cluster leg, as the likelihood's clustering spectra are; SSC and cNG are Limber. covariance/README.md explains compilation, the production CLI, exploratory notebooks, accuracy settings and output files.
Data-vector options belong to the selected likelihood block. Covariance
options belong to the evaluate YAML's covariance block. They use separate
names and settings; changing one does not refine the other.
| Data-vector setting | What it changes |
|---|---|
accuracyboost |
Overall interpolation-table resolution. |
integration_accuracy |
Quadrature resolution; levels 5/6/7 allow 2048/4096/8192 points per Limber panel. Refine independently of interpolation. |
internal_accuracyboost |
C-FAST-PT convolution grid. |
nonlimber_accuracyboost |
Non-Limber distance sampling. |
pk_z_refinement |
Nested redshift refinement of matter-power inputs. |
lmax |
Real-space angular-transform cutoff, where a real-space transform is used. |
kmax_boltzmann |
Requested Boltzmann power range; coordinate it with the theory settings. |
adopt_limber_gg and adopt_limber_gs choose a projection approximation.
photoz_interpolation_type chooses how n(z) is interpolated, while
photoz_zmid_convention describes the input coordinates. These are modeling
or input-convention choices, not interchangeable accuracy boosts.
photoz_histogram_akima: 0 retains the original midpoint n(z) reconstruction; 1 selects histogram preparation followed by Akima for source and lens samples. photoz_histogram_akima_factor chooses 3 (default), 5 or 7 preparation cells per original uniform bin. See the reconstruction comparisons and area plots. The selected first factor never changes with an accuracy boost.
The default data-vector power grid has 1,500 wavenumbers at boost 1.
Covariance alone uses power_accuracyboost: 8 to prepare 11,993 nodes by
natural cubic interpolation before C linear lookup. Its accuracy_boost
refines tables and cutoffs; its integration_accuracy independently selects
quadrature levels 0–4. See the complete covariance accuracy table.
CAMB's theory.camb.extra_args.AccuracyBoost controls CAMB, not CosmoLike.
Check interpolation, quadrature, input-power sampling and transform cutoffs
separately at fixed cosmology and measurement bins. Narrow n(z) overlaps
particularly require a quadrature check; increasing accuracyboost alone
is not that check. The data-vector test guide
and covariance test guide state what each sector
actually verifies. A passing regression or a larger boost is not a general
claim of survey or Fisher convergence.