def run_fit(self, optimize_opts=None): """Run all step for the spectrum fit.""" fit_range = self.config["fit"].get("fit_range") model = self.config["fit"]["model"] for obs in self.extraction.spectrum_observations: if fit_range is not None: obs.mask_fit = obs.counts.energy_mask(fit_range[0], fit_range[1]) obs.model = model self.fit = Fit(self.extraction.spectrum_observations) self.fit_result = self.fit.run(optimize_opts=optimize_opts) model = self.config["fit"]["model"] modelname = model.__class__.__name__ model.parameters.covariance = self.fit_result.parameters.covariance filename = make_path( self.config["outdir"]) / "fit_result_{}.yaml".format(modelname) self.write(filename=filename) obs_stacker = SpectrumDatasetOnOffStacker( self.extraction.spectrum_observations) obs_stacker.run() datasets_fp = obs_stacker.stacked_obs datasets_fp.model = model self.flux_point_estimator = FluxPointsEstimator( e_edges=self.config["fp_binning"], datasets=datasets_fp) fp = self.flux_point_estimator.run() fp.table["is_ul"] = fp.table["ts"] < 4 self.flux_points = fp
def test_stack_backscal(self): """Verify backscal stacking """ obs_list = make_observation_list() obs_stacker = SpectrumDatasetOnOffStacker(obs_list) obs_stacker.run() assert_allclose(obs_stacker.stacked_obs.alpha[0], 1.25 / 4.0) # When the OFF stack observation counts=0, the alpha is averaged on the total OFF counts for each run. assert_allclose(obs_stacker.stacked_obs.alpha[1], 2.5 / 8.0)
def test_stack_gti(self): obs_list = make_observation_list() obs_stacker = SpectrumDatasetOnOffStacker(obs_list) obs_stacker.run() table_gti = Table({ "START": [1.0, 5.0, 14.0], "STOP": [4.0, 8.0, 15.0] }) table_gti_stacked_obs = obs_stacker.stacked_obs.gti.table assert_allclose(table_gti_stacked_obs["START"], table_gti["START"]) assert_allclose(table_gti_stacked_obs["STOP"], table_gti["STOP"])
def setup(self): self.obs_list = _read_hess_obs() # Change threshold to make stuff more interesting self.obs_list[0].mask_safe = self.obs_list[0].counts.energy_mask( emin=1.2 * u.TeV, emax=50 * u.TeV) self.obs_list[1].mask_safe &= self.obs_list[0].counts.energy_mask( emax=20 * u.TeV) self.obs_stacker = SpectrumDatasetOnOffStacker(self.obs_list) self.obs_stacker.run()
def test_stacked_fit(self): obs_stacker = SpectrumDatasetOnOffStacker(self.obs_list) obs_stacker.run() dataset = obs_stacker.stacked_obs dataset.model = self.pwl fit = Fit([dataset]) result = fit.run() pars = result.parameters assert_allclose(pars["index"].value, 2.7767, rtol=1e-3) assert u.Unit(pars["amplitude"].unit) == "cm-2 s-1 TeV-1" assert_allclose(pars["amplitude"].value, 5.191e-11, rtol=1e-3)
get_ipython().run_cell_magic( 'time', '', 'model = models.PowerLaw(\n index=2, amplitude=1e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.TeV\n)\n\nfor dataset in extract.spectrum_observations:\n dataset.model = model\n\nfit = Fit(extract.spectrum_observations)\nresult = fit.run()\nprint(result)' ) # ### Spectral points # # Finally, let's compute spectral points. The method used is to first choose an energy binning, and then to do a 1-dim likelihood fit / profile to compute the flux and flux error. # In[ ]: # Flux points are computed on stacked observation from gammapy.spectrum import SpectrumDatasetOnOffStacker stacker = SpectrumDatasetOnOffStacker(extract.spectrum_observations) stacked_obs = stacker.run() print(stacked_obs) # In[ ]: e_edges = np.logspace(0, 1.5, 5) * u.TeV stacked_obs.model = model fpe = FluxPointsEstimator(datasets=[dataset], e_edges=e_edges) flux_points = fpe.run() flux_points.table_formatted # ### Plot
flux_points_dataset = FluxPointsDataset(data=flux_points, model=model_best_joint) # In[ ]: plt.figure(figsize=(8, 6)) flux_points_dataset.peek() # ## Stack observations # # And alternative approach to fitting the spectrum is stacking all observations first and the fitting a model. For this we first stack the individual datasets using the `SpectrumDatasetOnOffStacker` class: # In[ ]: stacker = SpectrumDatasetOnOffStacker(datasets_joint) dataset_stacked = stacker.run() # Again we set the model on the dataset we would like to fit (in this case it's only a singel one) and pass it to the `Fit` object: # In[ ]: dataset_stacked.model = model stacked_fit = Fit([dataset_stacked]) result_stacked = stacked_fit.run() # make a copy to compare later model_best_stacked = model.copy() model_best_stacked.parameters.covariance = result_stacked.parameters.covariance # In[ ]:
joint_fit = Fit(extraction.spectrum_observations) joint_result = joint_fit.run() model.parameters.covariance = joint_result.parameters.covariance print(joint_result) # Now you might want to do the stacking here even if in our case there is only one observation which makes it superfluous. # We can compute flux points by fitting the norm of the global model in energy bands. # In[ ]: e_edges = np.logspace(np.log10(0.04), np.log10(0.4), 7) * u.TeV from gammapy.spectrum import SpectrumDatasetOnOffStacker stacker = SpectrumDatasetOnOffStacker(extraction.spectrum_observations) dataset = stacker.run() dataset.model = model fpe = FluxPointsEstimator(datasets=[dataset], e_edges=e_edges) flux_points = fpe.run() flux_points.table["is_ul"] = flux_points.table["ts"] < 1 amplitude_ref = 0.57 * 19.4e-14 * u.Unit("1 / (cm2 s MeV)") spec_model_true = PowerLaw(index=4.5, amplitude=amplitude_ref, reference="20 GeV") flux_points_dataset = FluxPointsDataset(data=flux_points, model=model)
class TestSpectrumDatasetOnOffStacker: def setup(self): self.obs_list = _read_hess_obs() # Change threshold to make stuff more interesting self.obs_list[0].mask_safe = self.obs_list[0].counts.energy_mask( emin=1.2 * u.TeV, emax=50 * u.TeV) self.obs_list[1].mask_safe &= self.obs_list[0].counts.energy_mask( emax=20 * u.TeV) self.obs_stacker = SpectrumDatasetOnOffStacker(self.obs_list) self.obs_stacker.run() def test_basic(self): assert "Stacker" in str(self.obs_stacker) obs_1, obs_2 = self.obs_list counts1 = obs_1.counts.data[obs_1.mask_safe].sum() counts2 = obs_2.counts.data[obs_2.mask_safe].sum() summed_counts = counts1 + counts2 obs_stacked = self.obs_stacker.stacked_obs stacked_counts = obs_stacked.counts.data.sum() assert summed_counts == stacked_counts def test_thresholds(self): e_min, e_max = self.obs_stacker.stacked_obs.energy_range assert e_min.unit == "keV" assert_allclose(e_min.value, 8.912509e08, rtol=1e-3) assert e_max.unit == "keV" assert_allclose(e_max.value, 4.466836e10, rtol=1e-3) def test_verify_npred(self): """Veryfing npred is preserved during the stacking""" pwl = PowerLaw(index=2, amplitude=2e-11 * u.Unit("cm-2 s-1 TeV-1"), reference=1 * u.TeV) self.obs_stacker.stacked_obs.model = pwl npred_stacked = self.obs_stacker.stacked_obs.npred().data npred_summed = np.zeros_like(npred_stacked) for obs in self.obs_list: obs.model = pwl npred_summed[obs.mask_safe] += obs.npred().data[obs.mask_safe] assert_allclose(npred_stacked, npred_summed) def test_stack_backscal(self): """Verify backscal stacking """ obs_list = make_observation_list() obs_stacker = SpectrumDatasetOnOffStacker(obs_list) obs_stacker.run() assert_allclose(obs_stacker.stacked_obs.alpha[0], 1.25 / 4.0) # When the OFF stack observation counts=0, the alpha is averaged on the total OFF counts for each run. assert_allclose(obs_stacker.stacked_obs.alpha[1], 2.5 / 8.0) def test_stack_gti(self): obs_list = make_observation_list() obs_stacker = SpectrumDatasetOnOffStacker(obs_list) obs_stacker.run() table_gti = Table({ "START": [1.0, 5.0, 14.0], "STOP": [4.0, 8.0, 15.0] }) table_gti_stacked_obs = obs_stacker.stacked_obs.gti.table assert_allclose(table_gti_stacked_obs["START"], table_gti["START"]) assert_allclose(table_gti_stacked_obs["STOP"], table_gti["STOP"])