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 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 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 test_from_diagonal_response(self): e_true = [0.5, 1, 2, 4, 6] * u.TeV e_reco = [2, 4, 6] * u.TeV edisp = EDispKernel.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 = EDispKernel.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_from_diagonal_response(self): energy_axis_true = MapAxis.from_energy_edges([0.5, 1, 2, 4, 6] * u.TeV, name="energy_true") energy_axis = MapAxis.from_energy_edges([2, 4, 6] * u.TeV) edisp = EDispKernel.from_diagonal_response(energy_axis_true, energy_axis) 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 = EDispKernel.from_diagonal_response(energy_axis_true) assert_allclose(edisp.axes["energy"].edges, edisp.axes["energy_true"].edges) assert edisp.axes["energy"].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 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 create(cls, e_reco, e_true=None, region=None, reference_time="2000-01-01", name=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 : `~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 region : `~regions.SkyRegion` Region to define the dataset for. reference_time : `~astropy.time.Time` reference time of the dataset, Default is "2000-01-01" """ if e_true is None: e_true = e_reco if region is None: region = "icrs;circle(0, 0, 1)" # TODO: change .create() API energy = MapAxis.from_edges(e_reco, interp="log", name="energy") counts = RegionNDMap.create(region=region, axes=[energy]) background = RegionNDMap.create(region=region, axes=[energy]) aeff = EffectiveAreaTable(e_true[:-1], e_true[1:], np.zeros(e_true[:-1].shape) * u.m**2) edisp = EDispKernel.from_diagonal_response(e_true, e_reco) 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_apply_edisp(region_map_true): e_true = region_map_true.geom.axes[0].edges e_reco = MapAxis.from_energy_bounds("1 TeV", "10 TeV", nbin=3).edges edisp = EDispKernel.from_diagonal_response(e_true=e_true, e_reco=e_reco) m = region_map_true.apply_edisp(edisp) assert m.geom.data_shape == (3, 1, 1) e_reco = m.geom.axes[0].edges assert e_reco.unit == "TeV" assert m.geom.axes[0].name == "energy" assert_allclose(e_reco[[0, -1]].value, [1, 10])
def create(cls, e_reco, e_true=None, region=None, reference_time="2000-01-01", name=None): """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 region : `~regions.SkyRegion` Region to define the dataset for. 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:], region=region) counts_off = CountsSpectrum(e_reco[:-1], e_reco[1:], region=region) aeff = EffectiveAreaTable(e_true[:-1], e_true[1:], np.zeros(e_true[:-1].shape) * u.m**2) edisp = EDispKernel.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, name=name, )
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(): e_true = np.logspace(0, 1, 21) * u.TeV e_reco = np.logspace(0, 1, 5) * u.TeV aeff = EffectiveAreaTable.from_constant(value=1e6 * u.m**2, energy=e_true) edisp = EDispKernel.from_diagonal_response(e_true, e_reco) data = 3600 * np.ones(4) data[-1] *= 1e-3 background = CountsSpectrum(energy_lo=e_reco[:-1], energy_hi=e_reco[1:], data=data) return SpectrumDataset(aeff=aeff, livetime="1h", edisp=edisp, background=background)
def test_set_model(self): aeff = EffectiveAreaTable.from_parametrization(self.src.energy.edges, "HESS") edisp = EDispKernel.from_diagonal_response(self.src.energy.edges, self.src.energy.edges) dataset = SpectrumDataset(None, self.src, self.livetime, None, aeff, edisp, self.bkg) spectral_model = PowerLawSpectralModel() model = SkyModel(spectral_model=spectral_model, name="test") dataset.models = model assert dataset.models["test"] is model models = Models([model]) dataset.models = models assert dataset.models["test"] is model
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 get_map_dataset(geom, geom_etrue, edisp="edispmap", name="test", **kwargs): """Returns a MapDatasets""" # define background model background = Map.from_geom(geom) background.data += 0.2 psf = get_psf() exposure = get_exposure(geom_etrue) e_reco = geom.axes["energy"] e_true = geom_etrue.axes["energy_true"] if edisp == "edispmap": edisp = EDispMap.from_diagonal_response(energy_axis_true=e_true) elif edisp == "edispkernelmap": edisp = EDispKernelMap.from_diagonal_response( energy_axis=e_reco, energy_axis_true=e_true ) elif edisp == "edispkernel": edisp = EDispKernel.from_diagonal_response( energy_true=e_true.edges, energy=e_reco.edges ) else: edisp = None # define fit mask center = SkyCoord("0.2 deg", "0.1 deg", frame="galactic") circle = CircleSkyRegion(center=center, radius=1 * u.deg) mask_fit = geom.region_mask([circle]) mask_fit = Map.from_geom(geom, data=mask_fit) models = FoVBackgroundModel(dataset_name=name) return MapDataset( models=models, exposure=exposure, background=background, psf=psf, edisp=edisp, mask_fit=mask_fit, name=name, **kwargs, )
def get_map_dataset(sky_model, geom, geom_etrue, edisp="edispmap", name="test", **kwargs): """Returns a MapDatasets""" # define background model m = Map.from_geom(geom) m.quantity = 0.2 * np.ones(m.data.shape) background_model = BackgroundModel(m, datasets_names=[name]) psf = get_psf() exposure = get_exposure(geom_etrue) e_reco = geom.get_axis_by_name("energy") e_true = geom_etrue.get_axis_by_name("energy_true") if edisp == "edispmap": edisp = EDispMap.from_diagonal_response(energy_axis_true=e_true) elif edisp == "edispkernelmap": edisp = EDispKernelMap.from_diagonal_response(energy_axis=e_reco, energy_axis_true=e_true) elif edisp == "edispkernel": edisp = EDispKernel.from_diagonal_response(e_true=e_true.edges, e_reco=e_reco.edges) 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]) mask_fit = Map.from_geom(geom, data=mask_fit) return MapDataset(models=[sky_model, background_model], exposure=exposure, psf=psf, edisp=edisp, mask_fit=mask_fit, name=name, **kwargs)
def edisp(geom, geom_true): e_reco = geom.get_axis_by_name("energy").edges e_true = geom_true.get_axis_by_name("energy_true").edges return EDispKernel.from_diagonal_response(e_true=e_true, e_reco=e_reco)
def edisp(geom, geom_true): e_reco = geom.axes["energy"].edges e_true = geom_true.axes["energy_true"].edges return EDispKernel.from_diagonal_response(e_true=e_true, e_reco=e_reco)
def run_region(self, kr, lon, lat, radius): # TODO: for now we have to read/create the allsky maps each in each job # because we can't pickle <functools._lru_cache_wrapper object # send this back to init when fixed # exposure exposure_hpx = Map.read( "$GAMMAPY_DATA/fermi_3fhl/fermi_3fhl_exposure_cube_hpx.fits.gz" ) exposure_hpx.unit = "cm2 s" # iem iem_filepath = BASE_PATH / "data" / "gll_iem_v06_extrapolated.fits" iem_fermi_extra = Map.read(iem_filepath) # norm=1.1, tilt=0.03 see paper appendix A model_iem = SkyDiffuseCube( iem_fermi_extra, norm=1.1, tilt=0.03, name="iem_extrapolated" ) # ROI roi_time = time() ROI_pos = SkyCoord(lon, lat, frame="galactic", unit="deg") width = 2 * (radius + self.psf_margin) # Counts counts = Map.create( skydir=ROI_pos, width=width, proj="CAR", frame="galactic", binsz=1 / 8.0, axes=[self.energy_axis], dtype=float, ) counts.fill_by_coord( {"skycoord": self.events.radec, "energy": self.events.energy} ) axis = MapAxis.from_nodes( counts.geom.axes[0].center, name="energy_true", unit="GeV", interp="log" ) wcs = counts.geom.wcs geom = WcsGeom(wcs=wcs, npix=counts.geom.npix, axes=[axis]) coords = geom.get_coord() # expo data = exposure_hpx.interp_by_coord(coords) exposure = WcsNDMap(geom, data, unit=exposure_hpx.unit, dtype=float) # read PSF psf_kernel = PSFKernel.from_table_psf( self.psf, geom, max_radius=self.psf_margin * u.deg ) # Energy Dispersion e_true = exposure.geom.axes[0].edges e_reco = counts.geom.axes[0].edges edisp = EDispKernel.from_diagonal_response(e_true=e_true, e_reco=e_reco) # fit mask if coords["lon"].min() < 90 * u.deg and coords["lon"].max() > 270 * u.deg: coords["lon"][coords["lon"].value > 180] -= 360 * u.deg mask = ( (coords["lon"] >= coords["lon"].min() + self.psf_margin * u.deg) & (coords["lon"] <= coords["lon"].max() - self.psf_margin * u.deg) & (coords["lat"] >= coords["lat"].min() + self.psf_margin * u.deg) & (coords["lat"] <= coords["lat"].max() - self.psf_margin * u.deg) ) mask_fermi = WcsNDMap(counts.geom, mask) # IEM eval_iem = MapEvaluator( model=model_iem, exposure=exposure, psf=psf_kernel, edisp=edisp ) bkg_iem = eval_iem.compute_npred() # ISO eval_iso = MapEvaluator(model=self.model_iso, exposure=exposure, edisp=edisp) bkg_iso = eval_iso.compute_npred() # merge iem and iso, only one local normalization is fitted dataset_name = "3FHL_ROI_num" + str(kr) background_total = bkg_iem + bkg_iso background_model = BackgroundModel( background_total, name="bkg_iem+iso", datasets_names=[dataset_name] ) background_model.parameters["norm"].min = 0.0 # Sources model in_roi = self.FHL3.positions.galactic.contained_by(wcs) FHL3_roi = [] for ks in range(len(self.FHL3.table)): if in_roi[ks] == True: model = self.FHL3[ks].sky_model() model.spatial_model.parameters.freeze_all() # freeze spatial model.spectral_model.parameters["amplitude"].min = 0.0 if isinstance(model.spectral_model, PowerLawSpectralModel): model.spectral_model.parameters["index"].min = 0.1 model.spectral_model.parameters["index"].max = 10.0 else: model.spectral_model.parameters["alpha"].min = 0.1 model.spectral_model.parameters["alpha"].max = 10.0 FHL3_roi.append(model) model_total = Models([background_model] + FHL3_roi) # Dataset dataset = MapDataset( models=model_total, counts=counts, exposure=exposure, psf=psf_kernel, edisp=edisp, mask_fit=mask_fermi, name=dataset_name, ) cat_stat = dataset.stat_sum() datasets = Datasets([dataset]) fit = Fit(datasets) results = fit.run(**self.optimize_opts) print("ROI_num", str(kr), "\n", results) fit_stat = datasets.stat_sum() if results.message != "Optimization failed.": datasets.write(path=Path(self.resdir), prefix=dataset.name, overwrite=True) np.savez( self.resdir / f"3FHL_ROI_num{kr}_fit_infos.npz", message=results.message, stat=[cat_stat, fit_stat], ) exec_time = time() - roi_time print("ROI", kr, " time (s): ", exec_time) for model in FHL3_roi: if ( self.FHL3[model.name].data["ROI_num"] == kr and self.FHL3[model.name].data["Signif_Avg"] >= self.sig_cut ): flux_points = FluxPointsEstimator( e_edges=self.El_flux, source=model.name, n_sigma_ul=2, ).run(datasets=datasets) filename = self.resdir / f"{model.name}_flux_points.fits" flux_points.write(filename, overwrite=True) exec_time = time() - roi_time - exec_time print("ROI", kr, " Flux points time (s): ", exec_time)
def edisp(geom, geom_true): e_reco = geom.axes["energy"] e_true = geom_true.axes["energy_true"] return EDispKernel.from_diagonal_response(energy_axis_true=e_true, energy_axis=e_reco)