def from_table_hdu(cls, hdu): """Create `EnergyDependentMultiGaussPSF` from HDU list. Parameters ---------- hdu : `~astropy.io.fits.BinTableHDU` HDU """ table = Table.read(hdu) energy_axis_true = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") offset_axis = MapAxis.from_table(table, column_prefix="THETA", format="gadf-dl3") # Get sigmas shape = (offset_axis.nbin, energy_axis_true.nbin) sigmas = [] for key in ["SIGMA_1", "SIGMA_2", "SIGMA_3"]: sigma = hdu.data[key].reshape(shape).copy() sigmas.append(sigma) # Get amplitudes norms = [] for key in ["SCALE", "AMPL_2", "AMPL_3"]: norm = hdu.data[key].reshape(shape).copy() norms.append(norm) return cls(energy_axis_true=energy_axis_true, offset_axis=offset_axis, sigmas=sigmas, norms=norms, meta=dict(hdu.header))
def from_table(cls, table): """Create `PSF3D` from `~astropy.table.Table`. Parameters ---------- table : `~astropy.table.Table` Table Table-PSF info. """ psf_value = table["RPSF"].quantity[0] opts = {} try: opts["energy_thresh_lo"] = u.Quantity(table.meta["LO_THRES"], "TeV") opts["energy_thresh_hi"] = u.Quantity(table.meta["HI_THRES"], "TeV") except KeyError: pass energy_axis_true = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") offset_axis = MapAxis.from_table(table, column_prefix="THETA", format="gadf-dl3") rad_axis = MapAxis.from_table(table, column_prefix="RAD", format="gadf-dl3") return cls(energy_axis_true=energy_axis_true, offset_axis=offset_axis, rad_axis=rad_axis, psf_value=psf_value, **opts)
def from_table(cls, table): """Create `PSFKing` from `~astropy.table.Table`. Parameters ---------- table : `~astropy.table.Table` Table King PSF info. """ energy_axis_true = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") offset_axis = MapAxis.from_table(table, column_prefix="THETA", format="gadf-dl3") gamma = table["GAMMA"].quantity[0] sigma = table["SIGMA"].quantity[0] opts = {} try: opts["energy_thresh_lo"] = Quantity(table.meta["LO_THRES"], "TeV") opts["energy_thresh_hi"] = Quantity(table.meta["HI_THRES"], "TeV") except KeyError: pass return cls(energy_axis_true=energy_axis_true, offset_axis=offset_axis, gamma=gamma, sigma=sigma, **opts)
def from_table(cls, table): """Create from `~astropy.table.Table`.""" # TODO: move this to MapAxis.from_table() if "ENERG_LO" in table.colnames: energy_axis_true = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") elif "ETRUE_LO" in table.colnames: energy_axis_true = MapAxis.from_table(table, column_prefix="ETRUE", format="gadf-dl3") else: raise ValueError( 'Invalid column names. Need "ENERG_LO/ENERG_HI" or "ETRUE_LO/ETRUE_HI"' ) offset_axis = MapAxis.from_table(table, column_prefix="THETA", format="gadf-dl3") migra_axis = MapAxis.from_table(table, column_prefix="MIGRA", format="gadf-dl3") matrix = table["MATRIX"].quantity[0].transpose() return cls( energy_axis_true=energy_axis_true, offset_axis=offset_axis, migra_axis=migra_axis, data=matrix, )
def from_table(cls, table): """Read from `~astropy.table.Table`.""" # Spec says key should be "BKG", but there are files around # (e.g. CTA 1DC) that use "BGD". For now we support both if "BKG" in table.colnames: bkg_name = "BKG" elif "BGD" in table.colnames: bkg_name = "BGD" else: raise ValueError('Invalid column names. Need "BKG" or "BGD".') data_unit = u.Unit(table[bkg_name].unit, parse_strict="silent") if isinstance(data_unit, u.UnrecognizedUnit): data_unit = u.Unit("s-1 MeV-1 sr-1") log.warning( "Invalid unit found in background table! Assuming (s-1 MeV-1 sr-1)" ) energy_axis = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") fov_lon_axis = MapAxis.from_table(table, column_prefix="DETX", format="gadf-dl3") fov_lat_axis = MapAxis.from_table(table, column_prefix="DETY", format="gadf-dl3") return cls( energy_axis=energy_axis, fov_lon_axis=fov_lon_axis, fov_lat_axis=fov_lat_axis, data=table[bkg_name].data[0] * data_unit, meta=table.meta, )
def from_table(cls, table): """Read from `~astropy.table.Table`.""" # Spec says key should be "BKG", but there are files around # (e.g. CTA 1DC) that use "BGD". For now we support both if "BKG" in table.colnames: bkg_name = "BKG" elif "BGD" in table.colnames: bkg_name = "BGD" else: raise ValueError('Invalid column names. Need "BKG" or "BGD".') data_unit = table[bkg_name].unit if data_unit is not None: data_unit = u.Unit(table[bkg_name].unit, parse_strict="silent") if isinstance(data_unit, u.UnrecognizedUnit) or (data_unit is None): data_unit = u.Unit("s-1 MeV-1 sr-1") log.warning( "Invalid unit found in background table! Assuming (s-1 MeV-1 sr-1)" ) energy_axis = MapAxis.from_table( table, column_prefix="ENERG", format="gadf-dl3" ) fov_lon_axis = MapAxis.from_table( table, column_prefix="DETX", format="gadf-dl3" ) fov_lat_axis = MapAxis.from_table( table, column_prefix="DETY", format="gadf-dl3" ) # TODO: The present HESS and CTA backgroundfits files # have a reverse order (lon, lat, E) than recommened in GADF(E, lat, lon) # For now, we suport both. data = table[bkg_name].data[0].T * data_unit shape = (energy_axis.nbin, fov_lon_axis.nbin, fov_lat_axis.nbin) if shape == shape[::-1]: log.error("Ambiguous axes order in Background fits files!") if np.shape(data) != shape: log.debug("Transposing background table on read") data = data.transpose() return cls( energy_axis=energy_axis, fov_lon_axis=fov_lon_axis, fov_lat_axis=fov_lat_axis, data=data, meta=table.meta, )
def from_table(cls, table): """Read from `~astropy.table.Table`.""" energy_axis_true = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") offset_axis = MapAxis.from_table(table, column_prefix="THETA", format="gadf-dl3") return cls( energy_axis_true=energy_axis_true, offset_axis=offset_axis, data=table["EFFAREA"].quantity[0].transpose(), meta=table.meta, )
def from_table(cls, table): """Create from `~astropy.table.Table` in ARF format. Data format specification: :ref:`gadf:ogip-arf` """ energy_axis_true = MapAxis.from_table(table, format="ogip-arf") data = table["SPECRESP"].quantity return cls(energy_axis_true=energy_axis_true, data=data)
def from_table_hdu(cls, hdu): """Create `EnergyDependentMultiGaussPSF` from HDU list. Parameters ---------- hdu : `~astropy.io.fits.BinTableHDU` HDU """ table = Table.read(hdu) energy_axis_true = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") offset_axis = MapAxis.from_table(table, column_prefix="THETA", format="gadf-dl3") # Get sigmas shape = (offset_axis.nbin, energy_axis_true.nbin) sigmas = [] for key in ["SIGMA_1", "SIGMA_2", "SIGMA_3"]: sigma = hdu.data[key].reshape(shape).copy() sigmas.append(sigma) # Get amplitudes norms = [] for key in ["SCALE", "AMPL_2", "AMPL_3"]: norm = hdu.data[key].reshape(shape).copy() norms.append(norm) opts = {} try: opts["energy_thresh_lo"] = u.Quantity(hdu.header["LO_THRES"], "TeV") opts["energy_thresh_hi"] = u.Quantity(hdu.header["HI_THRES"], "TeV") except KeyError: pass return cls( energy_axis_true=energy_axis_true, offset_axis=offset_axis, sigmas=sigmas, norms=norms, **opts, )
def from_hdulist(cls, hdulist, hdu1="MATRIX", hdu2="EBOUNDS"): """Create `EnergyDispersion` object from `~astropy.io.fits.HDUList`. Parameters ---------- hdulist : `~astropy.io.fits.HDUList` HDU list with ``MATRIX`` and ``EBOUNDS`` extensions. hdu1 : str, optional HDU containing the energy dispersion matrix, default: MATRIX hdu2 : str, optional HDU containing the energy axis information, default, EBOUNDS """ matrix_hdu = hdulist[hdu1] ebounds_hdu = hdulist[hdu2] data = matrix_hdu.data header = matrix_hdu.header pdf_matrix = np.zeros([len(data), header["DETCHANS"]], dtype=np.float64) for i, l in enumerate(data): if l.field("N_GRP"): m_start = 0 for k in range(l.field("N_GRP")): pdf_matrix[i, l.field("F_CHAN")[k]:l.field("F_CHAN")[k] + l.field("N_CHAN")[k], ] = l.field( "MATRIX")[m_start:m_start + l.field("N_CHAN")[k]] m_start += l.field("N_CHAN")[k] table = Table.read(ebounds_hdu) energy_axis = MapAxis.from_table(table, format="ogip") table = Table.read(matrix_hdu) energy_axis_true = MapAxis.from_table(table, format="ogip-arf") return cls( energy_axis=energy_axis, energy_axis_true=energy_axis_true, data=pdf_matrix, )
def from_table(cls, table): """Create `PSFKing` from `~astropy.table.Table`. Parameters ---------- table : `~astropy.table.Table` Table King PSF info. """ energy_axis_true = MapAxis.from_table(table, column_prefix="ENERG", format="gadf-dl3") offset_axis = MapAxis.from_table(table, column_prefix="THETA", format="gadf-dl3") gamma = table["GAMMA"].quantity[0] sigma = table["SIGMA"].quantity[0] return cls(energy_axis_true=energy_axis_true, offset_axis=offset_axis, gamma=gamma, sigma=sigma, meta=table.meta)
def __init__(self, data, reference_spectral_model): # TODO: Check data self._data = data if hasattr(self._data["norm"], "geom"): self._energy_axis = self.data["norm"].geom.axes["energy"] self._expand_slice = (slice(None), np.newaxis, np.newaxis) else: # Here we assume there is only one row per energy self._energy_axis = MapAxis.from_table(table=data, format="gadf-sed") self._expand_slice = slice(None) # Note that here we could use the specification from dnde_ref to build piecewise PL # But does it work beyond min and max centers? self._reference_spectral_model = reference_spectral_model
def _convert_flux_columns(table, reference_model, sed_type): energy_axis = MapAxis.from_table(table, format="gadf-sed") with np.errstate(invalid="ignore", divide="ignore"): fluxes = reference_model.reference_fluxes(energy_axis=energy_axis) # TODO: handle reshaping in MapAxis col_ref = table[sed_type] factor = fluxes[f"ref_{sed_type}"].to(col_ref.unit) data = Table(fluxes) data["norm"] = col_ref / factor for key in OPTIONAL_QUANTITIES[sed_type]: if key in table.colnames: norm_type = key.replace(sed_type, "norm") data[norm_type] = table[key] / factor return data
def from_hdulist(cls, hdu_list): """Create `EnergyDependentTablePSF` from ``gtpsf`` format HDU list. Parameters ---------- hdu_list : `~astropy.io.fits.HDUList` HDU list with ``THETA`` and ``PSF`` extensions. """ rad_axis = MapAxis.from_table_hdu(hdu_list["THETA"], format="gtpsf") table = Table.read(hdu_list["PSF"]) energy_axis_true = MapAxis.from_table(table, format="gtpsf") exposure = table["Exposure"].data * u.Unit("cm2 s") data = table["Psf"].data return cls(axes=[energy_axis_true, rad_axis], exposure=exposure, data=data, unit="sr-1")
def from_hdulist( cls, hdulist, hdu=None, hdu_bands=None, exposure_hdu=None, exposure_hdu_bands=None, format="gadf", ): """Create from `~astropy.io.fits.HDUList`. Parameters ---------- hdulist : `~astropy.fits.HDUList` HDU list. hdu : str Name or index of the HDU with the IRF map. hdu_bands : str Name or index of the HDU with the IRF map BANDS table. exposure_hdu : str Name or index of the HDU with the exposure map data. exposure_hdu_bands : str Name or index of the HDU with the exposure map BANDS table. format : {"gadf", "gtpsf"} File format Returns ------- irf_map : `IRFMap` IRF map. """ if format == "gadf": if hdu is None: hdu = IRF_MAP_HDU_SPECIFICATION[cls.tag] irf_map = Map.from_hdulist(hdulist, hdu=hdu, hdu_bands=hdu_bands, format=format) if exposure_hdu is None: exposure_hdu = IRF_MAP_HDU_SPECIFICATION[cls.tag] + "_exposure" if exposure_hdu in hdulist: exposure_map = Map.from_hdulist(hdulist, hdu=exposure_hdu, hdu_bands=exposure_hdu_bands, format=format) else: exposure_map = None elif format == "gtpsf": rad_axis = MapAxis.from_table_hdu(hdulist["THETA"], format=format) table = Table.read(hdulist["PSF"]) energy_axis_true = MapAxis.from_table(table, format=format) geom_psf = RegionGeom.create(region=None, axes=[rad_axis, energy_axis_true]) psf_map = Map.from_geom(geom=geom_psf, data=table["Psf"].data, unit="sr-1") geom_exposure = geom_psf.squash("rad") exposure_map = Map.from_geom(geom=geom_exposure, data=table["Exposure"].data, unit="cm2 s") return cls(psf_map=psf_map, exposure_map=exposure_map) else: raise ValueError(f"Format {format} not supported") return cls(irf_map, exposure_map)