def get_skydir_lthist(self, skydir, cth_bins): """Get the livetime distribution (observing profile) for a given sky direction with binning in incidence angle defined by ``cth_bins``. Parameters ---------- skydir : `~astropy.coordinates.SkyCoord` Sky coordinate for which the observing profile will be computed. cth_bins : `~numpy.ndarray` Bin edges in cosine of the incidence angle. """ ra = skydir.ra.deg dec = skydir.dec.deg npts = 1 bins = utils.split_bin_edges(cth_bins, npts) center = edge_to_center(bins) width = edge_to_width(bins) ipix = hp.ang2pix(self.hpx.nside, np.pi / 2. - np.radians(dec), np.radians(ra), nest=self.hpx.nest) lt = np.histogram(self._cth_center, weights=self.data[:, ipix], bins=bins)[0] lt = np.sum(lt.reshape(-1, npts), axis=1) return lt
def create_empty(cls, tstart, tstop, fill=0.0, nside=64): """Create an empty livetime cube.""" cth_edges = np.linspace(0, 1.0, 41) domega = utils.edge_to_width(cth_edges) * 2.0 * np.pi hpx = HPX(nside, True, 'CEL', ebins=cth_edges) data = np.ones((len(cth_edges) - 1, hpx.npix)) * fill return cls(data, hpx, cth_edges, tstart=tstart, tstop=tstop)
def get_skydir_lthist(self, skydir, cth_bins): """Get the livetime distribution (observing profile) for a given sky direction with binning in incidence angle defined by ``cth_bins``. Parameters ---------- skydir : `~astropy.coordinates.SkyCoord` Sky coordinate for which the observing profile will be computed. cth_bins : `~numpy.ndarray` Bin edges in cosine of the incidence angle. """ ra = skydir.ra.deg dec = skydir.dec.deg bins = np.linspace(cth_bins[0], cth_bins[-1], (len(cth_bins) - 1) * 4 + 1) center = edge_to_center(bins) width = edge_to_width(bins) ipix = hp.ang2pix(self.hpx.nside, np.pi / 2. - np.radians(dec), np.radians(ra), nest=self.hpx.nest) lt = np.interp(center, self._cth_center, self.data[:, ipix] / self._cth_width) * width lt = np.sum(lt.reshape(-1, 4), axis=1) return lt
def compute_ps_counts(ebins, exp, psf, bkg, fn, egy_dim=0, spatial_model='PointSource', spatial_size=1E-3): """Calculate the observed signal and background counts given models for the exposure, background intensity, PSF, and source flux. Parameters ---------- ebins : `~numpy.ndarray` Array of energy bin edges. exp : `~numpy.ndarray` Model for exposure. psf : `~fermipy.irfs.PSFModel` Model for average PSF. bkg : `~numpy.ndarray` Array of background intensities. fn : `~fermipy.spectrum.SpectralFunction` egy_dim : int Index of energy dimension in ``bkg`` and ``exp`` arrays. """ ewidth = utils.edge_to_width(ebins) ectr = np.exp(utils.edge_to_center(np.log(ebins))) r68 = psf.containment_angle(ectr, fraction=0.68) if spatial_model != 'PointSource': r68[r68 < spatial_size] = spatial_size # * np.ones((len(ectr), 31)) theta_edges = np.linspace(0.0, 3.0, 31)[np.newaxis, :] theta_edges = theta_edges * r68[:, np.newaxis] theta = 0.5 * (theta_edges[:, :-1] + theta_edges[:, 1:]) domega = np.pi * (theta_edges[:, 1:]**2 - theta_edges[:, :-1]**2) if spatial_model == 'PointSource': sig_pdf = domega * psf.interp(ectr[:, np.newaxis], theta) elif spatial_model == 'RadialGaussian': sig_pdf = domega * utils.convolve2d_gauss(lambda t: psf.interp(ectr[:, np.newaxis, np.newaxis], t), theta, spatial_size / 1.5095921854516636, nstep=2000) elif spatial_model == 'RadialDisk': sig_pdf = domega * utils.convolve2d_disk(lambda t: psf.interp(ectr[:, np.newaxis, np.newaxis], t), theta, spatial_size / 0.8246211251235321) else: raise ValueError('Invalid spatial model: {}'.format(spatial_model)) sig_pdf *= (np.pi / 180.)**2 sig_flux = fn.flux(ebins[:-1], ebins[1:]) # Background and signal counts bkgc = bkg[..., np.newaxis] * domega * exp[..., np.newaxis] * \ ewidth[..., np.newaxis] * (np.pi / 180.)**2 sigc = sig_pdf * sig_flux[..., np.newaxis] * exp[..., np.newaxis] return sigc, bkgc
def __init__(self, data, hpx, cth_edges, tstart=None, tstop=None): HpxMap.__init__(self, data, hpx) self._cth_edges = cth_edges self._cth_center = edge_to_center(self._cth_edges) self._cth_width = edge_to_width(self._cth_edges) self._domega = (self._cth_edges[1:] - self._cth_edges[:-1]) * 2 * np.pi self._tstart = tstart self._tstop = tstop
def plot_projection(self,iaxis,**kwargs): data = kwargs.pop('data',self._data) noerror = kwargs.pop('noerror',False) axes = wcs_to_axes(self._wcs,self._data.shape[::-1]) x = edge_to_center(axes[iaxis]) w = edge_to_width(axes[iaxis]) c = self.get_data_projection(data,axes,iaxis,erange=self._erange) if noerror: plt.errorbar(x,c,**kwargs) else: plt.errorbar(x,c,yerr=c**0.5,xerr=w/2.,**kwargs)
def calc_drm(skydir, ltc, event_class, event_types, egy_bins, cth_bins, nbin=64): """Calculate the detector response matrix.""" npts = int(np.ceil(128. / bins_per_dec(egy_bins))) egy_bins = np.exp(utils.split_bin_edges(np.log(egy_bins), npts)) etrue_bins = 10**np.linspace(1.0, 6.5, nbin * 5.5 + 1) egy = 10**utils.edge_to_center(np.log10(egy_bins)) egy_width = utils.edge_to_width(egy_bins) etrue = 10**utils.edge_to_center(np.log10(etrue_bins)) edisp = create_avg_edisp(skydir, ltc, event_class, event_types, egy, etrue, cth_bins) edisp = edisp * egy_width[:, None, None] edisp = sum_bins(edisp, 0, npts) return edisp
def calc_drm(skydir, ltc, event_class, event_types, egy_bins, cth_bins, nbin=64): """Calculate the detector response matrix.""" npts = int(np.ceil(128. / bins_per_dec(egy_bins))) egy_bins = np.exp(utils.split_bin_edges(np.log(egy_bins), npts)) etrue_bins = 10**np.linspace(1.0, 6.5, nbin * 5.5 + 1) egy = 10**utils.edge_to_center(np.log10(egy_bins)) egy_width = utils.edge_to_width(egy_bins) etrue = 10**utils.edge_to_center(np.log10(etrue_bins)) edisp = create_avg_edisp(skydir, ltc, event_class, event_types, egy, etrue, cth_bins) edisp = edisp * egy_width[:, None, None] edisp = sum_bins(edisp,0,npts) return edisp
def get_src_lthist(self,skydir,cth_edges): ra = skydir.ra.deg dec = skydir.dec.deg edges = np.linspace(cth_edges[0],cth_edges[-1],(len(cth_edges)-1)*4+1) center = edge_to_center(edges) width = edge_to_width(edges) ipix = hp.ang2pix(64,np.pi/2. - np.radians(dec), np.radians(ra),nest=True) lt = np.interp(center,self._cth_center, self._ltmap[ipix,::-1]/self._cth_width)*width lt = np.sum(lt.reshape(-1,4),axis=1) return lt
def load_ltfile(self,ltfile): hdulist = pyfits.open(ltfile) if self._ltmap is None: self._ltmap = hdulist[1].data.field(0) self._tstart = hdulist[0].header['TSTART'] self._tstop = hdulist[0].header['TSTOP'] else: self._ltmap += hdulist[1].data.field(0) self._tstart = min(self._tstart,hdulist[0].header['TSTART']) self._tstop = max(self._tstop,hdulist[0].header['TSTOP']) cth_edges = np.array(hdulist[3].data.field(0)) cth_edges = np.concatenate(([1],cth_edges)) self._cth_edges = cth_edges[::-1] self._cth_center = edge_to_center(self._cth_edges) self._cth_width = edge_to_width(self._cth_edges)
def compute_ps_counts(ebins, exp, psf, bkg, fn, egy_dim=0): """Calculate the observed signal and background counts given models for the exposure, background intensity, PSF, and source flux. Parameters ---------- ebins : `~numpy.ndarray` Array of energy bin edges. exp : `~numpy.ndarray` Model for exposure. psf : `~fermipy.irfs.PSFModel` Model for average PSF. bkg : `~numpy.ndarray` Array of background intensities. fn : `~fermipy.spectrum.SpectralFunction` egy_dim : int Index of energy dimension in ``bkg`` and ``exp`` arrays. """ ewidth = utils.edge_to_width(ebins) ectr = np.exp(utils.edge_to_center(np.log(ebins))) theta_edges = np.linspace(0.0, 3.0, 31)[ np.newaxis, :] * np.ones((len(ectr), 31)) theta_edges *= psf.containment_angle(ectr, fraction=0.68)[:, np.newaxis] theta = 0.5 * (theta_edges[:, :-1] + theta_edges[:, 1:]) domega = np.pi * (theta_edges[:, 1:]**2 - theta_edges[:, :-1]**2) sig_pdf = domega * \ psf.interp(ectr[:, np.newaxis], theta) * (np.pi / 180.)**2 sig_flux = fn.flux(ebins[:-1], ebins[1:]) # Background and signal counts bkgc = bkg[:, np.newaxis] * domega * exp[:, np.newaxis] * \ ewidth[:, np.newaxis] * (np.pi / 180.)**2 sigc = sig_pdf * sig_flux[:, np.newaxis] * exp[:, np.newaxis] return sigc, bkgc
def __init__(self, data, hpx, cth_edges, **kwargs): HpxMap.__init__(self, data, hpx) self._cth_edges = cth_edges self._cth_center = edge_to_center(self._cth_edges) self._cth_width = edge_to_width(self._cth_edges) self._domega = (self._cth_edges[1:] - self._cth_edges[:-1]) * 2 * np.pi self._tstart = kwargs.get('tstart', None) self._tstop = kwargs.get('tstop', None) self._zmin = kwargs.get('zmin', 0.0) self._zmax = kwargs.get('zmax', 180.0) self._tab_gti = kwargs.get('tab_gti', None) self._header = kwargs.get('header', None) self._data_wt = kwargs.get('data_wt', None) if self._data_wt is None: self._data_wt = np.zeros_like(self.data) if self._tab_gti is None: cols = [Column(name='START', dtype='f8', unit='s'), Column(name='STOP', dtype='f8', unit='s')] self._tab_gti = Table(cols)
def compute_ps_counts(ebins, exp, psf, bkg, fn, egy_dim=0, spatial_model='PointSource', spatial_size=1E-3): """Calculate the observed signal and background counts given models for the exposure, background intensity, PSF, and source flux. Parameters ---------- ebins : `~numpy.ndarray` Array of energy bin edges. exp : `~numpy.ndarray` Model for exposure. psf : `~fermipy.irfs.PSFModel` Model for average PSF. bkg : `~numpy.ndarray` Array of background intensities. fn : `~fermipy.spectrum.SpectralFunction` egy_dim : int Index of energy dimension in ``bkg`` and ``exp`` arrays. """ ewidth = utils.edge_to_width(ebins) ectr = np.exp(utils.edge_to_center(np.log(ebins))) r68 = psf.containment_angle(ectr, fraction=0.68) if spatial_model != 'PointSource': r68[r68 < spatial_size] = spatial_size # * np.ones((len(ectr), 31)) theta_edges = np.linspace(0.0, 3.0, 31)[np.newaxis, :] theta_edges = theta_edges * r68[:, np.newaxis] theta = 0.5 * (theta_edges[:, :-1] + theta_edges[:, 1:]) domega = np.pi * (theta_edges[:, 1:]**2 - theta_edges[:, :-1]**2) if spatial_model == 'PointSource': sig_pdf = domega * psf.interp(ectr[:, np.newaxis], theta) elif spatial_model == 'RadialGaussian': sig_pdf = domega * utils.convolve2d_gauss( lambda t: psf.interp(ectr[:, np.newaxis, np.newaxis], t), theta, spatial_size / 1.5095921854516636, nstep=2000) elif spatial_model == 'RadialDisk': sig_pdf = domega * utils.convolve2d_disk( lambda t: psf.interp(ectr[:, np.newaxis, np.newaxis], t), theta, spatial_size / 0.8246211251235321) else: raise ValueError('Invalid spatial model: {}'.format(spatial_model)) sig_pdf *= (np.pi / 180.)**2 sig_flux = fn.flux(ebins[:-1], ebins[1:]) # Background and signal counts bkgc = bkg[..., np.newaxis] * domega * exp[..., np.newaxis] * \ ewidth[..., np.newaxis] * (np.pi / 180.)**2 sigc = sig_pdf * sig_flux[..., np.newaxis] * exp[..., np.newaxis] return sigc, bkgc