def to_energy_dependent_table_psf(self, offset, rad=None): """Convert to energy-dependent table PSF. Parameters ---------- offset : `~astropy.coordinates.Angle` Offset in the field of view. Default theta = 0 deg rad : `~astropy.coordinates.Angle` Offset from PSF center used for evaluating the PSF on a grid. Default offset = [0, 0.005, ..., 1.495, 1.5] deg. Returns ------- table_psf : `~gammapy.irf.EnergyDependentTablePSF` Energy-dependent PSF """ from gammapy.irf import EnergyDependentTablePSF from gammapy.datasets.map import RAD_AXIS_DEFAULT energy_axis_true = self.axes["energy_true"] if rad is None: rad_axis = RAD_AXIS_DEFAULT else: rad_axis = MapAxis.from_edges(rad, name="rad") axes = MapAxes([energy_axis_true, rad_axis]) data = self.evaluate(**axes.get_coord(), offset=offset) return EnergyDependentTablePSF(axes=axes, data=data.value, unit=data.unit)
def get_energy_dependent_table_psf(self, position): """Get energy-dependent PSF at a given position. Parameters ---------- position : `~astropy.coordinates.SkyCoord` the target position. Should be a single coordinates Returns ------- psf_table : `~gammapy.irf.EnergyDependentTablePSF` the table PSF """ if position.size != 1: raise ValueError( "EnergyDependentTablePSF can be extracted at one single position only." ) # axes ordering fixed. Could be changed. pix_ener = np.arange(self.psf_map.geom.axes[1].nbin) pix_rad = np.arange(self.psf_map.geom.axes[0].nbin) # Convert position to pixels pix_lon, pix_lat = self.psf_map.geom.to_image().coord_to_pix(position) # Build the pixels tuple pix = np.meshgrid(pix_lon, pix_lat, pix_rad, pix_ener) # Interpolate in the PSF map. Squeeze to remove dimensions of length 1 psf_values = np.squeeze( self.psf_map.interp_by_pix(pix) * u.Unit(self.psf_map.unit) ) energies = self.psf_map.geom.axes[1].center rad = self.psf_map.geom.axes[0].center if self.exposure_map is not None: exposure_3d = self.exposure_map.slice_by_idx({"theta": 0}) coords = { "skycoord": position, "energy": energies.reshape((-1, 1, 1)) } data = exposure_3d.interp_by_coord(coords).squeeze() exposure = data * self.exposure_map.unit else: exposure = None # Beware. Need to revert rad and energies to follow the TablePSF scheme. return EnergyDependentTablePSF( energy=energies, rad=rad, psf_value=psf_values.T, exposure=exposure )
def get_energy_dependent_table_psf(self, position): """Get energy-dependent PSF at a given position. Parameters ---------- position : `~astropy.coordinates.SkyCoord` the target position. Should be a single coordinates Returns ------- psf_table : `~gammapy.irf.EnergyDependentTablePSF` the table PSF """ if position.size != 1: raise ValueError( "EnergyDependentTablePSF can be extracted at one single position only." ) energy = self.psf_map.geom.get_axis_by_name("energy").center rad = self.psf_map.geom.get_axis_by_name("theta").center coords = { "skycoord": position, "energy": energy.reshape((-1, 1, 1, 1)), "theta": rad.reshape((1, -1, 1, 1)), } data = self.psf_map.interp_by_coord(coords) psf_values = u.Quantity(data[:, :, 0, 0], unit=self.psf_map.unit, copy=False) if self.exposure_map is not None: coords = { "skycoord": position, "energy": energy.reshape((-1, 1, 1)), "theta": 0 * u.deg, } data = self.exposure_map.interp_by_coord(coords).squeeze() exposure = data * self.exposure_map.unit else: exposure = None # Beware. Need to revert rad and energies to follow the TablePSF scheme. return EnergyDependentTablePSF(energy=energy, rad=rad, psf_value=psf_values, exposure=exposure)
def test_apply_containment_fraction(): n_edges_energy = 5 energy = energy_logspace(0.1, 10.0, nbins=n_edges_energy + 1, unit="TeV") area = np.ones(n_edges_energy) * 4 * u.m**2 aeff = EffectiveAreaTable(energy[:-1], energy[1:], data=area) nrad = 100 rad = Angle(np.linspace(0, 0.5, nrad), "deg") psf_table = TablePSF.from_shape(shape="disk", width="0.2 deg", rad=rad) psf_values = (np.resize(psf_table.psf_value.value, (n_edges_energy, nrad)) * psf_table.psf_value.unit) edep_psf_table = EnergyDependentTablePSF(aeff.energy.center, rad, psf_value=psf_values) new_aeff = apply_containment_fraction(aeff, edep_psf_table, Angle("0.1 deg")) assert_allclose(new_aeff.data.data.value, 1.0, rtol=5e-4) assert new_aeff.data.data.unit == "m2"