Fisher Forecasts
HIcosmo provides professional Fisher matrix analysis tools, supporting 21cm intensity mapping survey forecasts, multi-probe joint analysis, and parameter constraint predictions.
Fisher Matrix Fundamentals
Fisher Information Matrix
The Fisher information matrix quantifies the curvature of the likelihood function in parameter space, defined as:
For a Gaussian likelihood, the Fisher matrix can be computed from the covariance matrix \(C\) and the theoretical prediction \(\mu\):
Parameter Constraints
The \(1\sigma\) constraints on parameters are given by the covariance matrix:
Marginalized constraints: When nuisance parameters exist, the constraints on target parameters require integration over nuisance parameters:
Conditional constraints: Constraints are tighter when other parameters are fixed:
Quick Start
3 lines to complete a Fisher forecast:
from hicosmo.models import CPL
from hicosmo.fisher import IntensityMappingFisher
result = IntensityMappingFisher.forecast('ska1_mid_band2', CPL(), ['w0', 'wa'])
print(result)
IntensityMappingFisher Class
IntensityMappingFisher is the core class for 21cm intensity mapping Fisher forecasts, implementing the Bull et al. (2016) method.
Class Method Interface (Recommended)
from hicosmo.models import ILCDM
from hicosmo.fisher import IntensityMappingFisher
# 3 lines to complete a forecast
ilcdm = ILCDM(H0=67.36, Omega_m=0.3153, beta=0.001)
result = IntensityMappingFisher.forecast('tianlai', ilcdm, ['beta', 'H0'])
print(result)
Example Output:
======================================================================
Fisher Forecast Results: tianlai
======================================================================
Cosmology: ILCDM
Redshift bins: 3
Parameters: beta, H0
1σ Constraints:
----------------------------------------------------------------------
σ(beta ) = 1.340000e-02
σ(H0 ) = 8.250000e-01
======================================================================
Instance Interface
Use the instance interface when multiple forecasts are needed:
from hicosmo.fisher import IntensityMappingFisher, load_survey
from hicosmo.models import CPL
# Load survey configuration
survey = load_survey('ska1_mid_band2')
cosmology = CPL(H0=67.36, Omega_m=0.3153, w0=-1.0, wa=0.0)
# Create Fisher calculator
fisher = IntensityMappingFisher(survey, cosmology)
# Multiple forecasts
result1 = fisher.parameter_forecast(['w0', 'wa'])
result2 = fisher.parameter_forecast(['H0', 'Omega_m'])
With Marginalization
Marginalize over nuisance parameters:
result = IntensityMappingFisher.forecast(
'ska1_mid_band2',
cpl_model,
params=['w0', 'wa'],
marginalize_over=['H0', 'Omega_m', 'gamma']
)
print(f"σ(w0) = {result.errors['w0']:.4f}")
print(f"σ(wa) = {result.errors['wa']:.4f}")
FisherForecastResult Object
The result object returned by forecast() contains:
Attribute |
Type |
Description |
|---|---|---|
|
list |
List of parameter names |
|
dict |
\(1\sigma\) constraints |
|
ndarray |
Fisher matrix |
|
ndarray |
Covariance matrix |
|
ndarray |
Correlation matrix |
|
str |
Survey name |
|
int |
Number of redshift bins |
# Access results
print(f"σ(w0) = {result.errors['w0']:.4f}")
print(f"w0-wa correlation coefficient: {result.correlation[0,1]:.3f}")
# Convert to dictionary (compatible with legacy API)
data = result.to_dict()
Survey Configurations
HIcosmo includes built-in configurations for multiple 21cm intensity mapping surveys.
Available Surveys
from hicosmo.fisher import list_available_surveys
surveys = list_available_surveys()
print(surveys)
# ['ska1_mid_band2', 'ska1_wide_band1', 'tianlai', 'bingo', 'meerkat', 'chime', ...]
Survey |
Redshift Range |
Features |
|---|---|---|
ska1_mid_band2 |
0.0 - 0.5 |
SKA1-MID medium-deep, Band 2 |
ska1_wide_band1 |
0.4 - 1.0 |
SKA1-MID wide field, Band 1 |
tianlai |
0.8 - 1.2 |
Tianlai experiment, cylinder array |
bingo |
0.13 - 0.45 |
Brazilian 21cm project |
meerkat |
0.0 - 0.6 |
South African MeerKAT array |
chime |
0.8 - 2.5 |
Canadian CHIME cylinder array |
Loading a Survey
from hicosmo.fisher import load_survey
survey = load_survey('ska1_mid_band2')
# View survey information
print(f"Name: {survey.name}")
print(f"Description: {survey.description}")
print(f"Redshift bins: {len(survey.redshift_bins)}")
print(f"Number of dishes: {survey.instrument.ndish}")
print(f"Survey area: {survey.instrument.survey_area_deg2} deg2")
Survey Configuration Format
Surveys are configured in YAML format (located in hicosmo/fisher/surveys/):
name: ska1_mid_band2
description: "SKA1-MID Medium-Deep Band 2 survey"
# Hardware configuration
instrument:
telescope_type: single_dish
ndish: 133
dish_diameter_m: 15.0
nbeam: 1
# Observing strategy
observing:
survey_area_deg2: 5000.0
total_time_hours: 10000.0
channel_width_hz: 50000.0
# Noise parameters
noise:
system_temperature_K: 13.5
sky_temperature:
model: power_law
T_ref_K: 25.0
nu_ref_MHz: 408.0
beta: 2.75
# HI tracers
hi_tracers:
bias:
model: polynomial
coefficients: [0.67, 0.18, 0.05]
density:
model: polynomial
coefficients: [0.00048, 0.00039, -0.000065]
# Redshift binning
redshift_bins:
default_delta_z: 0.1
centers: [0.05, 0.15, 0.25, 0.35, 0.45]
21cm Physics
Brightness Temperature
21cm brightness temperature formula (Santos et al. 2015):
Where \(\Omega_{\text{HI}}\) is the HI density parameter and \(E(z) = H(z)/H_0\).
Power Spectrum
The 21cm power spectrum is:
Where: - \(b(z)\) is the HI bias factor - \(\beta = f/b\) is the redshift-space distortion parameter - \(f = d\ln D/d\ln a\) is the growth rate - \(\mu = \cos\theta\) is the cosine of the angle to the line of sight - \(P_m(k,z)\) is the matter power spectrum
Effective Volume
The Fisher information-weighted effective volume:
Noise Power Spectrum
Instrumental noise power spectrum:
Where \(W(k_\perp)\) is the beam window function and \(\sigma_{\text{pix}}\) is the pixel noise.
FisherMatrix Class
For general Fisher matrix computations (not 21cm-specific), use the FisherMatrix class.
Basic Usage
from hicosmo.fisher import FisherMatrix, FisherMatrixConfig
# Configuration
config = FisherMatrixConfig(
differentiation_method='automatic', # Use JAX automatic differentiation
regularization=True
)
# Create calculator
calculator = FisherMatrix(config)
# Compute Fisher matrix
fisher_matrix, param_names = calculator.compute_fisher_matrix(
likelihood_func=my_likelihood,
parameters=params,
fiducial_values={'H0': 67.36, 'Omega_m': 0.315}
)
Configuration Options
from hicosmo.fisher import FisherMatrixConfig
config = FisherMatrixConfig(
# Differentiation method
differentiation_method='automatic', # 'automatic', 'numerical', 'hybrid'
step_size=1e-6,
fallback_to_numerical=True,
# Regularization
regularization=True,
reg_lambda=1e-10,
svd_threshold=1e-12,
# Validation
check_symmetry=True,
check_positive_definite=True,
# Performance
vectorize_derivatives=True,
cache_derivatives=True
)
Matrix Combination
Combine multi-probe Fisher matrices:
# Compute Fisher matrices for each probe
fisher_bao, params_bao = calculator.compute_fisher_matrix(bao_likelihood, ...)
fisher_sn, params_sn = calculator.compute_fisher_matrix(sn_likelihood, ...)
# Combine
combined_fisher, combined_params = calculator.combine_fisher_matrices(
[(fisher_bao, params_bao), (fisher_sn, params_sn)],
probe_names=['BAO', 'SN']
)
Parameter Marginalization
# Marginalize over nuisance parameters
marginalized_fisher, remaining_params = calculator.marginalize_parameters(
fisher_matrix,
param_names,
marginalize_over=['M_B', 'delta_M']
)
Dark Energy Figure of Merit
The constraining power of dark energy experiments is quantified by the Figure of Merit (FoM):
This is equivalent to the inverse of the area enclosed by the \(1\sigma\) contour in the \(w_0\)-\(w_a\) plane.
from hicosmo.models import CPL
from hicosmo.fisher import IntensityMappingFisher
import numpy as np
# Forecast w0-wa constraints
cpl = CPL(H0=67.36, Omega_m=0.3153, w0=-1.0, wa=0.0)
result = IntensityMappingFisher.forecast('ska1_mid_band2', cpl, ['w0', 'wa'])
# Compute FoM
fom = 1.0 / np.sqrt(np.linalg.det(result.covariance))
print(f"Dark Energy FoM: {fom:.1f}")
Growth Parameter Forecasts
HIcosmo supports growth parameter forecasts for modified gravity theories.
Growth Parameterization
The growth rate is parameterized as:
The deviation parameters are:
In General Relativity: \(\gamma_0 = 0.55\), \(\gamma_1 = \eta_0 = \eta_1 = 0\).
Growth Scenarios
HIcosmo implements the four growth scenarios from Bull et al. (2016):
from hicosmo.fisher.intensity_mapping import GrowthScenario
# Available scenarios
scenarios = [
'gr', # General Relativity (no free growth parameters)
'gamma0_free', # gamma_0 free, others fixed
'gamma1_free', # gamma_1 free, others fixed
'eta0_free', # eta_0 free, others fixed
'eta1_free', # eta_1 free, others fixed
'all_free', # All growth parameters free
]
# Use a growth scenario
scenario = GrowthScenario('gamma0_free')
print(f"Free parameters: {scenario.free_params}")
print(f"Fixed parameters: {scenario.fixed_params}")
Visualization
Visualizing Fisher forecast results:
from hicosmo.visualization import Plotter, plot_fisher_contours
import numpy as np
# Method 1: Using Plotter.from_fisher
plotter = Plotter.from_fisher(
mean=result.cosmology_summary['fiducial'],
covariance=result.covariance,
param_names=result.params
)
plotter.corner(filename='forecast.pdf')
# Method 2: Using standalone function
plot_fisher_contours(
mean=[-1.0, 0.0],
covariance=result.covariance,
param_names=['w0', 'wa'],
filename='de_forecast.pdf'
)
Multi-Survey Comparison
from hicosmo.models import CPL
from hicosmo.fisher import IntensityMappingFisher
from hicosmo.visualization import Plotter
cpl = CPL()
surveys = ['ska1_mid_band2', 'tianlai', 'bingo']
results = []
for survey in surveys:
result = IntensityMappingFisher.forecast(survey, cpl, ['w0', 'wa'])
results.append(result)
# Comparison plot (using Plotter.from_fisher multiple times)
# Or manually generate Gaussian samples and use Plotter
Complete Examples
SKA1 Dark Energy Forecast
from hicosmo.models import CPL
from hicosmo.fisher import IntensityMappingFisher, list_available_surveys
import numpy as np
# Define the cosmological model
fiducial = CPL(
H0=67.36,
Omega_m=0.3153,
Omega_b=0.0493,
w0=-1.0,
wa=0.0,
sigma8=0.811,
n_s=0.9649
)
# Forecast w0-wa constraints
result = IntensityMappingFisher.forecast(
'ska1_mid_band2',
fiducial,
params=['w0', 'wa'],
marginalize_over=['H0', 'Omega_m']
)
# Print results
print(result)
# Compute FoM
fom = 1.0 / np.sqrt(np.linalg.det(result.covariance))
print(f"\nDark Energy FoM: {fom:.1f}")
# Correlation coefficient
print(f"w0-wa correlation: {result.correlation[0,1]:.3f}")
Interacting Dark Energy Forecast
from hicosmo.models import ILCDM
from hicosmo.fisher import IntensityMappingFisher
# Interacting dark energy model
ilcdm = ILCDM(
H0=67.36,
Omega_m=0.3153,
beta=0.001 # Interaction strength
)
# Tianlai constraints on beta
result = IntensityMappingFisher.forecast(
'tianlai',
ilcdm,
params=['beta', 'H0', 'Omega_m']
)
print(f"Tianlai constraints on the interaction parameter:")
print(f"sigma(beta) = {result.errors['beta']:.4e}")
Multi-Survey Joint Analysis
from hicosmo.models import CPL
from hicosmo.fisher import IntensityMappingFisher, load_survey, FisherMatrix
import numpy as np
cpl = CPL()
surveys = ['ska1_mid_band2', 'tianlai', 'bingo']
# Collect Fisher matrices from each survey
fisher_matrices = []
for survey_name in surveys:
result = IntensityMappingFisher.forecast(
survey_name, cpl, ['w0', 'wa', 'H0', 'Omega_m']
)
fisher_matrices.append((result.fisher_matrix, result.params))
# Combine Fisher matrices
calculator = FisherMatrix()
combined_fisher, combined_params = calculator.combine_fisher_matrices(
fisher_matrices,
probe_names=surveys
)
# Compute joint constraints
combined_cov = np.linalg.inv(combined_fisher)
combined_errors = np.sqrt(np.diag(combined_cov))
print("Joint constraints:")
for i, param in enumerate(combined_params):
print(f" sigma({param}) = {combined_errors[i]:.4e}")
Performance Benchmarks
Operation |
Time |
Notes |
|---|---|---|
Single-survey Fisher forecast |
~0.5s |
5 redshift bins |
Full parameter forecast (with marginalization) |
~1.2s |
6 parameters |
Automatic differentiation Hessian |
~0.1s |
JAX JIT |
FAQ
Q: How to customize a survey configuration?
Create a YAML file and use IntensityMappingSurvey.from_file():
from hicosmo.fisher import IntensityMappingSurvey
survey = IntensityMappingSurvey.from_file('my_survey.yaml')
Q: What if the Fisher matrix is not positive definite?
Enable regularization:
from hicosmo.fisher import FisherMatrixConfig
config = FisherMatrixConfig(
regularization=True,
reg_lambda=1e-8
)
Q: How to compare different cosmological models?
Use the same survey configuration with different models:
from hicosmo.models import LCDM, wCDM, CPL
survey = 'ska1_mid_band2'
result_lcdm = IntensityMappingFisher.forecast(survey, LCDM(), ['H0', 'Omega_m'])
result_wcdm = IntensityMappingFisher.forecast(survey, wCDM(), ['H0', 'Omega_m', 'w0'])
result_cpl = IntensityMappingFisher.forecast(survey, CPL(), ['H0', 'Omega_m', 'w0', 'wa'])
Next Steps
Visualization: Display Fisher forecast results
Cosmological Models: Learn about available models