Fiducial Spectra
LiLit needs fiducial (theoretical) power spectra to compute forecasts. This section explains how these are handled and how to customize them.
Default: Planck 2018 Best-Fit
If you don’t specify custom fiducial spectra, LiLit automatically computes them using Planck 2018 best-fit cosmological parameters. This provides a reasonable baseline for most forecasting studies.
The default cosmological parameters used are:
\(H_0 = 67.36\) km/s/Mpc
\(\Omega_b h^2 = 0.02237\)
\(\Omega_{cdm} h^2 = 0.1200\)
\(\tau_{reio} = 0.0544\)
\(A_s = 2.1 \times 10^{-9}\) (at \(k_0 = 0.05\) Mpc⁻¹)
\(n_s = 0.9649\)
For B-mode Analysis
When analyzing B-mode polarization, you must specify the tensor-to-scalar ratio:
from lilit import LiLit
likelihood = LiLit(
fields=["t", "e", "b"],
r=0.01, # Must specify r for B-modes
lmax=[2500, 2000, 500],
fsky=[0.7, 0.7, 0.6]
)
The tensor spectral index \(n_t\) follows the consistency relation \(n_t = -r/8\) unless specified otherwise.
Using Custom Fiducial Spectra
You can provide your own fiducial power spectra using the fiducial_spectra parameter:
# Your custom spectra (example format)
custom_spectra = {
'tt': cl_tt_array, # Temperature auto-correlation
'ee': cl_ee_array, # E-mode auto-correlation
'bb': cl_bb_array, # B-mode auto-correlation
'te': cl_te_array, # Temperature-E cross-correlation
# Add other spectra as needed
}
likelihood = LiLit(
fields=["t", "e", "b"],
fiducial_spectra=custom_spectra,
lmax=[2500, 2000, 500],
fsky=[0.7, 0.7, 0.6]
)
Generating Spectra with CAMB
The recommended way to generate custom fiducial spectra is using CAMB with the CAMBres2dict utility:
import camb
from lilit import CAMBres2dict
# Set up CAMB parameters
pars = camb.CAMBparams()
# Basic cosmology
pars.set_cosmology(
H0=70.0, # Hubble constant
ombh2=0.022, # Baryon density
omch2=0.12, # Cold dark matter density
tau=0.06, # Reionization optical depth
mnu=0.06 # Neutrino mass (eV)
)
# Primordial power spectrum
pars.InitPower.set_params(
As=2.2e-9, # Amplitude of scalar perturbations
ns=0.96, # Scalar spectral index
r=0.01, # Tensor-to-scalar ratio
nt=-0.00125 # Tensor spectral index (or use consistency relation)
)
# Set maximum multipole
pars.set_for_lmax(3000, lens_potential_accuracy=0)
# Generate results
results = camb.get_results(pars)
# Convert to LiLit format
fiducial_spectra = CAMBres2dict(results)
# Use in LiLit
likelihood = LiLit(
fields=["t", "e", "b"],
fiducial_spectra=fiducial_spectra,
lmax=[2500, 2000, 500],
fsky=[0.7, 0.7, 0.6]
)
The CAMBres2dict Function
The CAMBres2dict function converts CAMB results into the dictionary format expected by LiLit:
from lilit import CAMBres2dict
# After running CAMB
cl_dict = CAMBres2dict(camb_results)
# cl_dict contains:
# - 'tt': Temperature power spectrum
# - 'ee': E-mode power spectrum
# - 'bb': B-mode power spectrum
# - 'te': T-E cross-correlation
# etc.
This function handles the unit conversions and formatting needed by LiLit.
Modifying Default Parameters
You can modify specific cosmological parameters while keeping others at Planck 2018 values:
# Example: Different Hubble constant
pars = camb.CAMBparams()
pars.set_cosmology(H0=73.0) # Higher H0, other parameters default to Planck
pars.InitPower.set_params(As=2.1e-9, ns=0.9649, r=0.01)
pars.set_for_lmax(3000)
results = camb.get_results(pars)
custom_spectra = CAMBres2dict(results)
Lensed vs Unlensed Spectra
By default, LiLit uses lensed CMB power spectra, which include the effects of gravitational lensing by large-scale structure. This is appropriate for most analyses.
If you need unlensed spectra for specific studies:
# Get unlensed spectra from CAMB
powers = results.get_cmb_power_spectra(pars, CMB_unit='muK', raw_cl=True)
unlensed_spectra = powers['unlensed_scalar']
# Convert to LiLit format manually or modify CAMBres2dict as needed
Field Combinations
LiLit automatically includes only the power spectra needed for your chosen field combination:
fields = ["t"]: Only TT spectrumfields = ["t", "e"]: TT, EE, TE spectrafields = ["t", "e", "b"]: TT, EE, BB, TE spectrafields = ["b"]: Only BB spectrum
Cross-correlations between fields are automatically included when multiple fields are specified.
Validation
Always validate your fiducial spectra before running forecasts:
import matplotlib.pyplot as plt
# Plot your fiducial spectra
ells = np.arange(2, len(fiducial_spectra['tt']) + 2)
plt.figure(figsize=(12, 8))
plt.subplot(2, 2, 1)
plt.loglog(ells, ells*(ells+1)*fiducial_spectra['tt']/(2*np.pi), 'b-')
plt.xlabel(r'$\ell$')
plt.ylabel(r'$\ell(\ell+1)C_\ell^{TT}/2\pi$ [$\mu$K$^2$]')
plt.title('Temperature')
plt.subplot(2, 2, 2)
plt.loglog(ells, ells*(ells+1)*fiducial_spectra['ee']/(2*np.pi), 'r-')
plt.xlabel(r'$\ell$')
plt.ylabel(r'$\ell(\ell+1)C_\ell^{EE}/2\pi$ [$\mu$K$^2$]')
plt.title('E-mode')
if 'bb' in fiducial_spectra:
plt.subplot(2, 2, 3)
plt.loglog(ells, ells*(ells+1)*fiducial_spectra['bb']/(2*np.pi), 'g-')
plt.xlabel(r'$\ell$')
plt.ylabel(r'$\ell(\ell+1)C_\ell^{BB}/2\pi$ [$\mu$K$^2$]')
plt.title('B-mode')
plt.tight_layout()
plt.show()
This helps ensure your spectra have reasonable amplitudes and shapes before using them in forecasts.