def test_flux_point_dataset_serialization(tmp_path): path = "$GAMMAPY_DATA/tests/spectrum/flux_points/diff_flux_points.fits" table = Table.read(make_path(path)) table["e_ref"] = table["e_ref"].quantity.to("TeV") data = FluxPoints.from_table(table, format="gadf-sed") spectral_model = PowerLawSpectralModel(index=2.3, amplitude="2e-13 cm-2 s-1 TeV-1", reference="1 TeV") model = SkyModel(spectral_model=spectral_model, name="test_model") dataset = FluxPointsDataset(model, data, name="test_dataset") dataset2 = FluxPointsDataset.read(path, name="test_dataset2") assert_allclose(dataset.data.dnde.data, dataset2.data.dnde.data) assert dataset.mask_safe.data == dataset2.mask_safe.data assert dataset2.name == "test_dataset2" Datasets([dataset]).write( filename=tmp_path / "tmp_datasets.yaml", filename_models=tmp_path / "tmp_models.yaml", ) datasets = Datasets.read( filename=tmp_path / "tmp_datasets.yaml", filename_models=tmp_path / "tmp_models.yaml", ) new_dataset = datasets[0] assert_allclose(new_dataset.data.dnde, dataset.data.dnde, 1e-4) if dataset.mask_fit is None: assert np.all(new_dataset.mask_fit == dataset.mask_safe) assert np.all(new_dataset.mask_safe == dataset.mask_safe) assert new_dataset.name == "test_dataset"
def flux_points(self): """Flux points (`~gammapy.spectrum.FluxPoints`).""" table = Table() table.meta["SED_TYPE"] = "flux" table["e_min"] = self._ebounds[:-1] table["e_max"] = self._ebounds[1:] flux = self._get_flux_values("Flux_Band") flux_err = self._get_flux_values("Unc_Flux_Band") table["flux"] = flux table["flux_errn"] = np.abs(flux_err[:, 0]) table["flux_errp"] = flux_err[:, 1] nuFnu = self._get_flux_values("nuFnu_Band", "erg cm-2 s-1") table["e2dnde"] = nuFnu table["e2dnde_errn"] = np.abs(nuFnu * flux_err[:, 0] / flux) table["e2dnde_errp"] = nuFnu * flux_err[:, 1] / flux is_ul = np.isnan(table["flux_errn"]) table["is_ul"] = is_ul # handle upper limits table["flux_ul"] = np.nan * flux_err.unit flux_ul = compute_flux_points_ul(table["flux"], table["flux_errp"]) table["flux_ul"][is_ul] = flux_ul[is_ul] # handle upper limits table["e2dnde_ul"] = np.nan * nuFnu.unit e2dnde_ul = compute_flux_points_ul(table["e2dnde"], table["e2dnde_errp"]) table["e2dnde_ul"][is_ul] = e2dnde_ul[is_ul] # Square root of test statistic table["sqrt_TS"] = self.data["Sqrt_TS_Band"] return FluxPoints(table)
def get_flux_points(self, position=None): """Extract flux point at a given position. Parameters --------- position : `~astropy.coordinates.SkyCoord` Position where the flux points are extracted. Returns ------- flux_points : `~gammapy.estimators.FluxPoints` Flux points object """ from gammapy.estimators import FluxPoints if position is None: position = self.geom.center_skydir data = {} for name in self._data: m = getattr(self, name) data[name] = m.to_region_nd_map(region=position, method="nearest") return FluxPoints(data, reference_model=self.reference_model, meta=self.meta.copy(), gti=self.gti)
def flux_points_e2dnde(model): e_ref = [np.sqrt(10), np.sqrt(10 * 100)] * u.TeV table = Table() table.meta["SED_TYPE"] = "e2dnde" table["e_ref"] = e_ref table["e2dnde"] = (model(e_ref) * e_ref ** 2).to("erg cm-2 s-1") return FluxPoints(table)
def flux_points_dnde(model): e_ref = [np.sqrt(10), np.sqrt(10 * 100)] * u.TeV table = Table() table.meta["SED_TYPE"] = "dnde" table["e_ref"] = e_ref table["dnde"] = model(e_ref) return FluxPoints(table)
def test_flux_point_dataset_serialization(tmp_path): path = "$GAMMAPY_DATA/tests/spectrum/flux_points/diff_flux_points.fits" data = FluxPoints.read(path) data.table["e_ref"] = data.energy_ref.to("TeV") spectral_model = PowerLawSpectralModel(index=2.3, amplitude="2e-13 cm-2 s-1 TeV-1", reference="1 TeV") model = SkyModel(spectral_model=spectral_model, name="test_model") dataset = FluxPointsDataset(model, data, name="test_dataset") Datasets([dataset]).write( filename=tmp_path / "tmp_datasets.yaml", filename_models=tmp_path / "tmp_models.yaml", ) datasets = Datasets.read( filename=tmp_path / "tmp_datasets.yaml", filename_models=tmp_path / "tmp_models.yaml", ) new_dataset = datasets[0] assert_allclose(new_dataset.data.dnde, dataset.data.dnde, 1e-4) if dataset.mask_fit is None: assert np.all(new_dataset.mask_fit == dataset.mask_safe) assert np.all(new_dataset.mask_safe == dataset.mask_safe) assert new_dataset.name == "test_dataset"
def from_dict(cls, data, models, **kwargs): """Create flux point dataset from dict. Parameters ---------- data : dict Dict containing data to create dataset from. models : list of `SkyModel` List of model components. Returns ------- dataset : `FluxPointsDataset` Flux point datasets. """ from gammapy.estimators import FluxPoints filename = make_path(data["filename"]) table = Table.read(filename) mask_fit = table["mask_fit"].data.astype("bool") mask_safe = table["mask_safe"].data.astype("bool") table.remove_columns(["mask_fit", "mask_safe"]) return cls( models=models, name=data["name"], data=FluxPoints(table), mask_fit=mask_fit, mask_safe=mask_safe, )
def from_dict(cls, data, **kwargs): """Create flux point dataset from dict. Parameters ---------- data : dict Dict containing data to create dataset from. Returns ------- dataset : `FluxPointsDataset` Flux point datasets. """ from gammapy.estimators import FluxPoints filename = make_path(data["filename"]) table = Table.read(filename) mask_fit = table["mask_fit"].data.astype("bool") mask_safe = table["mask_safe"].data.astype("bool") table.remove_columns(["mask_fit", "mask_safe"]) return cls( name=data["name"], data=FluxPoints.from_table(table, format="gadf-sed"), mask_fit=mask_fit, mask_safe=mask_safe, )
def test_plot_fp_no_ul(): path = make_path("$GAMMAPY_DATA/tests/spectrum/flux_points/diff_flux_points.fits") table = Table.read(path) table.remove_column('dnde_ul') fp = FluxPoints.from_table(table, sed_type='dnde') with mpl_plot_check(): fp.plot()
def flux_points(self): """Flux points (`~gammapy.estimators.FluxPoints`).""" return FluxPoints.from_table( table=self.flux_points_table, reference_model=self.sky_model(), format="gadf-sed", )
def flux_points(self): """Flux points (`~gammapy.estimators.FluxPoints`).""" reference_model = SkyModel(spectral_model=self.spectral_model(), name=self.name) return FluxPoints.from_table( self.flux_points_table, reference_model=reference_model, )
def dataset(): path = "$GAMMAPY_DATA/tests/spectrum/flux_points/diff_flux_points.fits" data = FluxPoints.read(path) data.table["e_ref"] = data.e_ref.to("TeV") model = SkyModel(spectral_model=PowerLawSpectralModel( index=2.3, amplitude="2e-13 cm-2 s-1 TeV-1", reference="1 TeV")) dataset = FluxPointsDataset(model, data) return dataset
def flux_points_flux(model): e_min = [1, 10] * u.TeV e_max = [10, 100] * u.TeV table = Table() table.meta["SED_TYPE"] = "flux" table["e_min"] = e_min table["e_max"] = e_max table["flux"] = model.integral(e_min, e_max) return FluxPoints(table)
def test_lightcurve_read_write(tmp_path, lc, format): table = lc.to_table(format="lightcurve", sed_type="flux") table.write(tmp_path / "tmp", format=format) lc = FluxPoints.read(tmp_path / "tmp", format="lightcurve") # Check if time-related info round-trips axis = lc.geom.axes["time"] assert axis.reference_time.scale == "utc" assert axis.reference_time.format == "mjd" assert_allclose(axis.time_mid.mjd, [55198, 55202.5])
def test_flux_points_plot_no_error_bar(): table = Table() pwl = PowerLawSpectralModel() e_ref = np.geomspace(1, 100, 7) * u.TeV table["e_ref"] = e_ref table["dnde"] = pwl(e_ref) table.meta["SED_TYPE"] = "dnde" flux_points = FluxPoints.from_table(table) with mpl_plot_check(): _ = flux_points.plot(sed_type="dnde")
def test_lightcurve_estimator_spectrum_datasets(): # Doing a LC on one hour bin datasets = get_spectrum_datasets() time_intervals = [ Time(["2010-01-01T00:00:00", "2010-01-01T01:00:00"]), Time(["2010-01-01T01:00:00", "2010-01-01T02:00:00"]), ] estimator = LightCurveEstimator( energy_edges=[1, 30] * u.TeV, norm_n_values=3, time_intervals=time_intervals, selection_optional="all", ) lightcurve = estimator.run(datasets) table = lightcurve.to_table(format="lightcurve") assert_allclose(table["time_min"], [55197.0, 55197.041667]) assert_allclose(table["time_max"], [55197.041667, 55197.083333]) assert_allclose(table["e_ref"], [[5.623413], [5.623413]]) assert_allclose(table["e_min"], [[1], [1]]) assert_allclose(table["e_max"], [[31.622777], [31.622777]]) assert_allclose( table["ref_dnde"], [[3.162278e-14], [3.162278e-14]], rtol=1e-5 ) assert_allclose( table["ref_flux"], [[9.683772e-13], [9.683772e-13]], rtol=1e-5 ) assert_allclose( table["ref_eflux"], [[3.453878e-12], [3.453878e-12]], rtol=1e-5 ) assert_allclose(table["stat"], [[16.824042], [17.391981]], rtol=1e-5) assert_allclose(table["norm"], [[0.911963], [0.9069318]], rtol=1e-2) assert_allclose(table["norm_err"], [[0.057769], [0.057835]], rtol=1e-2) assert_allclose(table["counts"], [[[791, np.nan]], [[np.nan, 784]]]) assert_allclose(table["norm_errp"], [[0.058398], [0.058416]], rtol=1e-2) assert_allclose(table["norm_errn"], [[0.057144], [0.057259]], rtol=1e-2) assert_allclose(table["norm_ul"], [[1.029989], [1.025061]], rtol=1e-2) assert_allclose(table["sqrt_ts"], [[19.384781], [19.161769]], rtol=1e-2) assert_allclose(table["ts"], [[375.769735], [367.173374]], rtol=1e-2) assert_allclose(table[0]["norm_scan"], [[0.2, 1.0, 5.0]]) assert_allclose( table[0]["stat_scan"], [[224.058304, 19.074405, 2063.75636]], rtol=1e-5, ) # TODO: fix reference model I/O fp = FluxPoints.from_table( table=table, format="lightcurve", reference_model=PowerLawSpectralModel() ) assert fp.norm.geom.axes.names == ["energy", "time"] assert fp.counts.geom.axes.names == ["dataset", "energy", "time"] assert fp.stat_scan.geom.axes.names == ["norm", "energy", "time"]
def test_dnde_from_flux(): """Tests y-value normalization adjustment method. """ table = Table() table["e_min"] = np.array([10, 20, 30, 40]) table["e_max"] = np.array([20, 30, 40, 50]) table["flux"] = np.array([42, 52, 62, 72]) # 'True' integral flux in this test bin # Get values model = XSqrTestModel() table["e_ref"] = FluxPoints._energy_ref_lafferty(model, table["e_min"], table["e_max"]) dnde = FluxPoints.from_table(table, reference_model=model) # Set up test case comparison dnde_model = model(table["e_ref"]) # Test comparison result desired = model.integral(table["e_min"], table["e_max"]) # Test output result actual = table["flux"] * (dnde_model / dnde) # Compare assert_allclose(actual, desired, rtol=1e-6)
def test_dnde_from_flux(): """Tests y-value normalization adjustment method. """ e_min = np.array([10, 20, 30, 40]) e_max = np.array([20, 30, 40, 50]) flux = np.array([42, 52, 62, 72]) # 'True' integral flux in this test bin # Get values model = XSqrTestModel() e_ref = FluxPoints._e_ref_lafferty(model, e_min, e_max) dnde = FluxPoints._dnde_from_flux( flux, model, e_ref, e_min, e_max, pwl_approx=False ) # Set up test case comparison dnde_model = model(e_ref) # Test comparison result desired = model.integral(e_min, e_max) # Test output result actual = flux * (dnde_model / dnde) # Compare assert_allclose(actual, desired, rtol=1e-6)
def dataset(): path = "$GAMMAPY_DATA/tests/spectrum/flux_points/diff_flux_points.fits" data = FluxPoints.read(path) data.table["e_ref"] = data.e_ref.to("TeV") model = SkyModel(spectral_model=PowerLawSpectralModel( index=2.3, amplitude="2e-13 cm-2 s-1 TeV-1", reference="1 TeV")) obs_table = Table() obs_table["TELESCOP"] = ["CTA"] obs_table["OBS_ID"] = ["0001"] obs_table["INSTRUME"] = ["South_Z20_50h"] dataset = FluxPointsDataset(model, data, meta_table=obs_table) return dataset
def test_compute_flux_points_dnde_exp(method): """ Tests against analytical result or result from a powerlaw. """ model = ExpTestModel() energy_min = [1.0, 10.0] * u.TeV energy_max = [10.0, 100.0] * u.TeV table = Table() table.meta["SED_TYPE"] = "flux" table["e_min"] = energy_min table["e_max"] = energy_max flux = model.integral(energy_min, energy_max) table["flux"] = flux if method == "log_center": energy_ref = np.sqrt(energy_min * energy_max) elif method == "table": energy_ref = [2.0, 20.0] * u.TeV elif method == "lafferty": energy_ref = FluxPoints._energy_ref_lafferty(model, energy_min, energy_max) table["e_ref"] = energy_ref result = FluxPoints.from_table(table, reference_model=model) # Test energy actual = result.energy_ref assert_quantity_allclose(actual, energy_ref, rtol=1e-8) # Test flux actual = result.dnde desired = model(energy_ref) assert_quantity_allclose(actual, desired, rtol=1e-8)
def test_e_ref_lafferty(): """ Tests Lafferty & Wyatt x-point method. Using input function g(x) = 10^4 exp(-6x) against check values from paper Lafferty & Wyatt. Nucl. Instr. and Meth. in Phys. Res. A 355 (1995) 541-547, p. 542 Table 1 """ # These are the results from the paper desired = np.array([0.048, 0.190, 0.428, 0.762]) model = LWTestModel() e_min = np.array([0.0, 0.1, 0.3, 0.6]) e_max = np.array([0.1, 0.3, 0.6, 1.0]) actual = FluxPoints._e_ref_lafferty(model, e_min, e_max) assert_allclose(actual, desired, atol=1e-3)
def test_flux_points_estimator_no_norm_scan(fpe_pwl, tmpdir): datasets, fpe = fpe_pwl fpe.selection_optional = None fp = fpe.run(datasets) assert_allclose(fpe.fit.optimize_opts["tol"], 0.2) assert_allclose(fpe.fit.minuit.tol, 0.2) assert fp.sed_type_init == "likelihood" assert "stat_scan" not in fp._data # test GADF I/O fp.write(tmpdir / "test.fits", format="gadf-sed") fp_new = FluxPoints.read(tmpdir / "test.fits") assert fp_new.meta["sed_type_init"] == "likelihood"
def test_run_ecpl(fpe_ecpl, tmpdir): datasets, fpe = fpe_ecpl fp = fpe.run(datasets) table = fp.to_table() actual = table["ref_flux"].quantity desired = [9.024362e-13, 1.781341e-13, 1.260298e-18 ] * u.Unit("1 / (cm2 s)") assert_allclose(actual, desired, rtol=1e-3) actual = table["ref_dnde"].quantity desired = [1.351382e-12, 7.527318e-15, 2.523659e-22 ] * u.Unit("1 / (cm2 s TeV)") assert_allclose(actual, desired, rtol=1e-3) actual = table["ref_eflux"].quantity desired = [4.770557e-13, 2.787695e-13, 1.371963e-17 ] * u.Unit("TeV / (cm2 s)") assert_allclose(actual, desired, rtol=1e-3) actual = table["norm"].data assert_allclose(actual, [1.001683, 1.061821, 1.237512e03], rtol=1e-3) actual = table["norm_err"].data assert_allclose(actual, [1.386091e-01, 2.394241e-01, 3.259756e03], rtol=1e-2) actual = table["norm_errn"].data assert_allclose(actual, [1.374962e-01, 2.361246e-01, 2.888978e03], rtol=1e-2) actual = table["norm_errp"].data assert_allclose(actual, [1.397358e-01, 2.428481e-01, 3.716550e03], rtol=1e-2) actual = table["norm_ul"].data assert_allclose(actual, [1.283433e00, 1.555117e00, 9.698645e03], rtol=1e-2) actual = table["sqrt_ts"].data assert_allclose(actual, [7.678454, 4.735691, 0.399243], rtol=1e-2) # test GADF I/O fp.write(tmpdir / "test.fits", format="gadf-sed") fp_new = FluxPoints.read(tmpdir / "test.fits") assert fp_new.meta["sed_type_init"] == "likelihood"
def lightcurve(self, interval="1-year"): """Lightcurve (`~gammapy.estimators.FluxPoints`). Parameters ---------- interval : {'1-year', '2-month'} Time interval of the lightcurve. Default is '1-year'. Note that '2-month' is not available for all catalogue version. """ if interval == "1-year": tag = "Flux_History" time_axis = self.data["time_axis"] tag_sqrt_ts = "Sqrt_TS_History" elif interval == "2-month": tag = "Flux2_History" if tag not in self.data: raise ValueError( "Only '1-year' interval is available for this catalogue version" ) time_axis = self.data["time_axis_2"] tag_sqrt_ts = "Sqrt_TS2_History" else: raise ValueError("Time intervals available are '1-year' or '2-month'") energy_axis = MapAxis.from_energy_edges([50, 300000] * u.MeV) geom = RegionGeom.create(region=self.position, axes=[energy_axis, time_axis]) names = ["flux", "flux_errp", "flux_errn", "flux_ul", "ts"] maps = Maps.from_geom(geom=geom, names=names) maps["flux"].quantity = self.data[tag] maps["flux_errp"].quantity = self.data[f"Unc_{tag}"][:, 1] maps["flux_errn"].quantity = -self.data[f"Unc_{tag}"][:, 0] maps["flux_ul"].quantity = compute_flux_points_ul( maps["flux"].quantity, maps["flux_errp"].quantity ) maps["ts"].quantity = self.data[tag_sqrt_ts] ** 2 return FluxPoints.from_maps( maps=maps, sed_type="flux", reference_model=self.sky_model(), meta=self.flux_points.meta.copy(), )
def read_ref_lightcurve(): filename = "reference/Flux_LC_ChandraNight_700GeV.fits" table = Table.read(filename) table["e_min"] = [[700]] * u.GeV table["e_max"] = [[1e5]] * u.TeV table["time_min"].unit = u.day table["time_max"].unit = u.day # fix overlapping time intervals m = np.where((table["time_min"][1:] - table["time_max"][:-1]) >= 0 * u.s) return FluxPoints.from_table( table=table[m], format="lightcurve", sed_type="flux", )
def flux_points(self): """Flux points (`~gammapy.spectrum.FluxPoints`).""" table = Table() table.meta["SED_TYPE"] = "dnde" mask = ~np.isnan(self.data["Flux_Points_Energy"]) table["e_ref"] = self.data["Flux_Points_Energy"][mask] table["e_min"] = self.data["Flux_Points_Energy_Min"][mask] table["e_max"] = self.data["Flux_Points_Energy_Max"][mask] table["dnde"] = self.data["Flux_Points_Flux"][mask] table["dnde_errn"] = self.data["Flux_Points_Flux_Err_Lo"][mask] table["dnde_errp"] = self.data["Flux_Points_Flux_Err_Hi"][mask] table["dnde_ul"] = self.data["Flux_Points_Flux_UL"][mask] table["is_ul"] = self.data["Flux_Points_Flux_Is_UL"][mask].astype("bool") return FluxPoints(table)
def lc_2d(): meta = dict(TIMESYS="utc", SED_TYPE="flux") table = Table( meta=meta, data=[ Column(Time(["2010-01-01", "2010-01-03"]).mjd, "time_min"), Column(Time(["2010-01-03", "2010-01-10"]).mjd, "time_max"), Column([[1.0, 2.0], [1.0, 2.0]], "e_min", unit="TeV"), Column([[2.0, 4.0], [2.0, 4.0]], "e_max", unit="TeV"), Column([[1e-11, 1e-12], [3e-11, 3e-12]], "flux", unit="cm-2 s-1"), Column([[0.1e-11, 1e-13], [0.3e-11, 3e-13]], "flux_err", unit="cm-2 s-1"), Column([[np.nan, np.nan], [3.6e-11, 3.6e-12]], "flux_ul", unit="cm-2 s-1"), Column([[False, False], [True, True]], "is_ul"), ], ) return FluxPoints.from_table(table=table, format="lightcurve")
def flux_points(self): """Integral flux points (`~gammapy.spectrum.FluxPoints`).""" table = Table() table.meta["SED_TYPE"] = "flux" table["e_min"] = self._ebounds[:-1] table["e_max"] = self._ebounds[1:] table["flux"] = self._get_flux_values("Flux") flux_err = self._get_flux_values("Unc_Flux") table["flux_errn"] = np.abs(flux_err[:, 0]) table["flux_errp"] = flux_err[:, 1] # handle upper limits is_ul = np.isnan(table["flux_errn"]) table["is_ul"] = is_ul table["flux_ul"] = np.nan * flux_err.unit flux_ul = compute_flux_points_ul(table["flux"], table["flux_errp"]) table["flux_ul"][is_ul] = flux_ul[is_ul] return FluxPoints(table)
def test_run_map_pwl(fpe_map_pwl, tmpdir): datasets, fpe = fpe_map_pwl fp = fpe.run(datasets) table = fp.to_table() actual = table["e_min"].data assert_allclose(actual, [0.1, 1.178769, 8.48342], rtol=1e-5) actual = table["e_max"].data assert_allclose(actual, [1.178769, 8.483429, 100.0], rtol=1e-5) actual = table["e_ref"].data assert_allclose(actual, [0.343332, 3.162278, 29.126327], rtol=1e-5) actual = table["norm"].data assert_allclose(actual, [0.974726, 0.96342, 0.994251], rtol=1e-2) actual = table["norm_err"].data assert_allclose(actual, [0.067637, 0.052022, 0.087059], rtol=3e-2) actual = table["counts"].data assert_allclose(actual, [[44611, 0], [1923, 0], [282, 0]]) actual = table["norm_ul"].data assert_allclose(actual, [1.111852, 1.07004, 1.17829], rtol=1e-2) actual = table["sqrt_ts"].data assert_allclose(actual, [16.681221, 28.408676, 21.91912], rtol=1e-2) actual = table["norm_scan"][0] assert_allclose(actual, [0.2, 1.0, 5]) actual = table["stat_scan"][0] - table["stat"][0] assert_allclose(actual, [1.628398e02, 1.452456e-01, 2.008018e03], rtol=1e-2) # test GADF I/O fp.write(tmpdir / "test.fits", format="gadf-sed") fp_new = FluxPoints.read(tmpdir / "test.fits") assert fp_new.meta["sed_type_init"] == "likelihood"
def test_flux_points_single_bin_dnde(): path = make_path( "$GAMMAPY_DATA/tests/spectrum/flux_points/diff_flux_points.fits") table = Table.read(path) table_single_bin = table[1:2] fp = FluxPoints.from_table(table_single_bin, sed_type="dnde") with pytest.raises(ValueError): _ = fp.flux_ref with mpl_plot_check(): fp.plot(sed_type="e2dnde") with pytest.raises(ValueError): fp.to_table(sed_type="flux") table = fp.to_table(sed_type="dnde") assert_allclose(table["e_ref"], 153.992 * u.MeV, rtol=0.001) assert "e_min" not in table.colnames assert "e_max" not in table.colnames