def make_mask_energy_aeff_max(self, dataset): """Make safe energy mask from effective area maximum value. Parameters ---------- dataset : `~gammapy.datasets.MapDataset` or `~gammapy.datasets.SpectrumDataset` Dataset to compute mask for. Returns ------- mask_safe : `~numpy.ndarray` Safe data range mask. """ geom = dataset._geom if self.position is None: position = PointSkyRegion(dataset.counts.geom.center_skydir) else: position = PointSkyRegion(self.position) exposure = dataset.exposure.get_spectrum(position) energy = exposure.geom.axes["energy_true"] aeff = EffectiveAreaTable( energy_axis_true=energy, data=(exposure.quantity / dataset.gti.time_sum).squeeze(), ) aeff_thres = (self.aeff_percent / 100) * aeff.max_area e_min = aeff.find_energy(aeff_thres) return geom.energy_mask(emin=e_min)
def make_mask_energy_aeff_max(self, dataset): """Make safe energy mask from effective area maximum value. Parameters ---------- dataset : `~gammapy.datasets.MapDataset` or `~gammapy.datasets.SpectrumDataset` Dataset to compute mask for. Returns ------- mask_safe : `~numpy.ndarray` Safe data range mask. """ geom = dataset._geom if isinstance(dataset, MapDataset): position = self.position if position is None: position = dataset.counts.geom.center_skydir exposure = dataset.exposure energy = exposure.geom.get_axis_by_name("energy_true") coord = MapCoord.create({"skycoord": position, "energy_true": energy.center}) exposure_1d = exposure.interp_by_coord(coord) aeff = EffectiveAreaTable( energy_lo=energy.edges[:-1], energy_hi=energy.edges[1:], data=exposure_1d, ) else: aeff = dataset.aeff aeff_thres = (self.aeff_percent / 100) * aeff.max_area e_min = aeff.find_energy(aeff_thres) return geom.energy_mask(emin=e_min)
def test_spectrum_dataset_stack_nondiagonal_no_bkg(self): aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges, "HESS") edisp1 = EDispKernel.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 = EDispKernel.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=1.2e-3) assert_allclose(dataset1.edisp.get_resolution(1 * u.TeV), 0.1581, atol=1e-2)
def test_spectrum_dataset_stack_nondiagonal_no_bkg(spectrum_dataset): energy = spectrum_dataset.counts.geom.axes[0].edges aeff = EffectiveAreaTable.from_parametrization(energy, "HESS") edisp1 = EDispKernel.from_gauss(energy, energy, 0.1, 0) livetime = 100 * u.s spectrum_dataset1 = SpectrumDataset( counts=spectrum_dataset.counts.copy(), livetime=livetime, aeff=aeff, edisp=edisp1, ) livetime2 = livetime aeff2 = EffectiveAreaTable( energy[:-1], energy[1:], aeff.data.data ) edisp2 = EDispKernel.from_gauss(energy, energy, 0.2, 0.0) spectrum_dataset2 = SpectrumDataset( counts=spectrum_dataset.counts.copy(), livetime=livetime2, aeff=aeff2, edisp=edisp2, ) spectrum_dataset1.stack(spectrum_dataset2) assert spectrum_dataset1.background is None assert spectrum_dataset1.livetime == 2 * livetime assert_allclose( spectrum_dataset1.aeff.data.data.to_value("m2"), aeff.data.data.to_value("m2") ) assert_allclose(spectrum_dataset1.edisp.get_bias(1 * u.TeV), 0.0, atol=1.2e-3) assert_allclose(spectrum_dataset1.edisp.get_resolution(1 * u.TeV), 0.1581, atol=1e-2)
def test_spectrum_dataset_stack_diagonal_safe_mask(spectrum_dataset): geom = spectrum_dataset.counts.geom energy = MapAxis.from_energy_bounds("0.1 TeV", "10 TeV", nbin=30) energy_true = MapAxis.from_energy_bounds("0.1 TeV", "10 TeV", nbin=30, name="energy_true") aeff = EffectiveAreaTable.from_parametrization(energy.edges, "HESS") edisp = EDispKernelMap.from_diagonal_response(energy, energy_true, geom=geom.to_image()) livetime = 100 * u.s background = spectrum_dataset.background spectrum_dataset1 = SpectrumDataset( counts=spectrum_dataset.counts.copy(), livetime=livetime, aeff=aeff, edisp=edisp.copy(), background=background.copy(), ) livetime2 = 0.5 * livetime aeff2 = EffectiveAreaTable(energy.edges[:-1], energy.edges[1:], 2 * aeff.data.data) bkg2 = RegionNDMap.from_geom(geom=geom, data=2 * background.data) geom = spectrum_dataset.counts.geom data = np.ones(spectrum_dataset.data_shape, dtype="bool") data[0] = False safe_mask2 = RegionNDMap.from_geom(geom=geom, data=data) spectrum_dataset2 = SpectrumDataset( counts=spectrum_dataset.counts.copy(), livetime=livetime2, aeff=aeff2, edisp=edisp, background=bkg2, mask_safe=safe_mask2, ) spectrum_dataset1.stack(spectrum_dataset2) reference = spectrum_dataset.counts.data assert_allclose(spectrum_dataset1.counts.data[1:], reference[1:] * 2) assert_allclose(spectrum_dataset1.counts.data[0], 141363) assert spectrum_dataset1.livetime == 1.5 * livetime assert_allclose(spectrum_dataset1.background.data[1:], 3 * background.data[1:]) assert_allclose(spectrum_dataset1.background.data[0], background.data[0]) assert_allclose( spectrum_dataset1.aeff.data.data.to_value("m2"), 4.0 / 3 * aeff.data.data.to_value("m2"), ) kernel = edisp.get_edisp_kernel() kernel_stacked = spectrum_dataset1.edisp.get_edisp_kernel() assert_allclose(kernel_stacked.pdf_matrix[1:], kernel.pdf_matrix[1:]) assert_allclose(kernel_stacked.pdf_matrix[0], 0.5 * kernel.pdf_matrix[0])
def test_spectrum_dataset_stack_diagonal_safe_mask(spectrum_dataset): geom = spectrum_dataset.counts.geom energy = np.logspace(-1, 1, 31) * u.TeV aeff = EffectiveAreaTable.from_parametrization(energy, "HESS") edisp = EDispKernel.from_diagonal_response(energy, energy) livetime = 100 * u.s background = spectrum_dataset.background spectrum_dataset1 = SpectrumDataset( counts=spectrum_dataset.counts.copy(), livetime=livetime, aeff=aeff, edisp=edisp, background=background.copy(), ) livetime2 = 0.5 * livetime aeff2 = EffectiveAreaTable(energy[:-1], energy[1:], 2 * aeff.data.data) bkg2 = RegionNDMap.from_geom(geom=geom, data=2 * background.data) geom = spectrum_dataset.counts.geom data = np.ones(spectrum_dataset.data_shape, dtype="bool") data[0] = False safe_mask2 = RegionNDMap.from_geom(geom=geom, data=data) spectrum_dataset2 = SpectrumDataset( counts=spectrum_dataset.counts.copy(), livetime=livetime2, aeff=aeff2, edisp=edisp, background=bkg2, mask_safe=safe_mask2, ) spectrum_dataset1.stack(spectrum_dataset2) reference = spectrum_dataset.counts.data assert_allclose(spectrum_dataset1.counts.data[1:], reference[1:] * 2) assert_allclose(spectrum_dataset1.counts.data[0], 141363) assert spectrum_dataset1.livetime == 1.5 * livetime assert_allclose(spectrum_dataset1.background.data[1:], 3 * background.data[1:]) assert_allclose(spectrum_dataset1.background.data[0], background.data[0]) assert_allclose( spectrum_dataset1.aeff.data.data.to_value("m2"), 4.0 / 3 * aeff.data.data.to_value("m2"), ) assert_allclose(spectrum_dataset1.edisp.pdf_matrix[1:], edisp.pdf_matrix[1:]) assert_allclose(spectrum_dataset1.edisp.pdf_matrix[0], 0.5 * edisp.pdf_matrix[0])
def spectrum_dataset(): energy = np.logspace(-1, 1, 31) * u.TeV livetime = 100 * u.s pwl = PowerLawSpectralModel( index=2.1, amplitude="1e5 cm-2 s-1 TeV-1", reference="0.1 TeV", ) temp_mod = ConstantTemporalModel() model = SkyModel(spectral_model=pwl, temporal_model=temp_mod, name="test-source") aeff = EffectiveAreaTable.from_constant(energy, "1 cm2") axis = MapAxis.from_edges(energy, interp="log", name="energy") background = RegionNDMap.create(region="icrs;circle(0, 0, 0.1)", axes=[axis]) bkg_rate = np.ones(30) / u.s background.quantity = bkg_rate * livetime start = [1, 3, 5] * u.day stop = [2, 3.5, 6] * u.day t_ref = Time(55555, format="mjd") gti = GTI.create(start, stop, reference_time=t_ref) dataset = SpectrumDataset( models=model, aeff=aeff, livetime=livetime, background=background, name="test", gti=gti, ) dataset.fake(random_state=23) return dataset
def setup(self): self.nbins = 30 binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV self.source_model = PowerLawSpectralModel(index=2.1, amplitude=1e5 * u.Unit("cm-2 s-1 TeV-1"), reference=0.1 * u.TeV) self.livetime = 100 * u.s aeff = EffectiveAreaTable.from_constant(binning, "1 cm2") bkg_rate = np.ones(self.nbins) / u.s bkg_expected = (bkg_rate * self.livetime).to_value("") self.bkg = CountsSpectrum(energy_lo=binning[:-1], energy_hi=binning[1:], data=bkg_expected) random_state = get_random_state(23) flux = self.source_model.integral(binning[:-1], binning[1:]) self.npred = (flux * aeff.data.data[0] * self.livetime).to_value("") self.npred += bkg_expected source_counts = random_state.poisson(self.npred) self.src = CountsSpectrum(energy_lo=binning[:-1], energy_hi=binning[1:], data=source_counts) self.dataset = SpectrumDataset( model=self.source_model, counts=self.src, aeff=aeff, livetime=self.livetime, background=self.bkg, )
def simulate_spectrum_dataset(model, random_state=0): edges = np.logspace(-0.5, 1.5, 21) * u.TeV energy_axis = MapAxis.from_edges(edges, interp="log", name="energy") aeff = EffectiveAreaTable.from_parametrization(energy=edges).to_region_map() bkg_model = SkyModel( spectral_model=PowerLawSpectralModel( index=2.5, amplitude="1e-12 cm-2 s-1 TeV-1" ), name="background", ) bkg_model.spectral_model.amplitude.frozen = True bkg_model.spectral_model.index.frozen = True geom = RegionGeom(region=None, axes=[energy_axis]) acceptance = RegionNDMap.from_geom(geom=geom, data=1) edisp = EDispKernelMap.from_diagonal_response( energy_axis=energy_axis, energy_axis_true=energy_axis.copy(name="energy_true"), geom=geom ) dataset = SpectrumDatasetOnOff( aeff=aeff, livetime=100 * u.h, acceptance=acceptance, acceptance_off=5, edisp=edisp ) dataset.models = bkg_model bkg_npred = dataset.npred_sig() dataset.models = model dataset.fake(random_state=random_state, background_model=bkg_npred) return dataset
def setup(self): self.nbins = 30 energy = np.logspace(-1, 1, self.nbins + 1) * u.TeV self.source_model = SkyModel( spectral_model=PowerLawSpectralModel( index=2, amplitude=1e5 * u.Unit("cm-2 s-1 TeV-1"), reference=0.1 * u.TeV ) ) bkg_model = PowerLawSpectralModel( index=3, amplitude=1e4 * u.Unit("cm-2 s-1 TeV-1"), reference=0.1 * u.TeV ) self.alpha = 0.1 random_state = get_random_state(23) npred = self.source_model.spectral_model.integral( energy[:-1], energy[1:] ).value source_counts = random_state.poisson(npred) axis = MapAxis.from_edges(energy, name="energy", interp="log") geom = RegionGeom(region=None, axes=[axis]) self.src = RegionNDMap.from_geom(geom=geom, data=source_counts) self.src.livetime = 1 * u.s self.aeff = EffectiveAreaTable.from_constant(energy, "1 cm2") npred_bkg = bkg_model.integral(energy[:-1], energy[1:]).value bkg_counts = random_state.poisson(npred_bkg) off_counts = random_state.poisson(npred_bkg * 1.0 / self.alpha) self.bkg = RegionNDMap.from_geom(geom=geom, data=bkg_counts) self.off = RegionNDMap.from_geom(geom=geom, data=off_counts)
def test(aeff): assert aeff.data.axes["energy_true"].nbin == 96 assert aeff.data.axes["offset"].nbin == 6 assert aeff.data.data.shape == (96, 6) assert aeff.data.axes["energy_true"].unit == "TeV" assert aeff.data.axes["offset"].unit == "deg" assert aeff.data.data.unit == "m2" assert_quantity_allclose(aeff.high_threshold, 100 * u.TeV, rtol=1e-3) assert_quantity_allclose(aeff.low_threshold, 0.870964 * u.TeV, rtol=1e-3) test_val = aeff.data.evaluate(energy_true="14 TeV", offset="0.2 deg") assert_allclose(test_val.value, 683177.5, rtol=1e-3) # Test ARF export offset = 0.236 * u.deg e_axis = np.logspace(0, 1, 20) * u.TeV effareafrom2d = aeff.to_effective_area_table(offset, e_axis) energy = np.sqrt(e_axis[:-1] * e_axis[1:]) area = aeff.data.evaluate(energy_true=energy, offset=offset) energy_axis_true = MapAxis.from_energy_edges(e_axis, name="energy_true") effarea1d = EffectiveAreaTable(energy_axis_true=energy_axis_true, data=area) actual = effareafrom2d.data.evaluate(energy_true="2.34 TeV") desired = effarea1d.data.evaluate(energy_true="2.34 TeV") assert_equal(actual, desired) # Test ARF export #2 offset = 1.2 * u.deg actual = aeff.to_effective_area_table(offset=offset).data.data desired = aeff.data.evaluate(offset=offset) assert_allclose(actual.value, desired.value.squeeze(), rtol=1e-9)
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 setup(self): self.nbins = 30 binning = np.logspace(-1, 1, self.nbins + 1) * u.TeV self.source_model = PowerLawSpectralModel(index=2, amplitude=1e5 * u.Unit("cm-2 s-1 TeV-1"), reference=0.1 * u.TeV) bkg_model = PowerLawSpectralModel(index=3, amplitude=1e4 * u.Unit("cm-2 s-1 TeV-1"), reference=0.1 * u.TeV) self.alpha = 0.1 random_state = get_random_state(23) npred = self.source_model.integral(binning[:-1], binning[1:]).value source_counts = random_state.poisson(npred) self.src = CountsSpectrum(energy_lo=binning[:-1], energy_hi=binning[1:], data=source_counts) self.src.livetime = 1 * u.s self.aeff = EffectiveAreaTable.from_constant(binning, "1 cm2") npred_bkg = bkg_model.integral(binning[:-1], binning[1:]).value bkg_counts = random_state.poisson(npred_bkg) off_counts = random_state.poisson(npred_bkg * 1.0 / self.alpha) self.bkg = CountsSpectrum(energy_lo=binning[:-1], energy_hi=binning[1:], data=bkg_counts) self.off = CountsSpectrum(energy_lo=binning[:-1], energy_hi=binning[1:], data=off_counts)
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 = EDispKernel.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 extract_aeff(exposure, target_position, energy): energy_log_ctr = np.sqrt(energy[1:] * energy[:-1]) lon = target_position.galactic.l lat = target_position.galactic.b expo_values = exposure.get_by_coord((lon.value, lat.value, energy_log_ctr.value)) table = Table( [energy[:-1], energy[1:], expo_values], names=("ENERG_LO", "ENERG_HI", "SPECRESP"), dtype=("float64", "float64", "float64"), meta={"name": "Fermi-LAT exposure"}, ) table["ENERG_LO"].unit = str(energy.unit) table["ENERG_HI"].unit = str(energy.unit) table["SPECRESP"].unit = "cm2" table.meta["EXTNAME"] = "SPECRESP" table.meta["TELESCOP"] = "Fermi" table.meta["INSTRUME"] = "LAT" table.meta["EXPOSURE"] = "1" table.meta["FILTER"] = "" table.meta["HDUCLASS"] = "OGIP" table.meta["HDUCLAS1"] = "RESPONSE" table.meta["HDUCLAS2"] = "SPECRESP" table.meta["HDUVERS"] = "1.1.0" return EffectiveAreaTable.from_table(table)
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_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 spectrum_dataset(): energy = np.logspace(-1, 1, 31) * u.TeV livetime = 100 * u.s pwl = PowerLawSpectralModel( index=2.1, amplitude="1e5 cm-2 s-1 TeV-1", reference="0.1 TeV", ) model = SkyModel(spectral_model=pwl, name="test-source") aeff = EffectiveAreaTable.from_constant(energy, "1 cm2") axis = MapAxis.from_edges(energy, interp="log", name="energy") background = RegionNDMap.create(region="icrs;circle(0, 0, 0.1)", axes=[axis]) bkg_rate = np.ones(30) / u.s background.quantity = bkg_rate * livetime dataset = SpectrumDataset( models=model, aeff=aeff, livetime=livetime, background=background, name="test", ) dataset.fake(random_state=23) return dataset
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 = EDispKernel.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_spectrum_dataset_stack_diagonal_safe_mask(self): aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges, "HESS") edisp = EDispKernel.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 create(cls, e_reco, e_true=None, region=None, reference_time="2000-01-01", name=None, meta_table=None): """Creates empty spectrum dataset. Empty containers are created with the correct geometry. counts, background and aeff are zero and edisp is diagonal. The safe_mask is set to False in every bin. Parameters ---------- e_reco : `~gammapy.maps.MapAxis` counts energy axis. Its name must be "energy". e_true : `~gammapy.maps.MapAxis` effective area table energy axis. Its name must be "energy-true". If not set use reco energy values. Default : None region : `~regions.SkyRegion` Region to define the dataset for. reference_time : `~astropy.time.Time` reference time of the dataset, Default is "2000-01-01" meta_table : `~astropy.table.Table` Table listing informations on observations used to create the dataset. One line per observation for stacked datasets. """ if e_true is None: e_true = e_reco.copy(name="energy_true") if region is None: region = "icrs;circle(0, 0, 1)" counts = RegionNDMap.create(region=region, axes=[e_reco]) background = RegionNDMap.create(region=region, axes=[e_reco]) aeff = EffectiveAreaTable( e_true.edges[:-1], e_true.edges[1:], np.zeros(e_true.edges[:-1].shape) * u.m**2, ) edisp = EDispKernel.from_diagonal_response(e_true.edges, e_reco.edges) mask_safe = RegionNDMap.from_geom(counts.geom, dtype="bool") gti = GTI.create(u.Quantity([], "s"), u.Quantity([], "s"), reference_time) livetime = gti.time_sum return SpectrumDataset( counts=counts, aeff=aeff, edisp=edisp, mask_safe=mask_safe, background=background, livetime=livetime, gti=gti, name=name, )
def test_from_parametrization(): # Log center of this is 100 GeV energy = [80, 125] * u.GeV area_ref = 1.65469579e07 * u.cm ** 2 area = EffectiveAreaTable.from_parametrization(energy, "HESS") assert_allclose(area.data.data, area_ref) assert area.data.data.unit == area_ref.unit # Log center of this is 0.1, 2 TeV energy = [0.08, 0.125, 32] * u.TeV area_ref = [1.65469579e07, 1.46451957e09] * u.cm * u.cm area = EffectiveAreaTable.from_parametrization(energy, "HESS") assert_allclose(area.data.data, area_ref) assert area.data.data.unit == area_ref.unit
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 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 = EDispKernel.from_diagonal_response(etrue, ereco) 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.on_region = make_region("icrs;circle(0.,1.,0.1)") off_region = make_region("icrs;box(0.,1.,0.1, 0.2,30)") self.off_region = off_region.union( make_region("icrs;box(-1.,-1.,0.1, 0.2,150)") ) self.wcs = WcsGeom.create(npix=300, binsz=0.01, frame="icrs").wcs data = np.ones(elo.shape) data[-1] = 0 # to test stats calculation with empty bins axis = MapAxis.from_edges(ereco, name="energy", interp="log") self.on_counts = RegionNDMap.create( region=self.on_region, wcs=self.wcs, axes=[axis] ) self.on_counts.data += 1 self.on_counts.data[-1] = 0 self.off_counts = RegionNDMap.create( region=self.off_region, wcs=self.wcs, axes=[axis] ) self.off_counts.data += 10 acceptance = RegionNDMap.from_geom(self.on_counts.geom) acceptance.data += 1 data = np.ones(elo.shape) data[-1] = 0 acceptance_off = RegionNDMap.from_geom(self.off_counts.geom) acceptance_off.data += 10 self.dataset = SpectrumDatasetOnOff( counts=self.on_counts, counts_off=self.off_counts, aeff=self.aeff, edisp=self.edisp, livetime=self.livetime, acceptance=acceptance, acceptance_off=acceptance_off, name="test", gti=self.gti, )
def spectrum_dataset(): e_true = np.logspace(0, 1, 21) * u.TeV e_reco = MapAxis.from_energy_bounds("1 TeV", "10 TeV", nbin=4) aeff = EffectiveAreaTable.from_constant(value=1e6 * u.m ** 2, energy=e_true) edisp = EDispKernel.from_diagonal_response(e_true, e_reco.edges) background = RegionNDMap.create(region="icrs;circle(0, 0, 0.1)", axes=[e_reco]) background.data += 3600 background.data[-1] *= 1e-3 return SpectrumDataset(aeff=aeff, livetime="1h", edisp=edisp, background=background)
def test_spectrum_dataset_stack_nondiagonal_no_bkg(spectrum_dataset): energy = spectrum_dataset.counts.geom.axes["energy"] geom = spectrum_dataset.counts.geom.to_image() edisp1 = EDispKernelMap.from_gauss( energy_axis=energy, energy_axis_true=energy.copy(name="energy_true"), sigma=0.1, bias=0, geom=geom) edisp1.exposure_map.data += 1 aeff = EffectiveAreaTable.from_parametrization( energy.edges, "HESS").to_region_map(geom.region) geom = spectrum_dataset.counts.geom counts = RegionNDMap.from_geom(geom=geom) gti = GTI.create(start=0 * u.s, stop=100 * u.s) spectrum_dataset1 = SpectrumDataset( counts=counts, exposure=aeff * gti.time_sum, edisp=edisp1, meta_table=Table({"OBS_ID": [0]}), gti=gti.copy(), ) edisp2 = EDispKernelMap.from_gauss( energy_axis=energy, energy_axis_true=energy.copy(name="energy_true"), sigma=0.2, bias=0.0, geom=geom) edisp2.exposure_map.data += 1 gti2 = GTI.create(start=100 * u.s, stop=200 * u.s) spectrum_dataset2 = SpectrumDataset( counts=counts, exposure=aeff * gti2.time_sum, edisp=edisp2, meta_table=Table({"OBS_ID": [1]}), gti=gti2, ) spectrum_dataset1.stack(spectrum_dataset2) assert_allclose(spectrum_dataset1.meta_table["OBS_ID"][0], [0, 1]) assert spectrum_dataset1.background_model is None assert_allclose(spectrum_dataset1.gti.time_sum.to_value("s"), 200) assert_allclose(spectrum_dataset1.exposure.quantity[2].to_value("m2 s"), 1573851.079861) kernel = edisp1.get_edisp_kernel() assert_allclose(kernel.get_bias(1 * u.TeV), 0.0, atol=1.2e-3) assert_allclose(kernel.get_resolution(1 * u.TeV), 0.1581, atol=1e-2)
def test_EffectiveAreaTable(tmpdir, aeff): arf = aeff.to_effective_area_table(offset=0.3 * u.deg) assert_quantity_allclose(arf.data.evaluate(), arf.data.data) with mpl_plot_check(): arf.plot() filename = str(tmpdir / "effarea_test.fits") arf.write(filename) arf2 = EffectiveAreaTable.read(filename) assert_quantity_allclose(arf.data.evaluate(), arf2.data.evaluate()) test_aeff = 0.6 * arf.max_area node_above = np.where(arf.data.data > test_aeff)[0][0] energy = arf.data.axis("energy") ener_above = energy.center[node_above] ener_below = energy.center[node_above - 1] test_ener = arf.find_energy(test_aeff) assert ener_below < test_ener and test_ener < ener_above elo_threshold = arf.find_energy(0.1 * arf.max_area) assert elo_threshold.unit == "TeV" assert_allclose(elo_threshold.value, 0.554086, rtol=1e-3) ehi_threshold = arf.find_energy(0.9 * arf.max_area, emin=30 * u.TeV, emax=100 * u.TeV) assert ehi_threshold.unit == "TeV" assert_allclose(ehi_threshold.value, 53.347217, rtol=1e-3) # Test evaluation outside safe range data = [np.nan, np.nan, 0, 0, 1, 2, 3, np.nan, np.nan] energy = np.logspace(0, 10, 10) * u.TeV aeff = EffectiveAreaTable(data=data, energy_lo=energy[:-1], energy_hi=energy[1:]) vals = aeff.evaluate_fill_nan() assert vals[1] == 0 assert vals[-1] == 3
def test_EffectiveAreaTable(tmp_path, aeff): arf = aeff.to_effective_area_table(offset=0.3 * u.deg) assert_quantity_allclose(arf.data.evaluate(), arf.data.data) with mpl_plot_check(): arf.plot() arf.write(tmp_path / "tmp.fits") arf2 = EffectiveAreaTable.read(tmp_path / "tmp.fits") assert_quantity_allclose(arf.data.evaluate(), arf2.data.evaluate()) test_aeff = 0.6 * arf.max_area node_above = np.where(arf.data.data > test_aeff)[0][0] energy = arf.data.axes["energy_true"] ener_above = energy.center[node_above] ener_below = energy.center[node_above - 1] test_ener = arf.find_energy(test_aeff) assert ener_below < test_ener and test_ener < ener_above elo_threshold = arf.find_energy(0.1 * arf.max_area) assert elo_threshold.unit == "TeV" assert_allclose(elo_threshold.value, 0.554086, rtol=1e-3) ehi_threshold = arf.find_energy(0.9 * arf.max_area, emin=30 * u.TeV, emax=100 * u.TeV) assert ehi_threshold.unit == "TeV" assert_allclose(ehi_threshold.value, 53.347217, rtol=1e-3) # Test evaluation outside safe range data = [np.nan, np.nan, 0, 0, 1, 2, 3, np.nan, np.nan] energy_axis_true = MapAxis.from_energy_bounds("1 TeV", "10 TeV", nbin=9, name="energy_true") aeff = EffectiveAreaTable(data=data, energy_axis_true=energy_axis_true) vals = aeff.evaluate_fill_nan() assert vals[1] == 0 assert vals[-1] == 3
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 axis = MapAxis.from_edges(energy, name="energy", interp="log") geom = RegionGeom(region=None, axes=[axis]) on_vector = RegionNDMap.from_geom(geom=geom, data=data_on) off_vector1 = RegionNDMap.from_geom(geom=geom, data=dataoff_1) off_vector2 = RegionNDMap.from_geom(geom=geom, data=dataoff_2) mask_safe = RegionNDMap.from_geom(geom, dtype=bool) mask_safe.data += True aeff = EffectiveAreaTable.from_constant(energy, "1 cm2") edisp = EDispKernel.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=mask_safe, 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=mask_safe, 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) thresh_lo = aeff.find_energy(aeff=0.1 * aeff.max_area) e_max = aeff.energy.edges[-1] thresh_hi = aeff.find_energy( aeff=0.9 * aeff.max_area, energy_min=0.1 * e_max, energy_max=e_max ) assert_allclose(thresh_lo.to("TeV").value, 0.18557, rtol=1e-4) assert_allclose(thresh_hi.to("TeV").value, 43.818, rtol=1e-4)
def read(cls, filename, offset='0.5 deg'): """Read from a FITS file. Compute RMF at 0.5 deg offset on fly. Parameters ---------- filename : `str` File containing the IRFs """ filename = str(make_path(filename)) with fits.open(filename, memmap=False) as hdulist: aeff = EffectiveAreaTable.from_hdulist(hdulist=hdulist) edisp = EnergyDispersion2D.read(filename, hdu='ENERGY DISPERSION') bkg = BgRateTable.from_hdulist(hdulist=hdulist) psf = Psf68Table.from_hdulist(hdulist=hdulist) sens = SensitivityTable.from_hdulist(hdulist=hdulist) # Create rmf with appropriate dimensions (e_reco->bkg, e_true->area) e_reco_min = bkg.energy.lo[0] e_reco_max = bkg.energy.hi[-1] e_reco_bin = bkg.energy.nbins e_reco_axis = EnergyBounds.equal_log_spacing( e_reco_min, e_reco_max, e_reco_bin, 'TeV', ) e_true_min = aeff.energy.lo[0] e_true_max = aeff.energy.hi[-1] e_true_bin = aeff.energy.nbins e_true_axis = EnergyBounds.equal_log_spacing( e_true_min, e_true_max, e_true_bin, 'TeV', ) rmf = edisp.to_energy_dispersion( offset=offset, e_reco=e_reco_axis, e_true=e_true_axis, ) return cls( aeff=aeff, bkg=bkg, edisp=edisp, psf=psf, sens=sens, rmf=rmf )
def retrieve_arf_info(hdu_list, energies, plot=False): """ Retrieve effective area information from arf fits file. Parameters ---------- hdu_list : `~astropy.io.fits.HDUList` HDU list with ``SPECRESP``extension. plot : bool Make an effective area vs. energy plot. """ from gammapy.irf import EffectiveAreaTable arf = EffectiveAreaTable.from_fits(hdu_list) energies = Quantity(energies, 'TeV') print(arf.info(energies=energies)) if plot: arf.plot_area_vs_energy('effective_area.png')
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) bkg = 0.2 * npred.data alpha = 0.1 counts_kwargs = dict( energy=npred.energy, exposure=livetime,