def plot_energy_resolution(irf_file, ax=None, **kwargs): """ Plot angular resolution from an IRF file Parameters ---------- irf_filename ax kwargs Returns ------- """ e2d = EnergyDispersion2D.read(irf_file, hdu='ENERGY DISPERSION') edisp = e2d.to_energy_dispersion('0 deg') energy_bin = np.logspace(-1.5, 1, 15) e = np.sqrt(energy_bin[1:] * energy_bin[:-1]) xerr = (e - energy_bin[:-1], energy_bin[1:] - e) r = edisp.get_resolution(e) if 'fmt' not in kwargs: kwargs['fmt'] = 'o' ax.errorbar(e, r, xerr=xerr, **kwargs) ax.set_xscale('log') ax.grid(True, which='both') ax.set_title('Energy resoluton') ax.set_xlabel('Energy [TeV]') ax.legend() return ax
def setup_class(cls): filename = "$GAMMAPY_DATA/hess-dl3-dr1/data/hess_dl3_dr1_obs_id_020136.fits.gz" cls.edisp = EnergyDispersion2D.read(filename, hdu="EDISP") # Make a test case energy_axis_true = MapAxis.from_energy_bounds("0.1 TeV", "100 TeV", nbin=50, name="energy_true") migra_axis = MapAxis.from_bounds(0, 4, nbin=1000, node_type="edges", name="migra") offset_axis = MapAxis.from_bounds(0, 2.5, nbin=5, unit="deg", name="offset") energy_true = energy_axis_true.edges[:-1].reshape((-1, 1, 1)) sigma = 0.15 / (energy_true / (1 * u.TeV)).value**0.3 bias = 1e-3 * (energy_true - 1 * u.TeV).value cls.edisp2 = EnergyDispersion2D.from_gauss( energy_axis_true=energy_axis_true, migra_axis=migra_axis, bias=bias, sigma=sigma, offset_axis=offset_axis, )
def get_irfs(): filename = '$GAMMAPY_EXTRA/datasets/cta-1dc/caldb/data/cta//1dc/bcf/South_z20_50h/irf_file.fits' psf = EnergyDependentMultiGaussPSF.read(filename, hdu='POINT SPREAD FUNCTION') aeff = EffectiveAreaTable2D.read(filename, hdu='EFFECTIVE AREA') edisp = EnergyDispersion2D.read(filename, hdu='ENERGY DISPERSION') bkg = Background3D.read(filename, hdu='BACKGROUND') return dict(psf=psf, aeff=aeff, edisp=edisp, bkg=bkg)
def read(cls, filename): """Read from a FITS file. Parameters ---------- filename : `str` File containing the IRFs """ filename = str(make_path(filename)) hdu_list = fits.open(filename) aeff = EffectiveAreaTable2D.read(filename, hdu='EFFECTIVE AREA') bkg = Background3D.read(filename, hdu='BACKGROUND') edisp = EnergyDispersion2D.read(filename, hdu='ENERGY DISPERSION') psf = EnergyDependentMultiGaussPSF.read(filename, hdu='POINT SPREAD FUNCTION') if 'SENSITIVITY' in hdu_list: sensi = SensitivityTable.read(filename, hdu='SENSITIVITY') else: sensi = None return cls( aeff=aeff, bkg=bkg, edisp=edisp, psf=psf, ref_sensi=sensi, )
def energy_dispersion_3d_plot(irf_file_path, ax=None, hdu="ENERGY DISPERSION"): if not ax: fig = plt.figure(figsize=(10, 7), ) ax = fig.add_subplot(111, projection='3d') edisp = EnergyDispersion2D.read(irf_file_path, hdu=hdu) energy_reco = np.logspace(-2, 2, 20) * u.TeV offsets = np.linspace(0, 6, 7) * u.deg Z = [] for offset in offsets: erf = edisp.to_energy_dispersion(offset) zs = erf.get_resolution(energy_reco).value Z.append(zs) X, Y = np.meshgrid(energy_reco, offsets) Z = np.vstack(Z) mask = ~np.isfinite(Z) Z[mask] = np.nanmean(Z) Z = gaussian_filter(Z, sigma=0.8) X, Y, Z = np.log10(X.to_value('TeV')).ravel(), Y.ravel(), Z.ravel() ax.plot_trisurf(X, Y, Z, cmap='viridis', vmin=0, vmax=np.nanpercentile(Z, 99), antialiased=True) ax.xaxis.set_major_formatter(mticker.FuncFormatter(_log_tick_formatter)) return ax
def get_irfs(config, filename): '''Get IRFs from file. Parameters ---------- config : `dict` Configuration dictionary. filename : fits file IRFs file Returns ------- irfs : `dict` IRFs dictionary. ''' offset = Angle(config['selection']['offset_fov'] * u.deg) psf_fov = EnergyDependentMultiGaussPSF.read(filename, hdu='POINT SPREAD FUNCTION') psf = psf_fov.to_energy_dependent_table_psf(theta=offset) print(' psf', psf) aeff = EffectiveAreaTable2D.read(filename, hdu='EFFECTIVE AREA') edisp_fov = EnergyDispersion2D.read(filename, hdu='ENERGY DISPERSION') table = fits.open('irf_file.fits')['BACKGROUND'] table.columns.change_name(str('BGD'), str('Bgd')) table.header['TUNIT7'] = '1 / (MeV s sr)' bkg = Background3D.read(filename, hdu='BACKGROUND') irfs = dict(psf=psf, aeff=aeff, edisp=edisp_fov, bkg=bkg, offset=offset) return irfs
def test_energy_dispersion(): '''Test our energy dispersion is readable by gammapy''' pytest.importorskip('gammapy') from pyirf.io import create_energy_dispersion_hdu from gammapy.irf import EnergyDispersion2D e_bins = np.geomspace(0.1, 100, 31) * u.TeV migra_bins = np.linspace(0.2, 5, 101) fov_bins = [0, 1, 2, 3] * u.deg edisp = np.zeros((30, 100, 3)) edisp[:, 50, :] = 1.0 for point_like in [True, False]: with tempfile.NamedTemporaryFile(suffix='.fits') as f: hdu = create_energy_dispersion_hdu(edisp, e_bins, migra_bins, fov_bins, point_like=point_like) fits.HDUList([fits.PrimaryHDU(), hdu]).writeto(f.name) # test reading with gammapy works edisp2d = EnergyDispersion2D.read(f.name, 'EDISP') assert u.allclose(edisp, edisp2d.data.data, atol=1e-16)
def test_edisp2d_pointlike(): filename = "$GAMMAPY_DATA/joint-crab/dl3/magic/run_05029748_DL3.fits" edisp = EnergyDispersion2D.read(filename) hdu = edisp.to_table_hdu() assert edisp.is_pointlike assert hdu.header["HDUCLAS3"] == "POINT-LIKE"
def get_irfs(): """Load CTA IRFs""" filename = "$GAMMAPY_DATA/cta-1dc/caldb/data/cta/1dc/bcf/South_z20_50h/irf_file.fits" psf = EnergyDependentMultiGaussPSF.read(filename, hdu="POINT SPREAD FUNCTION") aeff = EffectiveAreaTable2D.read(filename, hdu="EFFECTIVE AREA") edisp = EnergyDispersion2D.read(filename, hdu="ENERGY DISPERSION") bkg = Background3D.read(filename, hdu="BACKGROUND") return dict(psf=psf, aeff=aeff, edisp=edisp, bkg=bkg)
def check_edisp(label): irf_file = '1dc/1dc/caldb/data/cta/1dc/bcf/' + label + '/irf_file.fits' log.info(f'Reading {irf_file}') edisp = EnergyDispersion2D.read(irf_file, hdu='ENERGY DISPERSION') edisp.peek() filename = 'checks/irfs/' + label + '_edisp.png' log.info(f'Writing {filename}') plt.savefig(filename)
def get_edisp(geom, geom_etrue): filename = "$GAMMAPY_DATA/hess-dl3-dr1/data/hess_dl3_dr1_obs_id_020136.fits.gz" edisp2d = EnergyDispersion2D.read(filename, hdu="EDISP") energy = geom.axes["energy"].edges energy_true = geom_etrue.axes["energy_true"].edges edisp_kernel = edisp2d.to_edisp_kernel( offset="1.2 deg", energy=energy, energy_true=energy_true ) edisp = EDispKernelMap.from_edisp_kernel(edisp_kernel) return edisp
def read_energy_resolution(irf_filename): e2d = EnergyDispersion2D.read(irf_filename, hdu='ENERGY DISPERSION') edisp = e2d.to_energy_dispersion('0 deg') energy_bin = np.logspace(-1.5, 1, 15) energy, energy_err = bins_limits_to_errorbars(energy_bin[:-1], energy_bin[1:], log=True) e_res = edisp.get_resolution(energy) return energy_bin[1:], energy_bin[:-1], e_res
def setup_class(cls): filename = "$GAMMAPY_DATA/hess-dl3-dr1/data/hess_dl3_dr1_obs_id_020136.fits.gz" cls.edisp = EnergyDispersion2D.read(filename, hdu="EDISP") # Make a test case e_true = np.logspace(-1.0, 2.0, 51) * u.TeV migra = np.linspace(0.0, 4.0, 1001) offset = np.linspace(0.0, 2.5, 5) * u.deg sigma = 0.15 / (e_true[:-1] / (1 * u.TeV)).value ** 0.3 bias = 1e-3 * (e_true[:-1] - 1 * u.TeV).value cls.edisp2 = EnergyDispersion2D.from_gauss(e_true, migra, bias, sigma, offset)
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 test_energy_dispersion_gammapy(edisp_hdus): '''Test our energy dispersion is readable by gammapy''' from gammapy.irf import EnergyDispersion2D edisp, hdus = edisp_hdus for hdu in hdus: with tempfile.NamedTemporaryFile(suffix='.fits') as f: fits.HDUList([fits.PrimaryHDU(), hdu]).writeto(f.name) # test reading with gammapy works edisp2d = EnergyDispersion2D.read(f.name, 'EDISP') assert u.allclose(edisp, edisp2d.data.data, atol=1e-16)
def setup(self): # TODO: use from_gauss method to create know edisp (see below) # At the moment only 1 test uses it (test_get_response) filename = "$GAMMAPY_DATA/tests/irf/hess/pa/hess_edisp_2d_023523.fits.gz" self.edisp = EnergyDispersion2D.read(filename, hdu="ENERGY DISPERSION") # Make a test case e_true = np.logspace(-1.0, 2.0, 51) * u.TeV migra = np.linspace(0.0, 4.0, 1001) offset = np.linspace(0.0, 2.5, 5) * u.deg sigma = 0.15 / (e_true[:-1] / (1 * u.TeV)).value**0.3 bias = 1e-3 * (e_true[:-1] - 1 * u.TeV).value self.edisp2 = EnergyDispersion2D.from_gauss(e_true, migra, bias, sigma, offset)
def load_irf(self): filename = os.path.join(self.outdir, "irf.fits.gz") with fits.open(filename, memmap=False) as hdulist: aeff = EffectiveAreaTable2D.from_hdulist(hdulist=hdulist) edisp = EnergyDispersion2D.read(filename, hdu="ENERGY DISPERSION") bkg_fits_table = hdulist["BACKGROUND"] bkg_table = Table.read(bkg_fits_table) energy_lo = bkg_table["ENERG_LO"].quantity energy_hi = bkg_table["ENERG_HI"].quantity bkg = bkg_table["BGD"].quantity axes = [ BinnedDataAxis(energy_lo, energy_hi, interpolation_mode="log", name="energy") ] bkg = BkgData(data=NDDataArray(axes=axes, data=bkg)) # 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.data.axes[0].lo[0] e_true_max = aeff.data.axes[0].hi[-1] e_true_bin = len(aeff.data.axes[0].bins) - 1 e_true_axis = EnergyBounds.equal_log_spacing(e_true_min, e_true_max, e_true_bin, "TeV") # Fake offset... rmf = edisp.to_energy_dispersion(offset=0.5 * u.deg, e_reco=e_reco_axis, e_true=e_true_axis) # This is required because in gammapy v0.8 # gammapy.spectrum.utils.integrate_model # calls the attribute aeff.energy which is an attribute of # EffectiveAreaTable and not of EffectiveAreaTable2D # WARNING the angle is not important, but only because we started with # on-axis data! TO UPDATE aeff = aeff.to_effective_area_table(Angle("1d")) self.irf = Irf(bkg=bkg, aeff=aeff, rmf=rmf)
def load(self): """Load HDU as appropriate class. TODO: this should probably go via an extensible registry. """ hdu_class = self.hdu_class filename = self.path() hdu = self.hdu_name if hdu_class == "events": from gammapy.data import EventList return EventList.read(filename, hdu=hdu) elif hdu_class == "gti": from gammapy.data import GTI return GTI.read(filename, hdu=hdu) elif hdu_class == "aeff_2d": from gammapy.irf import EffectiveAreaTable2D return EffectiveAreaTable2D.read(filename, hdu=hdu) elif hdu_class == "edisp_2d": from gammapy.irf import EnergyDispersion2D return EnergyDispersion2D.read(filename, hdu=hdu) elif hdu_class == "psf_table": from gammapy.irf import PSF3D return PSF3D.read(filename, hdu=hdu) elif hdu_class == "psf_3gauss": from gammapy.irf import EnergyDependentMultiGaussPSF return EnergyDependentMultiGaussPSF.read(filename, hdu=hdu) elif hdu_class == "psf_king": from gammapy.irf import PSFKing return PSFKing.read(filename, hdu=hdu) elif hdu_class == "bkg_2d": from gammapy.irf import Background2D return Background2D.read(filename, hdu=hdu) elif hdu_class == "bkg_3d": from gammapy.irf import Background3D return Background3D.read(filename, hdu=hdu) else: raise ValueError(f"Invalid hdu_class: {hdu_class}")
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 test_writeread(self, tmp_path): path = tmp_path / "tmp.fits" fits.HDUList([ fits.PrimaryHDU(), self.aeff.to_table_hdu(), self.edisp.to_table_hdu(), self.bkg.to_table_hdu(), ]).writeto(path) read_aeff = EffectiveAreaTable2D.read(path, hdu="EFFECTIVE AREA") assert_allclose(read_aeff.data.data, self.aeff_data) read_edisp = EnergyDispersion2D.read(path, hdu="ENERGY DISPERSION") assert_allclose(read_edisp.data.data, self.edisp_data) read_bkg = Background3D.read(path, hdu="BACKGROUND") assert_allclose(read_bkg.data.data, self.bkg_data)
def get_irfs(config): filename = '$GAMMAPY_EXTRA/datasets/cta-1dc/caldb/data/cta//1dc/bcf/South_z20_50h/irf_file.fits' offset = Angle(config['selection']['offset_fov'] * u.deg) psf_fov = EnergyDependentMultiGaussPSF.read(filename, hdu='POINT SPREAD FUNCTION') psf = psf_fov.to_energy_dependent_table_psf(theta=offset) print(' psf', psf) aeff = EffectiveAreaTable2D.read(filename, hdu='EFFECTIVE AREA') edisp_fov = EnergyDispersion2D.read(filename, hdu='ENERGY DISPERSION') edisp = edisp_fov.to_energy_dispersion(offset=offset) # TODO: read background once it's working! # bkg = Background3D.read(filename, hdu='BACKGROUND') return dict(psf=psf, aeff=aeff, edisp=edisp)
def test_writeread(self, tmpdir): filename = str(tmpdir / "testirf.fits") fits.HDUList([ fits.PrimaryHDU(), self.aeff.to_fits(), self.edisp.to_fits(), self.bkg.to_fits(), ]).writeto(filename) read_aeff = EffectiveAreaTable2D.read(filename=filename, hdu="EFFECTIVE AREA") assert_allclose(read_aeff.data.data, self.aeff_data) read_edisp = EnergyDispersion2D.read(filename=filename, hdu="ENERGY DISPERSION") assert_allclose(read_edisp.data.data, self.edisp_data) read_bkg = Background3D.read(filename=filename, hdu="BACKGROUND") assert_allclose(read_bkg.data.data, self.bkg_data)
def load_irf(self): filename = os.path.join(self.outdir, 'irf.fits.gz') with fits.open(filename, memmap=False) as hdulist: aeff = EffectiveAreaTable.from_hdulist(hdulist=hdulist) edisp = EnergyDispersion2D.read(filename, hdu="ENERGY DISPERSION") bkg_fits_table = hdulist["BACKGROUND"] bkg_table = Table.read(bkg_fits_table) energy_lo = bkg_table["ENERG_LO"].quantity energy_hi = bkg_table["ENERG_HI"].quantity bkg = bkg_table["BGD"].quantity axes = [ BinnedDataAxis( energy_lo, energy_hi, interpolation_mode="log", name="energy" ) ] bkg = BkgData(data=NDDataArray(axes=axes, data=bkg)) # 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" ) # Fake offset... rmf = edisp.to_energy_dispersion( offset=0.5 * u.deg, e_reco=e_reco_axis, e_true=e_true_axis ) self.irf = Irf(bkg=bkg, aeff=aeff, rmf=rmf)
"""Example of how to create an ObservationCTA from CTA's 1DC""" from gammapy.data import ObservationCTA, EventList, GTI from gammapy.irf import EnergyDependentMultiGaussPSF, EffectiveAreaTable2D, EnergyDispersion2D, Background3D filename = '$GAMMAPY_EXTRA/datasets/cta-1dc/data/baseline/gps/gps_baseline_110380.fits' event_list = EventList.read(filename) gti = GTI.read(filename) filename = '$GAMMAPY_EXTRA/datasets/cta-1dc/caldb/data/cta/1dc/bcf/South_z20_50h/irf_file.fits' aeff = EffectiveAreaTable2D.read(filename) bkg = Background3D.read(filename) edisp = EnergyDispersion2D.read(filename, hdu='Energy Dispersion') psf = EnergyDependentMultiGaussPSF.read(filename, hdu='Point Spread Function') obs = ObservationCTA( obs_id=event_list.table.meta['OBS_ID'], events=event_list, gti=gti, psf=psf, aeff=aeff, edisp=edisp, bkg=bkg, pointing_radec=event_list.pointing_radec, observation_live_time_duration=event_list.observation_live_time_duration, observation_dead_time_fraction=event_list.observation_dead_time_fraction, ) print(obs)
aeff.to_effective_area_table(offset="1 deg") # ### Energy dispersion # # Let's have a look at the CTA energy dispersion with three axes: true energy, fov offset and migra = e_reco / e_true and has dP / dmigra as value. # # Similar to the event energy distribution above, we can see the mixed-telescope array reflected in the EDISP. # At low energies the events are only detected and reconstructed by the LSTs. # At ~100 GeV, the MSTs take over and EDISP is chaotic in the ~ 50 GeV to 100 GeV energy range. # So it can be useful to have quick access to IRFs like with Gammapy (e.g. for spectral line searches in this case), even if for 95% of science analyses users later won't have to look at the IRFs and just trust that everything is working. # In[ ]: from gammapy.irf import EnergyDispersion2D edisp = EnergyDispersion2D.read(irf_filename, hdu="ENERGY DISPERSION") print(type(edisp)) print(type(edisp.data)) # In[ ]: print(edisp.data) # In[ ]: edisp.peek() # In[ ]: # This is how for analysis you could slice out an `EnergyDispersion` # object at a given offset:
import os #now reading IRFs from one particular observation DIR = "/Users/asinha/HESS_data/ash_stereo/run054200-054399/run054213/" files = os.listdir(DIR) for afile in files: if afile[0:4] == "aeff": f_ar = str(DIR + afile) if afile[0:5] == "edisp": f_edp = str(DIR + afile) if afile[0:3] == "psf": f_psf = str(DIR + afile) aeff = EffectiveAreaTable2D.read(f_ar, hdu='EFFECTIVE AREA') edisp = EnergyDispersion2D.read(f_edp) #psf = EnergyDependentMultiGaussPSF.read(f_psf, hdu='POINT SPREAD FUNCTION') # Define obs parameters livetime = 1.0 * u.hr offset = 0.01 * u.deg lo_threshold = 0.1 * u.TeV hi_threshold = 60 * u.TeV # Define spectral model index = 2.0 * u.Unit('') amplitude = 2.5 * 1e-10 * u.Unit('cm-2 s-1 TeV-1') reference = 1 * u.TeV model = PowerLaw(index=index, amplitude=amplitude, reference=reference) edisp = edisp.to_energy_dispersion(offset=offset)
"""Plot the energy dispersion at a given offset.""" import matplotlib.pyplot as plt from astropy.coordinates import Angle from gammapy.irf import EnergyDispersion2D filename = "$GAMMAPY_DATA/hess-dl3-dr1/data/hess_dl3_dr1_obs_id_020136.fits.gz" edisp = EnergyDispersion2D.read(filename, hdu="EDISP") # offset at which we want to examine the energy dispersion offset = Angle("0.5 deg") edisp_kernel = edisp.to_energy_dispersion(offset=offset) edisp_kernel.peek() plt.show()