Skip to content

Guide to cloelib's Architecture

This guide explains the modular architecture of cloelib and provides instructions for contributors to extend the library by adding new implementations of Perturbations and Observables.

Overview

cloelib follows a layered architecture that separates cosmological calculations into distinct components:

graph LR
    A["<b>Background</b><br/>Distances, Hubble, Densities"] --> B["<b>Perturbations</b><br/>Power Spectra, Growth Rates"]
    B --> C["<b>Observables</b><br/>Survey-Specific Predictions"]
    C --> D["<b>Summary Statistics</b><br/>Power Spectra, Correlation Functions"]

    style A fill:#e1f5ff
    style B fill:#f3e5f5
    style C fill:#e8f5e9
    style D fill:#fff3e0

Each layer depends on the previous one, creating a flexible pipeline from fundamental cosmology to final data products.

Design Principles

cloelib embraces the following principles:

  • Modularity: Each module owns one responsibility—Background handles cosmology, Perturbations handles structure growth, Observables handles survey specifics, and Summary Statistics handles final products. This keeps code maintainable, testable, and extensible. The architecture allows easy swapping of external code implementations (e.g., CAMB for CLASS)
  • Extensibility: Uses Python protocols (PEP 544) for type safety and flexibility—any class implementing required methods is valid, with no inheritance needed.
  • Flexibility: Contributors can extend the library without modifying existing code by implementing classes that satisfy the required protocols—no need to touch cloelib source code.
  • Reproducibility: Clear interfaces ensure consistent behavior across implementations, boosting the capacity of the user to reproduce results with other external codes.

Core Components

1. Background

  • Purpose: Compute background quantities as functions of redshift
  • Dependencies: None (foundational layer)
  • Use case: Implementing new Boltzmann solvers or emulators
  • Learn more about Background

2. Perturbations

  • Purpose: Calculate perturbation theory quantities
  • Dependencies: Background module
  • Use case: Adding (non)-linear models or new structure formation codes
  • Learn more about Perturbations

3. Observables

  • Purpose: Compute survey-specific observables
  • Dependencies: Perturbations (for tracers) or Background/Perturbations (for spectroscopic)
  • Use case: Adding new measurement types or survey configurations
  • Learn more about Observables

4. Summary Statistics

Typical Workflow

The standard workflow for computing observables follows this pattern:

# 1. Initialize background cosmology
background = CAMBBackground(H0=67.5, Omega_b0=0.049, ...)

# 2. Initialize perturbations with background
perturbations = CAMBPerturbations(background=background, ...)

# 3. Define observables with perturbations or background
tracer = ShearTracer(perturbations=perturbations, dndz=..., z=..., ...)

# 4. Compute summary statistics
two_point = AngularTwoPoint(tracer1=tracer, tracer2=tracer)
C_ell = two_point.compute_Cl(ells=...)

For Contributors

Each module page includes:

  • Protocol definitions specifying required methods and properties
  • Step-by-step guides for adding new implementations
  • Code examples demonstrating proper usage
  • Interface specifications for connecting with external codes
  • Testing recommendations

The protocol-based design means contributors only need to implement the required methods without inheriting from base classes or understanding the entire codebase.

Additional Resources

Support

For questions about the code structure or implementing new components: