def test_spectrum_dataset_stack_nondiagonal_no_bkg(self): aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges, "HESS") edisp1 = EnergyDispersion.from_gauss(self.src.energy.edges, self.src.energy.edges, 0.1, 0.0) livetime = self.livetime dataset1 = SpectrumDataset(counts=None, livetime=livetime, aeff=aeff, edisp=edisp1, background=None) livetime2 = livetime aeff2 = EffectiveAreaTable(self.src.energy.edges[:-1], self.src.energy.edges[1:], aeff.data.data) edisp2 = EnergyDispersion.from_gauss(self.src.energy.edges, self.src.energy.edges, 0.2, 0.0) dataset2 = SpectrumDataset( counts=self.src.copy(), livetime=livetime2, aeff=aeff2, edisp=edisp2, background=None, ) dataset1.stack(dataset2) assert dataset1.counts is None assert dataset1.background is None assert dataset1.livetime == 2 * self.livetime assert_allclose(dataset1.aeff.data.data.to_value("m2"), aeff.data.data.to_value("m2")) assert_allclose(dataset1.edisp.get_bias(1 * u.TeV), 0.0, atol=1e-3) assert_allclose(dataset1.edisp.get_resolution(1 * u.TeV), 0.1581, atol=1e-2)
def get_map_dataset(sky_model, geom, geom_etrue, edisp=True, **kwargs): """This computes the total npred""" # define background model m = Map.from_geom(geom) m.quantity = 0.2 * np.ones(m.data.shape) background_model = BackgroundModel(m) psf = get_psf(geom_etrue) exposure = get_exposure(geom_etrue) if edisp: # define energy dispersion e_true = geom_etrue.get_axis_by_name("energy").edges e_reco = geom.get_axis_by_name("energy").edges edisp = EnergyDispersion.from_diagonal_response(e_true=e_true, e_reco=e_reco) else: edisp = None # define fit mask center = sky_model.spatial_model.position circle = CircleSkyRegion(center=center, radius=1 * u.deg) mask_fit = background_model.map.geom.region_mask([circle]) return MapDataset( model=sky_model, exposure=exposure, background_model=background_model, psf=psf, edisp=edisp, mask_fit=mask_fit, **kwargs )
def setup(self): etrue = np.logspace(-1, 1, 10) * u.TeV self.e_true = etrue ereco = np.logspace(-1, 1, 5) * u.TeV elo = ereco[:-1] ehi = ereco[1:] self.e_reco = ereco self.aeff = EffectiveAreaTable(etrue[:-1], etrue[1:], np.ones(9) * u.cm**2) self.edisp = EnergyDispersion.from_diagonal_response(etrue, ereco) data = np.ones(elo.shape) data[-1] = 0 # to test stats calculation with empty bins self.on_counts = CountsSpectrum(elo, ehi, data) self.off_counts = CountsSpectrum(elo, ehi, np.ones(elo.shape) * 10) start = u.Quantity([0], "s") stop = u.Quantity([1000], "s") time_ref = Time("2010-01-01 00:00:00.0") self.gti = GTI.create(start, stop, time_ref) self.livetime = self.gti.time_sum self.dataset = SpectrumDatasetOnOff(counts=self.on_counts, counts_off=self.off_counts, aeff=self.aeff, edisp=self.edisp, livetime=self.livetime, acceptance=np.ones(elo.shape), acceptance_off=np.ones(elo.shape) * 10, name="test", gti=self.gti)
def sens(): etrue = np.logspace(0, 1, 21) * u.TeV elo = etrue[:-1] ehi = etrue[1:] area = np.zeros(20) + 1e6 * u.m**2 arf = EffectiveAreaTable(energy_lo=elo, energy_hi=ehi, data=area) ereco = np.logspace(0, 1, 5) * u.TeV rmf = EnergyDispersion.from_diagonal_response(etrue, ereco) bkg_array = np.ones(4) bkg_array[-1] = 1e-3 bkg = CountsSpectrum(energy_lo=ereco[:-1], energy_hi=ereco[1:], data=bkg_array, unit="s-1") sens = SensitivityEstimator(arf=arf, rmf=rmf, bkg=bkg, livetime=1 * u.h, index=2, gamma_min=20, alpha=0.2) sens.run() return sens
def make_observation_list(): """obs with dummy IRF""" nbin = 3 energy = np.logspace(-1, 1, nbin + 1) * u.TeV livetime = 2 * u.h data_on = np.arange(nbin) dataoff_1 = np.ones(3) dataoff_2 = np.ones(3) * 3 dataoff_1[1] = 0 dataoff_2[1] = 0 on_vector = CountsSpectrum(energy_lo=energy[:-1], energy_hi=energy[1:], data=data_on) off_vector1 = CountsSpectrum(energy_lo=energy[:-1], energy_hi=energy[1:], data=dataoff_1) off_vector2 = CountsSpectrum(energy_lo=energy[:-1], energy_hi=energy[1:], data=dataoff_2) aeff = EffectiveAreaTable.from_constant(energy, "1 cm2") edisp = EnergyDispersion.from_gauss(e_true=energy, e_reco=energy, sigma=0.2, bias=0) time_ref = Time("2010-01-01") gti1 = make_gti({ "START": [5, 6, 1, 2], "STOP": [8, 7, 3, 4] }, time_ref=time_ref) gti2 = make_gti({"START": [14], "STOP": [15]}, time_ref=time_ref) obs1 = SpectrumDatasetOnOff( counts=on_vector, counts_off=off_vector1, aeff=aeff, edisp=edisp, livetime=livetime, mask_safe=np.ones(on_vector.energy.nbin, dtype=bool), acceptance=1, acceptance_off=2, name="1", gti=gti1, ) obs2 = SpectrumDatasetOnOff( counts=on_vector, counts_off=off_vector2, aeff=aeff, edisp=edisp, livetime=livetime, mask_safe=np.ones(on_vector.energy.nbin, dtype=bool), acceptance=1, acceptance_off=4, name="2", gti=gti2, ) obs_list = [obs1, obs2] return obs_list
def test_compute_thresholds_from_parametrization(): energy = np.logspace(-2, 2.0, 100) * u.TeV aeff = EffectiveAreaTable.from_parametrization(energy=energy) edisp = EnergyDispersion.from_gauss(e_true=energy, e_reco=energy, sigma=0.2, bias=0) thresh_lo, thresh_hi = compute_energy_thresholds( aeff=aeff, edisp=edisp, method_lo="area_max", method_hi="area_max", area_percent_lo=10, area_percent_hi=90, ) assert_allclose(thresh_lo.to("TeV").value, 0.18557, rtol=1e-4) assert_allclose(thresh_hi.to("TeV").value, 43.818, rtol=1e-4) thresh_lo, thresh_hi = compute_energy_thresholds(aeff=aeff, edisp=edisp, method_hi="area_max", area_percent_hi=70) assert_allclose(thresh_hi.to("TeV").value, 100.0, rtol=1e-4)
def test_io(self, tmp_path): indices = np.array([[1, 3, 6], [3, 3, 2]]) desired = self.edisp.pdf_matrix[indices] self.edisp.write(tmp_path / "tmp.fits") edisp2 = EnergyDispersion.read(tmp_path / "tmp.fits") actual = edisp2.pdf_matrix[indices] assert_allclose(actual, desired)
def setup(self): etrue = np.logspace(-1, 1, 10) * u.TeV self.e_true = etrue ereco = np.logspace(-1, 1, 5) * u.TeV elo = ereco[:-1] ehi = ereco[1:] self.aeff = EffectiveAreaTable(etrue[:-1], etrue[1:], np.ones(9) * u.cm**2) self.edisp = EnergyDispersion.from_diagonal_response(etrue, ereco) data = np.ones(elo.shape) data[-1] = 0 # to test stats calculation with empty bins self.on_counts = CountsSpectrum(elo, ehi, data) self.off_counts = CountsSpectrum(elo, ehi, np.ones(elo.shape) * 10) self.livetime = 1000 * u.s self.dataset = SpectrumDatasetOnOff( counts=self.on_counts, counts_off=self.off_counts, aeff=self.aeff, edisp=self.edisp, livetime=self.livetime, acceptance=np.ones(elo.shape), acceptance_off=np.ones(elo.shape) * 10, obs_id="test", )
def test_io(self, tmpdir): indices = np.array([[1, 3, 6], [3, 3, 2]]) desired = self.edisp.pdf_matrix[indices] writename = str(tmpdir / "rmf_test.fits") self.edisp.write(writename) edisp2 = EnergyDispersion.read(writename) actual = edisp2.pdf_matrix[indices] assert_allclose(actual, desired)
def from_hdulist(cls, hdulist, name=""): """Create map dataset from list of HDUs. Parameters ---------- hdulist : `~astropy.io.fits.HDUList` List of HDUs. Returns ------- dataset : `MapDataset` Map dataset. """ kwargs = {"name": name} if "COUNTS" in hdulist: kwargs["counts"] = Map.from_hdulist(hdulist, hdu="counts") if "EXPOSURE" in hdulist: kwargs["exposure"] = Map.from_hdulist(hdulist, hdu="exposure") if "BACKGROUND" in hdulist: background_map = Map.from_hdulist(hdulist, hdu="background") kwargs["background_model"] = BackgroundModel(background_map) if "EDISP_MATRIX" in hdulist: kwargs["edisp"] = EnergyDispersion.from_hdulist( hdulist, hdu1="EDISP_MATRIX", hdu2="EDISP_MATRIX_EBOUNDS" ) if "EDISP" in hdulist: edisp_map = Map.from_hdulist(hdulist, hdu="edisp") exposure_map = Map.from_hdulist(hdulist, hdu="edisp_exposure") kwargs["edisp"] = EDispMap(edisp_map, exposure_map) if "PSF_KERNEL" in hdulist: psf_map = Map.from_hdulist(hdulist, hdu="psf_kernel") kwargs["psf"] = PSFKernel(psf_map) if "PSF" in hdulist: psf_map = Map.from_hdulist(hdulist, hdu="psf") exposure_map = Map.from_hdulist(hdulist, hdu="psf_exposure") kwargs["psf"] = PSFMap(psf_map, exposure_map) if "MASK_SAFE" in hdulist: mask_safe = Map.from_hdulist(hdulist, hdu="mask_safe") mask_safe.data = mask_safe.data.astype(bool) kwargs["mask_safe"] = mask_safe if "MASK_FIT" in hdulist: mask_fit = Map.from_hdulist(hdulist, hdu="mask_fit") mask_fit.data = mask_fit.data.astype(bool) kwargs["mask_fit"] = mask_fit if "GTI" in hdulist: gti = GTI(Table.read(hdulist, hdu="GTI")) kwargs["gti"] = gti return cls(**kwargs)
def test_from_diagonal_response(self): e_true = [0.5, 1, 2, 4, 6] * u.TeV e_reco = [2, 4, 6] * u.TeV edisp = EnergyDispersion.from_diagonal_response(e_true, e_reco) assert edisp.pdf_matrix.shape == (4, 2) expected = [[0, 0], [0, 0], [1, 0], [0, 1]] assert_equal(edisp.pdf_matrix, expected) # Test square matrix edisp = EnergyDispersion.from_diagonal_response(e_true) assert_allclose(edisp.e_reco.edges.value, e_true.value) assert edisp.e_reco.unit == "TeV" assert_equal(edisp.pdf_matrix[0][0], 1) assert_equal(edisp.pdf_matrix[2][0], 0) assert edisp.pdf_matrix.sum() == 4
def test_set_model(self): aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges, "HESS") edisp = EnergyDispersion.from_diagonal_response( self.src.energy.edges, self.src.energy.edges) dataset = SpectrumDataset(None, self.src, self.livetime, None, aeff, edisp, self.bkg) with pytest.raises(AttributeError): dataset.parameters dataset.model = self.source_model assert dataset.parameters[0] == self.source_model.parameters[0]
def from_hdulist(cls, hdulist, name=""): """Create map dataset from list of HDUs. Parameters ---------- hdulist : `~astropy.io.fits.HDUList` List of HDUs. Returns ------- dataset : `MapDataset` Map dataset. """ init_kwargs = {} init_kwargs["name"] = name if "COUNTS" in hdulist: init_kwargs["counts"] = Map.from_hdulist(hdulist, hdu="counts") if "COUNTS_OFF" in hdulist: init_kwargs["counts_off"] = Map.from_hdulist(hdulist, hdu="counts_off") if "ACCEPTANCE" in hdulist: init_kwargs["acceptance"] = Map.from_hdulist(hdulist, hdu="acceptance") if "ACCEPTANCE_OFF" in hdulist: init_kwargs["acceptance_off"] = Map.from_hdulist( hdulist, hdu="acceptance_off" ) if "EXPOSURE" in hdulist: init_kwargs["exposure"] = Map.from_hdulist(hdulist, hdu="exposure") if "EDISP_MATRIX" in hdulist: init_kwargs["edisp"] = EnergyDispersion.from_hdulist( hdulist, hdu1="EDISP_MATRIX", hdu2="EDISP_MATRIX_EBOUNDS" ) if "PSF_KERNEL" in hdulist: psf_map = Map.from_hdulist(hdulist, hdu="psf_kernel") init_kwargs["psf"] = PSFKernel(psf_map) if "MASK_SAFE" in hdulist: mask_safe_map = Map.from_hdulist(hdulist, hdu="mask_safe") init_kwargs["mask_safe"] = mask_safe_map.data.astype(bool) if "MASK_FIT" in hdulist: mask_fit_map = Map.from_hdulist(hdulist, hdu="mask_fit") init_kwargs["mask_fit"] = mask_fit_map.data.astype(bool) if "GTI" in hdulist: gti = GTI(Table.read(hdulist, hdu="GTI")) init_kwargs["gti"] = gti return cls(**init_kwargs)
def setup(self): self.e_true = np.logspace(0, 1, 101) * u.TeV self.e_reco = self.e_true self.resolution = 0.1 self.bias = 0 self.edisp = EnergyDispersion.from_gauss( e_true=self.e_true, e_reco=self.e_reco, pdf_threshold=1e-7, sigma=self.resolution, bias=self.bias, )
def test_spectrum_dataset_stack_diagonal_safe_mask(self): aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges, "HESS") edisp = EnergyDispersion.from_diagonal_response( self.src.energy.edges, self.src.energy.edges) livetime = self.livetime dataset1 = SpectrumDataset( counts=self.src.copy(), livetime=livetime, aeff=aeff, edisp=edisp, background=self.bkg.copy(), ) livetime2 = 0.5 * livetime aeff2 = EffectiveAreaTable(self.src.energy.edges[:-1], self.src.energy.edges[1:], 2 * aeff.data.data) bkg2 = CountsSpectrum( self.src.energy.edges[:-1], self.src.energy.edges[1:], data=2 * self.bkg.data, ) safe_mask2 = np.ones_like(self.src.data, bool) safe_mask2[0] = False dataset2 = SpectrumDataset( counts=self.src.copy(), livetime=livetime2, aeff=aeff2, edisp=edisp, background=bkg2, mask_safe=safe_mask2, ) dataset1.stack(dataset2) assert_allclose(dataset1.counts.data[1:], self.src.data[1:] * 2) assert_allclose(dataset1.counts.data[0], self.src.data[0]) assert dataset1.livetime == 1.5 * self.livetime assert_allclose(dataset1.background.data[1:], 3 * self.bkg.data[1:]) assert_allclose(dataset1.background.data[0], self.bkg.data[0]) assert_allclose( dataset1.aeff.data.data.to_value("m2"), 4.0 / 3 * aeff.data.data.to_value("m2"), ) assert_allclose(dataset1.edisp.pdf_matrix[1:], edisp.pdf_matrix[1:]) assert_allclose(dataset1.edisp.pdf_matrix[0], 0.5 * edisp.pdf_matrix[0])
def get_test_cases(): e_true = Quantity(np.logspace(-1, 2, 120), "TeV") e_reco = Quantity(np.logspace(-1, 2, 100), "TeV") return [ dict(model=PowerLawSpectralModel(amplitude="1e2 TeV-1"), e_true=e_true, npred=999), dict( model=PowerLaw2SpectralModel(amplitude="1", emin="0.1 TeV", emax="100 TeV"), e_true=e_true, npred=1, ), dict( model=PowerLawSpectralModel(amplitude="1e-11 TeV-1 cm-2 s-1"), aeff=EffectiveAreaTable.from_parametrization(e_true), livetime="10 h", npred=1448.05960, ), dict( model=PowerLawSpectralModel(reference="1 GeV", amplitude="1e-11 GeV-1 cm-2 s-1"), aeff=EffectiveAreaTable.from_parametrization(e_true), livetime="30 h", npred=4.34417881, ), dict( model=PowerLawSpectralModel(amplitude="1e-11 TeV-1 cm-2 s-1"), aeff=EffectiveAreaTable.from_parametrization(e_true), edisp=EnergyDispersion.from_gauss(e_reco=e_reco, e_true=e_true, bias=0, sigma=0.2), livetime="10 h", npred=1437.450076, ), dict( model=TemplateSpectralModel( energy=[0.1, 0.2, 0.3, 0.4] * u.TeV, values=[4.0, 3.0, 1.0, 0.1] * u.Unit("TeV-1"), ), e_true=[0.1, 0.2, 0.3, 0.4] * u.TeV, npred=0.554513062, ), ]
def plot_rmf(): import matplotlib.pyplot as plt from gammapy.irf import EnergyDispersion #filename = 'xspec_test_rmf.fits' filename = '/Users/deil/code/gammalib/inst/cta/test/caldb/dc1/rmf.fits' #filename = '/Users/deil/work/host/howto/ctools_crab/cta-1dc/data/hess/dummy_s0.1.rmf.fits' filename = '/Users/deil/work/host/howto/xspec/Crab/run_rmf61261.fits' logging.info('Reading {0}'.format(filename)) edisp = EnergyDispersion.read(filename) print(edisp) plt.figure(figsize=(5, 5)) edisp.plot() filename = 'xspec_test_rmf.png' logging.info('Writing {0}'.format(filename)) plt.savefig(filename, dpi=200)
def test_compute_thresholds_from_crab_data(): """Obs read from file""" arffile = "$GAMMAPY_DATA/joint-crab/spectra/hess/arf_obs23523.fits" rmffile = "$GAMMAPY_DATA/joint-crab/spectra/hess/rmf_obs23523.fits" aeff = EffectiveAreaTable.read(arffile) edisp = EnergyDispersion.read(rmffile) thresh_lo, thresh_hi = compute_energy_thresholds( aeff=aeff, edisp=edisp, method_lo="energy_bias", method_hi="none", bias_percent_lo=10, bias_percent_hi=10, ) assert_allclose(thresh_lo.to("TeV").value, 0.9174, rtol=1e-4) assert_allclose(thresh_hi.to("TeV").value, 100.0, rtol=1e-4)
def create(cls, e_reco, e_true=None, reference_time="2000-01-01"): """Create empty SpectrumDatasetOnOff. Empty containers are created with the correct geometry. counts, counts_off and aeff are zero and edisp is diagonal. The safe_mask is set to False in every bin. Parameters ---------- e_reco : `~astropy.units.Quantity` edges of counts vector e_true : `~astropy.units.Quantity` edges of effective area table. If not set use reco energy values. Default : None reference_time : `~astropy.time.Time` reference time of the dataset, Default is "2000-01-01" """ if e_true is None: e_true = e_reco counts = CountsSpectrum(e_reco[:-1], e_reco[1:]) counts_off = CountsSpectrum(e_reco[:-1], e_reco[1:]) aeff = EffectiveAreaTable(e_true[:-1], e_true[1:], np.zeros(e_true[:-1].shape) * u.m**2) edisp = EnergyDispersion.from_diagonal_response(e_true, e_reco) mask_safe = np.zeros_like(counts.data, "bool") gti = GTI.create(u.Quantity([], "s"), u.Quantity([], "s"), reference_time) livetime = gti.time_sum acceptance = np.ones_like(counts.data, int) acceptance_off = np.ones_like(counts.data, int) return SpectrumDatasetOnOff( counts=counts, counts_off=counts_off, aeff=aeff, edisp=edisp, mask_safe=mask_safe, acceptance=acceptance, acceptance_off=acceptance_off, livetime=livetime, gti=gti, )
def run(self): self.make_empty_vectors(self.bkg_estimate) self.extract_counts(self.bkg_estimate) aeff = extract_aeff(self.exposure, self.target_position, self.energy) containment_factor = extract_psf_containment( self.psf, self.on_radius, self.energy ) aeff.data.data *= containment_factor # Not the real Fermi-LAT EDISP # Use 5% energy resolution as approximation edisp = EnergyDispersion.from_gauss( e_true=self.energy, e_reco=self.energy, sigma=0.05, bias=0 ) return SpectrumObservation( on_vector=self._on_vector, aeff=aeff, off_vector=self._off_vector, edisp=edisp, )
def extract_edisp(energy): """Dummy migration matrix for the fermi filename Its presence is needed for the sherpa fit, otherwise will trigger the issue commented in https://github.com/sherpa/sherpa/blob/7f9d31714eccfc7851fe2c439e5f186781109211/sherpa/astro/instrument.py#L556 Parameters ---------- energy : `~astropy.units.Quantity` energy binning to calculate the the migration matrix, since it's a mock energy dispersion we assume same binning for `e_true` and `e_reco` Returns ------- `~gammapy.irf.EnergyDispersion` energy dispersion ontained assuming bias 0 and 0.05 resolution """ edisp = EnergyDispersion.from_gauss( e_true=energy, e_reco=energy, sigma=0.05, bias=0 ) return edisp
def test_model(model): print(model) print(model(energy=Q(10, 'TeV'))) print(model.integral(emin=Q(1, 'TeV'), emax=Q(2, 'TeV'))) # plot # butterfly # npred reco_bins = 5 true_bins = 10 e_reco = Q(np.logspace(-1, 1, reco_bins + 1), 'TeV') e_true = Q(np.logspace(-1.5, 1.5, true_bins + 1), 'TeV') livetime = Q(26, 'min') aeff_data = Q(np.ones(true_bins) * 1e5, 'cm2') aeff = EffectiveAreaTable(energy=e_true, data=aeff_data) edisp_data = make_perfect_resolution(e_true, e_reco) edisp = EnergyDispersion(edisp_data, EnergyBounds(e_true), EnergyBounds(e_reco)) npred = calculate_predicted_counts(model=model, livetime=livetime, aeff=aeff, edisp=edisp) print(npred.data)
def from_hdulist(cls, hdulist): """Create map dataset from list of HDUs. Parameters ---------- hdulist : `~astropy.io.fits.HDUList` List of HDUs. Returns ------- dataset : `MapDataset` Map dataset. """ init_kwargs = {} init_kwargs["counts"] = Map.from_hdulist(hdulist, hdu="counts") init_kwargs["exposure"] = Map.from_hdulist(hdulist, hdu="exposure") background_map = Map.from_hdulist(hdulist, hdu="background") init_kwargs["background_model"] = BackgroundModel(background_map) if "EDISP_MATRIX" in hdulist: init_kwargs["edisp"] = EnergyDispersion.from_hdulist( hdulist, hdu1="EDISP_MATRIX", hdu2="EDISP_MATRIX_EBOUNDS") if "PSF_KERNEL" in hdulist: psf_map = Map.from_hdulist(hdulist, hdu="psf_kernel") init_kwargs["psf"] = PSFKernel(psf_map) if "MASK_SAFE" in hdulist: mask_safe_map = Map.from_hdulist(hdulist, hdu="mask_safe") init_kwargs["mask_safe"] = mask_safe_map.data.astype(bool) if "MASK_FIT" in hdulist: mask_fit_map = Map.from_hdulist(hdulist, hdu="mask_fit") init_kwargs["mask_fit"] = mask_fit_map.data.astype(bool) return cls(**init_kwargs)
"""Plot energy dispersion example.""" import matplotlib.pyplot as plt import astropy.units as u import numpy as np from gammapy.irf import EnergyDispersion ebounds = np.logspace(-1, 2, 101) * u.TeV energy_dispersion = EnergyDispersion.from_gauss(e_true=ebounds, e_reco=ebounds, sigma=0.3) energy_dispersion.plot_matrix() plt.show()
bkg = TableModel('bkg') bkg.load(None, bkg_3d.data.value.ravel()) bkg.ampl = 1 bkg.ampl.freeze() # Set the exposure exposure_3d = SkyCube.read(cube_dir / 'exposure_cube_etrue.fits') i_nan = np.where(np.isnan(exposure_3d.data)) exposure_3d.data[i_nan] = 0 exposure_3d.data = exposure_3d.data * 1e4 # Set the mean psf model psf_3d = SkyCube.read(cube_dir / 'psf_cube_etrue.fits') # Load the mean rmf calculated for the 4 Crab runs rmf = EnergyDispersion.read(cube_dir / 'rmf.fits') # Setup combined spatial and spectral model spatial_model = NormGauss2DInt('spatial-model') spectral_model = PowLaw1D('spectral-model') coord = counts_3d.sky_image_ref.coordinates(mode="edges") energies = counts_3d.energies(mode='edges').to("TeV") source_model = CombinedModel3DIntConvolveEdisp( coord=coord, energies=energies, use_psf=True, exposure=exposure_3d, psf=psf_3d, spatial_model=spatial_model, spectral_model=spectral_model, edisp=rmf.data.data, )
def edisp(geom, geom_true): e_reco = geom.get_axis_by_name("energy").edges e_true = geom_true.get_axis_by_name("energy").edges return EnergyDispersion.from_diagonal_response(e_true=e_true, e_reco=e_reco)
def cta_perf_root_to_fits(root_filename, fits_filename): """ Convert CTA performance file from ROOT to FITS format. Parameters ---------- root_filename : str Input ROOT filename fits_filename : str Output FITS filename """ from ROOT import TFile print('Reading {}'.format(root_filename)) root_file = TFile(root_filename) # Bg rate bg_rate = hist1d_to_table(hist=root_file.Get('BGRate')) # ENERG_LO bg_rate.rename_column('x_bin_lo', 'ENERG_LO') bg_rate['ENERG_LO'].unit = u.TeV bg_rate['ENERG_LO'].format = 'E' bg_rate.replace_column('ENERG_LO', 10 ** (bg_rate['ENERG_LO'])) # ENERG_HI bg_rate.rename_column('x_bin_hi', 'ENERG_HI') bg_rate['ENERG_HI'].unit = u.TeV bg_rate['ENERG_HI'].format = 'E' bg_rate.replace_column('ENERG_HI', 10 ** (bg_rate['ENERG_HI'])) # BGD bg_rate.rename_column('y', 'BGD') bg_rate['BGD'].unit = u.Hz bg_rate['BGD'].format = 'E' bg_rate_hdu = fits.BinTableHDU.from_columns([ fits.Column('ENERG_LO', bg_rate['ENERG_LO'].format, unit=bg_rate['ENERG_LO'].unit.to_string(), array=bg_rate['ENERG_LO']), fits.Column('ENERG_HI', bg_rate['ENERG_HI'].format, unit=bg_rate['ENERG_HI'].unit.to_string(), array=bg_rate['ENERG_HI']), fits.Column('BGD', bg_rate['BGD'].format, unit=bg_rate['BGD'].unit.to_string(), array=bg_rate['BGD']), ]) bg_rate_hdu.header.set("EXTNAME", "BACKGROUND") # EffectiveAreaEtrue area = hist1d_to_table(hist=root_file.Get('EffectiveAreaEtrue')) # ENERG_LO area.rename_column('x_bin_lo', 'ENERG_LO') area['ENERG_LO'].unit = u.TeV area['ENERG_LO'].format = 'E' area.replace_column('ENERG_LO', 10 ** (area['ENERG_LO'])) # ENERG_HI area.rename_column('x_bin_hi', 'ENERG_HI') area['ENERG_HI'].unit = u.TeV area['ENERG_HI'].format = 'E' area.replace_column('ENERG_HI', 10 ** (area['ENERG_HI'])) # EFFAREA area.rename_column('y', 'SPECRESP') area['SPECRESP'].unit = u.meter * u.meter area['SPECRESP'].format = 'E' area.replace_column('SPECRESP', area['SPECRESP']) area_hdu = fits.BinTableHDU.from_columns([ fits.Column('ENERG_LO', area['ENERG_LO'].format, unit=area['ENERG_LO'].unit.to_string(), array=area['ENERG_LO']), fits.Column('ENERG_HI', area['ENERG_HI'].format, unit=area['ENERG_HI'].unit.to_string(), array=area['ENERG_HI']), fits.Column('SPECRESP', area['SPECRESP'].format, unit=area['SPECRESP'].unit.to_string(), array=area['SPECRESP']), ]) area_hdu.header.set("EXTNAME", "SPECRESP") # PSF psf = hist1d_to_table(hist=root_file.Get('AngRes')) # ENERG_LO psf.rename_column('x_bin_lo', 'ENERG_LO') psf['ENERG_LO'].unit = u.TeV psf['ENERG_LO'].format = 'E' psf.replace_column('ENERG_LO', 10 ** (psf['ENERG_LO'])) # ENERG_HI psf.rename_column('x_bin_hi', 'ENERG_HI') psf['ENERG_HI'].unit = u.TeV psf['ENERG_HI'].format = 'E' psf.replace_column('ENERG_HI', 10 ** (psf['ENERG_HI'])) # PSF68 psf.rename_column('y', 'PSF68') psf['PSF68'].unit = u.degree psf['PSF68'].format = 'E' psf.replace_column('PSF68', psf['PSF68']) psf_hdu = fits.BinTableHDU.from_columns([ fits.Column('ENERG_LO', psf['ENERG_LO'].format, unit=psf['ENERG_LO'].unit.to_string(), array=psf['ENERG_LO']), fits.Column('ENERG_HI', psf['ENERG_HI'].format, unit=psf['ENERG_HI'].unit.to_string(), array=psf['ENERG_HI']), fits.Column('PSF68', psf['PSF68'].format, unit=psf['PSF68'].unit.to_string(), array=psf['PSF68']), ]) psf_hdu.header.set("EXTNAME", "POINT SPREAD FUNCTION") # MigMatrix (x=e_reco, y=e_true, z=prob) histo_edisp = root_file.Get('MigMatrix') # data data = TH2_to_FITS_data(hist=histo_edisp, flipx=False) # get e_reco x_axis = histo_edisp.GetXaxis() x_nbins = x_axis.GetNbins() x_min = 10 ** (x_axis.GetBinLowEdge(1)) x_max = 10 ** (x_axis.GetBinUpEdge(x_nbins)) e_reco = BinnedDataAxis.logspace(x_min, x_max, x_nbins, unit=u.TeV) # get e_true y_axis = histo_edisp.GetYaxis() y_nbins = y_axis.GetNbins() y_min = 10 ** (y_axis.GetBinLowEdge(1)) y_max = 10 ** (y_axis.GetBinUpEdge(y_nbins)) e_true = BinnedDataAxis.logspace(y_min, y_max, y_nbins, unit=u.TeV) e_disp = EnergyDispersion(data=data, e_true=e_true, e_reco=e_reco) edisp_hdus = e_disp.to_hdulist() # Sensitivity sens = hist1d_to_table(hist=root_file.Get('DiffSens')) # ENERG_LO sens.rename_column('x_bin_lo', 'ENERG_LO') sens['ENERG_LO'].unit = u.TeV sens['ENERG_LO'].format = 'E' sens.replace_column('ENERG_LO', 10 ** (sens['ENERG_LO'])) # ENERG_HI sens.rename_column('x_bin_hi', 'ENERG_HI') sens['ENERG_HI'].unit = u.TeV sens['ENERG_HI'].format = 'E' sens.replace_column('ENERG_HI', 10 ** (sens['ENERG_HI'])) # BGD sens.rename_column('y', 'SENSITIVITY') sens['SENSITIVITY'].unit = u.erg / (u.cm * u.cm * u.s) sens['SENSITIVITY'].format = 'E' sens_hdu = fits.BinTableHDU.from_columns([ fits.Column('ENERG_LO', sens['ENERG_LO'].format, unit=sens['ENERG_LO'].unit.to_string(), array=sens['ENERG_LO']), fits.Column('ENERG_HI', sens['ENERG_HI'].format, unit=sens['ENERG_HI'].unit.to_string(), array=sens['ENERG_HI']), fits.Column('SENSITIVITY', sens['SENSITIVITY'].format, unit=sens['SENSITIVITY'].unit.to_string(), array=sens['SENSITIVITY']), ]) sens_hdu.header.set("EXTNAME", "SENSITIVITY") hdulist = fits.HDUList([ edisp_hdus[0], area_hdu, psf_hdu, edisp_hdus[1], edisp_hdus[2], bg_rate_hdu, sens_hdu, ]) print('Writing {}'.format(fits_filename)) hdulist.writeto(fits_filename, overwrite=True)
import astropy.units as u from gammapy.irf import EnergyDispersion, EffectiveAreaTable from gammapy.spectrum import SpectrumSimulation, SpectrumFit from gammapy.spectrum.models import PowerLaw # ## Create detector # # For the sake of self consistency of this tutorial, we will simulate a simple detector. For a real application you would want to replace this part of the code with loading the IRFs or your detector. # In[ ]: e_true = np.logspace(-2, 2.5, 109) * u.TeV e_reco = np.logspace(-2, 2, 79) * u.TeV edisp = EnergyDispersion.from_gauss(e_true=e_true, e_reco=e_reco, sigma=0.2, bias=0) aeff = EffectiveAreaTable.from_parametrization(energy=e_true) fig, axes = plt.subplots(1, 2, figsize=(12, 6)) edisp.plot_matrix(ax=axes[0]) aeff.plot(ax=axes[1]) # ## Power law # # In this section we will simulate one observation using a power law model. # In[ ]: pwl = PowerLaw(index=2.3, amplitude=1e-11 * u.Unit("cm-2 s-1 TeV-1"),
def get_energy_dispersion(self, position, e_reco, migra_step=5e-3): """Get energy dispersion at a given position. Parameters ---------- position : `~astropy.coordinates.SkyCoord` the target position. Should be a single coordinates e_reco : `~astropy.units.Quantity` Reconstructed energy axis binning migra_step : float Integration step in migration Returns ------- edisp : `~gammapy.irf.EnergyDispersion` the energy dispersion (i.e. rmf object) """ # TODO: reduce code duplication with EnergyDispersion2D.get_response if position.size != 1: raise ValueError( "EnergyDispersion can be extracted at one single position only." ) # axes ordering fixed. Could be changed. pix_ener = np.arange(self.edisp_map.geom.axes[1].nbin) # Define a vector of migration with mig_step step mrec_min = self.edisp_map.geom.axes[0].edges[0] mrec_max = self.edisp_map.geom.axes[0].edges[-1] mig_array = np.arange(mrec_min, mrec_max, migra_step) pix_migra = (mig_array - mrec_min) / mrec_max * self.edisp_map.geom.axes[0].nbin # Convert position to pixels pix_lon, pix_lat = self.edisp_map.geom.to_image().coord_to_pix( position) # Build the pixels tuple pix = np.meshgrid(pix_lon, pix_lat, pix_migra, pix_ener) # Interpolate in the EDisp map. Squeeze to remove dimensions of length 1 edisp_values = np.squeeze( self.edisp_map.interp_by_pix(pix) * u.Unit(self.edisp_map.unit) # * migra_step ) e_trues = self.edisp_map.geom.axes[1].center data = [] for i, e_true in enumerate(e_trues): # We now perform integration over migra # The code is adapted from `~gammapy.EnergyDispersion2D.get_response` # migration value of e_reco bounds migra_e_reco = e_reco / e_true # Compute normalized cumulative sum to prepare integration tmp = np.nan_to_num( np.cumsum(edisp_values[:, i]) / np.sum(edisp_values[:, i])) # Determine positions (bin indices) of e_reco bounds in migration array pos_mig = np.digitize(migra_e_reco, mig_array) - 1 # We ensure that no negative values are found pos_mig = np.maximum(pos_mig, 0) # We compute the difference between 2 successive bounds in e_reco # to get integral over reco energy bin integral = np.diff(tmp[pos_mig]) data.append(integral) data = np.asarray(data) # EnergyDispersion uses edges of true energy bins e_true_edges = self.edisp_map.geom.axes[1].edges e_lo, e_hi = e_true_edges[:-1], e_true_edges[1:] ereco_lo, ereco_hi = (e_reco[:-1], e_reco[1:]) return EnergyDispersion( e_true_lo=e_lo, e_true_hi=e_hi, e_reco_lo=ereco_lo, e_reco_hi=ereco_hi, data=data, )
"""Plot energy dispersion example.""" import numpy as np import matplotlib.pyplot as plt import astropy.units as u from gammapy.irf import EnergyDispersion ebounds = np.logspace(-1, 2, 101) * u.TeV edisp = EnergyDispersion.from_gauss( e_true=ebounds, e_reco=ebounds, bias=0, sigma=0.3, ) edisp.peek() plt.show()
""" from gammapy.irf import EnergyDispersion, EffectiveAreaTable, abramowski_effective_area from gammapy.spectrum.models import PowerLaw from gammapy.spectrum import calculate_predicted_counts, SpectrumExtraction, PHACountsSpectrum, SpectrumObservation from gammapy.utils.random import get_random_state import numpy as np import astropy.units as u import matplotlib.pyplot as plt e_true = SpectrumExtraction.DEFAULT_TRUE_ENERGY e_reco = SpectrumExtraction.DEFAULT_RECO_ENERGY # EDISP edisp = EnergyDispersion.from_gauss(e_true=e_true, e_reco=e_true, sigma=0.2) # AEFF nodes = np.sqrt(e_true[:-1] * e_true[1:]) data = abramowski_effective_area(energy=nodes) aeff = EffectiveAreaTable(data=data, energy=e_true) lo_threshold = aeff.find_energy(0.1 * aeff.max_area) # MODEL model = PowerLaw(index=2.3 * u.Unit(""), amplitude=2.5 * 1e-12 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.TeV) # COUNTS livetime = 2 * u.h npred = calculate_predicted_counts(model=model, aeff=aeff, edisp=edisp, livetime=livetime)
def from_ogip_files(cls, filename): """Read `~gammapy.spectrum.SpectrumDatasetOnOff` from OGIP files. BKG file, ARF, and RMF must be set in the PHA header and be present in the same folder. The naming scheme is fixed to the following scheme * PHA file is named pha_obs{name}.fits * BKG file is named bkg_obs{name}.fits * ARF file is named arf_obs{name}.fits * RMF file is named rmf_obs{name}.fits with {name} the dataset name. Parameters ---------- filename : str OGIP PHA file to read """ filename = make_path(filename) dirname = filename.parent with fits.open(filename, memmap=False) as hdulist: data = _read_ogip_hdulist(hdulist) counts = CountsSpectrum(energy_hi=data["energy_hi"], energy_lo=data["energy_lo"], data=data["data"]) phafile = filename.name try: rmffile = phafile.replace("pha", "rmf") energy_dispersion = EnergyDispersion.read(dirname / rmffile) except OSError: # TODO : Add logger and echo warning energy_dispersion = None try: bkgfile = phafile.replace("pha", "bkg") with fits.open(dirname / bkgfile, memmap=False) as hdulist: data_bkg = _read_ogip_hdulist(hdulist) counts_off = CountsSpectrum( energy_hi=data_bkg["energy_hi"], energy_lo=data_bkg["energy_lo"], data=data_bkg["data"], ) acceptance_off = data_bkg["backscal"] except OSError: # TODO : Add logger and echo warning counts_off, acceptance_off = None, None arffile = phafile.replace("pha", "arf") aeff = EffectiveAreaTable.read(dirname / arffile) mask_safe = np.logical_not(data["quality"]) return cls( counts=counts, aeff=aeff, counts_off=counts_off, edisp=energy_dispersion, livetime=data["livetime"], mask_safe=mask_safe, acceptance=data["backscal"], acceptance_off=acceptance_off, name=str(data["obs_id"]), gti=data["gti"], )
"""Plot energy dispersion example.""" import numpy as np import matplotlib.pyplot as plt from gammapy.irf import EnergyDispersion from gammapy.spectrum import EnergyBounds ebounds = EnergyBounds.equal_log_spacing(0.1, 100, 100, 'TeV') energy_dispersion = EnergyDispersion.from_gauss(ebounds, sigma=0.3) energy_dispersion.plot(type='matrix') plt.show()
"""Plot energy dispersion example.""" import matplotlib.pyplot as plt import astropy.units as u import numpy as np from gammapy.irf import EnergyDispersion ebounds = np.logspace(-1, 2, 101) * u.TeV edisp = EnergyDispersion.from_gauss( e_true=ebounds, e_reco=ebounds, bias=0, sigma=0.3, ) edisp.peek() plt.show()