def stats_stacked_bad_on_region(bad_on_region, observations): bge = ReflectedRegionsBackgroundEstimator( on_region=bad_on_region, observations=observations ) bge.run() return ObservationStats.stack( [ ObservationStats.from_observation(obs, bg) for obs, bg in zip(observations, bge.result) ] )
def test_extract(pars, results, observations, bkg_estimate): """Test quantitative output for various configs""" extraction = SpectrumExtraction(observations=observations, bkg_estimate=bkg_estimate, **pars) extraction.run() obs = extraction.spectrum_observations[0] aeff_actual = obs.aeff.data.evaluate(energy=5 * u.TeV) edisp_actual = obs.edisp.data.evaluate(e_true=5 * u.TeV, e_reco=5.2 * u.TeV) assert_quantity_allclose(aeff_actual, results["aeff"], rtol=1e-3) assert_quantity_allclose(edisp_actual, results["edisp"], rtol=1e-3) containment_actual = extraction.containment[60] # TODO: Introduce assert_stats_allclose stats = ObservationStats(**obs._info_dict()) n_on_actual = stats.n_on sigma_actual = stats.sigma assert n_on_actual == results["n_on"] assert_allclose(sigma_actual, results["sigma"], atol=1e-2) assert_allclose(containment_actual, results["containment"], rtol=1e-3) gti_obs = obs.gti.table gti_dataset = extraction.spectrum_observations[0].gti.table assert_allclose(gti_dataset["START"], gti_obs["START"]) assert_allclose(gti_dataset["STOP"], gti_obs["STOP"])
def peek(self, figsize=(10, 10)): """Quick-look summary plots.""" import matplotlib.pyplot as plt e_min, e_max = self.energy_range fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, figsize=figsize) ax1.set_title("Counts") energy_unit = "TeV" if self.counts_off is not None: self.background.plot_hist(ax=ax1, label="alpha * n_off", color="darkblue", energy_unit=energy_unit) self.counts.plot_hist( ax=ax1, label="n_on", color="darkred", energy_unit=energy_unit, show_energy=(e_min, e_max), ) ax1.set_xlim(0.7 * e_min.to_value(energy_unit), 1.3 * e_max.to_value(energy_unit)) ax1.legend(numpoints=1) ax2.set_title("Effective Area") e_unit = self.aeff.energy.unit self.aeff.plot(ax=ax2, show_energy=(e_min, e_max)) ax2.set_xlim(0.7 * e_min.to_value(e_unit), 1.3 * e_max.to_value(e_unit)) ax3.axis("off") if self.counts_off is not None: info = self._info_dict(in_safe_energy_range=True) info["obs_id"] = info.pop("name") stats = ObservationStats(**info) ax3.text(0, 0.2, f"{stats}", fontsize=12) ax4.set_title("Energy Dispersion") if self.edisp is not None: self.edisp.plot_matrix(ax=ax4) # TODO: optimize layout plt.subplots_adjust(wspace=0.3)
def setup_class(cls): datastore = DataStore.from_dir("$GAMMAPY_DATA/hess-dl3-dr1/") obs_ids = [23523, 23526] on_region = CircleSkyRegion( SkyCoord(83.63 * u.deg, 22.01 * u.deg, frame="icrs"), 0.3 * u.deg) obs_stats_list = [] for obs_id in obs_ids: obs = datastore.obs(obs_id) bkg = ReflectedRegionsBackgroundEstimator(on_region=on_region, observations=[obs]) bkg.run() bg_estimate = bkg.result[0] obs_stats = ObservationStats.from_observation(obs, bg_estimate) obs_stats_list.append(obs_stats) cls.obs_summary = ObservationSummary(obs_stats_list)
# print(background_estimator.result[0]) # In[ ]: plt.figure(figsize=(8, 8)) background_estimator.plot(add_legend=True) # ## Source statistic # # Next we're going to look at the overall source statistics in our signal region. For more info about what debug plots you can create check out the [ObservationSummary](https://docs.gammapy.org/0.10/api/gammapy.data.ObservationSummary.html#gammapy.data.ObservationSummary) class. # In[ ]: stats = [] for obs, bkg in zip(observations, background_estimator.result): stats.append(ObservationStats.from_observation(obs, bkg)) print(stats[1]) obs_summary = ObservationSummary(stats) fig = plt.figure(figsize=(10, 6)) ax1 = fig.add_subplot(121) obs_summary.plot_excess_vs_livetime(ax=ax1) ax2 = fig.add_subplot(122) obs_summary.plot_significance_vs_livetime(ax=ax2) # ## Extract spectrum # # Now, we're going to extract a spectrum using the [SpectrumExtraction](https://docs.gammapy.org/0.10/api/gammapy.spectrum.SpectrumExtraction.html) class. We provide the reconstructed energy binning we want to use. It is expected to be a Quantity with unit energy, i.e. an array with an energy unit. We use a utility function to create it. We also provide the true energy binning to use.
def stats_bad_on_region(bad_on_region, observations): obs = observations[0] bge = ReflectedRegionsBackgroundEstimator(on_region=bad_on_region, observations=obs) bg = bge.process(obs) return ObservationStats.from_observation(obs, bg)
def calculate_flux_point_binning(obs_list, min_signif): """Compute energy binning This is usefule to get an energy binning to use with :func:`~gammapy.spectrum.DifferentialFluxPoints.compute` Each bin in the resulting energy binning will include a ``min_signif`` source detection. TODO: This only works for one observation at the moment. Make it stack counts before computing the binning TODO: It is required that at least two fine bins be included in one flux point interval, otherwise the sherpa covariance method breaks down. Parameters ---------- obs_list : `~gammapy.spectrum.SpectrumObservationList` Observations min_signif : float Required significance for each bin Returns ------- binning : `~astropy.units.Quantity` Energy binning """ # NOTE: Results may vary from FitSpectrum since there the rebin # parameter can only have fixed values, here it grows linearly. Also it # has to start at 2 here (see docstring) # rebin_factor = 1 rebin_factor = 2 # TODO: Implement stacking (at least for counts) if len(obs_list) > 1: raise NotImplementedError('stack counts') obs = obs_list[0] # First first bin above low threshold and last bin below high threshold current_ebins = obs.on_vector.energy current_bin = (current_ebins.find_node(obs.lo_threshold) + 1)[0] max_bin = (current_ebins.find_node(obs.hi_threshold))[0] # List holding final energy binning binning = [current_ebins.data[current_bin]] # Precompute ObservationStats for each bin obs_stats = [obs.stats(i) for i in range(current_ebins.nbins)] while (current_bin + rebin_factor <= max_bin): # Merge bins together until min_signif is reached stats_list = obs_stats[current_bin:current_bin + rebin_factor:1] stats = ObservationStats.stack(stats_list) sigma = stats.sigma if (sigma < min_signif or np.isnan(sigma)): rebin_factor += 1 continue # Append upper bin edge of good energy bin to final binning binning.append(current_ebins.data[current_bin + rebin_factor]) current_bin += rebin_factor binning = Quantity(binning) # Replace highest bin edge by high threshold binning[-1] = obs.hi_threshold return binning