This is a fixed-text formatted version of a Jupyter notebook
- Try online
- You can contribute with your own notebooks in this GitHub repository.
- Source files: spectrum_simulation_cta.ipynb | spectrum_simulation_cta.py
Spectrum simulation for CTA¶
A quick example how to simulate and fit a spectrum for the Cherenkov Telescope Array (CTA).
We will use the following classes:
- gammapy.spectrum.SpectrumObservation
- gammapy.spectrum.SpectrumSimulation
- gammapy.spectrum.SpectrumFit
- gammapy.irf.load_cta_irfs
Setup¶
[1]:
%matplotlib inline
import matplotlib.pyplot as plt
[2]:
import numpy as np
import astropy.units as u
from gammapy.irf import EnergyDispersion, EffectiveAreaTable
from gammapy.spectrum import SpectrumSimulation, SpectrumFit
from gammapy.spectrum.models import PowerLaw
from gammapy.irf import load_cta_irfs
Simulation¶
[3]:
# Define simulation parameters parameters
livetime = 1 * u.h
offset = 0.5 * u.deg
# Energy from 0.1 to 100 TeV with 10 bins/decade
energy = np.logspace(-1, 2, 31) * u.TeV
[4]:
# Define spectral model
model = PowerLaw(
index=2.1,
amplitude=2.5e-12 * u.Unit("cm-2 s-1 TeV-1"),
reference=1 * u.TeV,
)
[5]:
# Load IRFs
filename = (
"$GAMMAPY_DATA/cta-1dc/caldb/data/cta/1dc/bcf/South_z20_50h/irf_file.fits"
)
cta_irf = load_cta_irfs(filename)
[6]:
aeff = cta_irf["aeff"].to_effective_area_table(offset=offset, energy=energy)
aeff.plot()
plt.loglog()
print(cta_irf["aeff"].data)
NDDataArray summary info
energy : size = 42, min = 0.014 TeV, max = 177.828 TeV
offset : size = 6, min = 0.500 deg, max = 5.500 deg
Data : size = 252, min = 0.000 m2, max = 5371581.000 m2
[7]:
edisp = cta_irf["edisp"].to_energy_dispersion(
offset=offset, e_true=energy, e_reco=energy
)
edisp.plot_matrix()
print(edisp.data)
NDDataArray summary info
e_true : size = 30, min = 0.112 TeV, max = 89.125 TeV
e_reco : size = 30, min = 0.112 TeV, max = 89.125 TeV
Data : size = 900, min = 0.000, max = 0.926
[8]:
# Simulate data
sim = SpectrumSimulation(
aeff=aeff, edisp=edisp, source_model=model, livetime=livetime
)
sim.simulate_obs(seed=42, obs_id=0)
[9]:
sim.obs.peek()
print(sim.obs)
*** Observation summary report ***
Observation Id: 0
Livetime: 1.000 h
On events: 411
Off events: 0
Alpha: 1.000
Bkg events in On region: 0.00
Excess: 411.00
Gamma rate: 6.85 1 / min
Bkg rate: 0.00 1 / min
Sigma: nan
energy range: 0.10 TeV - 100.00 TeV
Spectral analysis¶
Now that we have some simulated CTA counts spectrum, let’s analyse it.
[10]:
# Fit data
fit = SpectrumFit(obs_list=sim.obs, model=model, stat="cash")
fit.run()
result = fit.result[0]
[11]:
print(result)
Fit result info
---------------
Model: PowerLaw
Parameters:
name value error unit min max frozen
--------- --------- --------- -------------- --- --- ------
index 2.116e+00 3.446e-02 nan nan False
amplitude 2.382e-12 1.205e-13 cm-2 s-1 TeV-1 nan nan False
reference 1.000e+00 0.000e+00 TeV nan nan True
Covariance:
name index amplitude reference
--------- ---------- ---------- ---------
index 1.188e-03 -9.160e-16 0.000e+00
amplitude -9.160e-16 1.451e-26 0.000e+00
reference 0.000e+00 0.000e+00 0.000e+00
Statistic: -1591.397 (cash)
Fit Range: [ 0.1 100. ] TeV
[12]:
energy_range = [0.1, 100] * u.TeV
model.plot(energy_range=energy_range, energy_power=2)
result.model.plot(energy_range=energy_range, energy_power=2)
result.model.plot_error(energy_range=energy_range, energy_power=2);
Exercises¶
- Change the observation time to something longer or shorter. Does the observation and spectrum results change as you expected?
- Change the spectral model, e.g. add a cutoff at 5 TeV, or put a steep-spectrum source with spectral index of 4.0
[13]:
# Start the exercises here!
What next?¶
In this tutorial we simulated and analysed the spectrum of source using CTA prod 2 IRFs.
If you’d like to go further, please see the other tutorial notebooks.