示例#1
0
def calc_counts(skydir, ltc, event_class, event_types,
                egy_bins, cth_bins, fn, npts=1):
    """Calculate the expected counts vs. true energy and incidence angle
    for a source with spectral parameterization ``fn``.

    Parameters
    ----------
    skydir : `~astropy.coordinate.SkyCoord`

    ltc : `~fermipy.irfs.LTCube`

    egy_bins : `~numpy.ndarray`
        Bin edges in observed energy in MeV.

    cth_bins : `~numpy.ndarray`
        Bin edges in cosine of the true incidence angle.

    npts : int
        Number of points by which to oversample each energy bin.
    """
    #npts = int(np.ceil(32. / bins_per_dec(egy_bins)))
    egy_bins = np.exp(utils.split_bin_edges(np.log(egy_bins), npts))
    exp = calc_exp(skydir, ltc, event_class, event_types,
                   egy_bins, cth_bins)
    dnde = fn.dnde(egy_bins)
    cnts = loglog_quad(egy_bins, exp * dnde[:, None], 0)
    cnts = sum_bins(cnts, 0, npts)
    return cnts
示例#2
0
def calc_exp(skydir, ltc, event_class, event_types,
             egy, cth_bins, npts=None):
    """Calculate the exposure on a 2D grid of energy and incidence angle.

    Parameters
    ----------
    npts : int    
        Number of points by which to sample the response in each
        incidence angle bin.  If None then npts will be automatically
        set such that incidence angle is sampled on intervals of <
        0.05 in Cos(Theta).

    Returns
    -------
    exp : `~numpy.ndarray`
        2D Array of exposures vs. energy and incidence angle.

    """

    if npts is None:
        npts = int(np.ceil(np.max(cth_bins[1:] - cth_bins[:-1]) / 0.025))

    exp = np.zeros((len(egy), len(cth_bins) - 1))
    cth_bins = utils.split_bin_edges(cth_bins, npts)
    cth = edge_to_center(cth_bins)
    ltw = ltc.get_skydir_lthist(skydir, cth_bins).reshape(-1, npts)
    for et in event_types:
        aeff = create_aeff(event_class, et, egy, cth)
        aeff = aeff.reshape(exp.shape + (npts,))
        exp += np.sum(aeff * ltw[np.newaxis, :, :], axis=-1)

    return exp
示例#3
0
def create_avg_rsp(rsp_fn, skydir, ltc, event_class, event_types, x,
                   egy, cth_bins, npts=None):
    """Calculate the weighted response function.
    """
    if npts is None:
        npts = int(np.ceil(np.max(cth_bins[1:] - cth_bins[:-1]) / 0.05))

    wrsp = np.zeros((len(x), len(egy), len(cth_bins) - 1))
    exps = np.zeros((len(egy), len(cth_bins) - 1))

    cth_bins = utils.split_bin_edges(cth_bins, npts)
    cth = edge_to_center(cth_bins)
    ltw = ltc.get_skydir_lthist(skydir, cth_bins)
    ltw = ltw.reshape(-1, npts)

    for et in event_types:
        rsp = rsp_fn(event_class, et, x, egy, cth)
        aeff = create_aeff(event_class, et, egy, cth)
        rsp = rsp.reshape(wrsp.shape + (npts,))
        aeff = aeff.reshape(exps.shape + (npts,))
        wrsp += np.sum(rsp * aeff[np.newaxis, :, :, :] *
                       ltw[np.newaxis, np.newaxis, :, :], axis=-1)
        exps += np.sum(aeff * ltw[np.newaxis, :, :], axis=-1)

    exps_inv = np.zeros_like(exps)
    exps_inv[exps > 0] = 1./exps[exps>0]        
    wrsp *= exps_inv[np.newaxis, :, :]
    return wrsp
示例#4
0
    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
示例#5
0
    def interp_bin(self, egy_bins, dtheta, scale_fn=None):
        """Evaluate the bin-averaged PSF model over the energy bins ``egy_bins``.

        Parameters
        ----------
        egy_bins : array_like
            Energy bin edges in MeV.

        dtheta : array_like
            Array of angular separations in degrees.

        scale_fn : callable        
            Function that evaluates the PSF scaling function.
            Argument is energy in MeV.
        """

        npts = 4
        egy_bins = np.exp(utils.split_bin_edges(np.log(egy_bins), npts))
        egy = np.exp(utils.edge_to_center(np.log(egy_bins)))
        log_energies = np.log10(egy)

        vals = self.interp(egy[None, :], dtheta[:, None],
                           scale_fn=scale_fn)
        wts = np.exp(self._wts_fn((log_energies,)))
        wts = wts.reshape((1,) + wts.shape)
        vals = np.sum(
            (vals * wts).reshape((vals.shape[0], int(vals.shape[1] / npts), npts)), axis=2)
        vals /= np.sum(wts.reshape(wts.shape[0],
                                   int(wts.shape[1] / npts), npts), axis=2)
        return vals
示例#6
0
def calc_exp(skydir, ltc, event_class, event_types, egy, cth_bins, npts=None):
    """Calculate the exposure on a 2D grid of energy and incidence angle.

    Parameters
    ----------
    npts : int    
        Number of points by which to sample the response in each
        incidence angle bin.  If None then npts will be automatically
        set such that incidence angle is sampled on intervals of <
        0.05 in Cos(Theta).

    Returns
    -------
    exp : `~numpy.ndarray`
        2D Array of exposures vs. energy and incidence angle.

    """

    if npts is None:
        npts = int(np.ceil(np.max(cth_bins[1:] - cth_bins[:-1]) / 0.025))

    exp = np.zeros((len(egy), len(cth_bins) - 1))
    cth_bins = utils.split_bin_edges(cth_bins, npts)
    cth = edge_to_center(cth_bins)
    ltw = ltc.get_skydir_lthist(skydir, cth_bins).reshape(-1, npts)
    for et in event_types:
        aeff = create_aeff(event_class, et, egy, cth)
        aeff = aeff.reshape(exp.shape + (npts, ))
        exp += np.sum(aeff * ltw[np.newaxis, :, :], axis=-1)

    return exp
示例#7
0
def calc_counts(skydir,
                ltc,
                event_class,
                event_types,
                egy_bins,
                cth_bins,
                fn,
                npts=1):
    """Calculate the expected counts vs. true energy and incidence angle
    for a source with spectral parameterization ``fn``.

    Parameters
    ----------
    skydir : `~astropy.coordinate.SkyCoord`

    ltc : `~fermipy.irfs.LTCube`

    egy_bins : `~numpy.ndarray`
        Bin edges in observed energy in MeV.

    cth_bins : `~numpy.ndarray`
        Bin edges in cosine of the true incidence angle.

    npts : int
        Number of points by which to oversample each energy bin.
    """
    #npts = int(np.ceil(32. / bins_per_dec(egy_bins)))
    egy_bins = np.exp(utils.split_bin_edges(np.log(egy_bins), npts))
    exp = calc_exp(skydir, ltc, event_class, event_types, egy_bins, cth_bins)
    dnde = fn.dnde(egy_bins)
    cnts = loglog_quad(egy_bins, exp * dnde[:, None], 0)
    cnts = sum_bins(cnts, 0, npts)
    return cnts
示例#8
0
def calc_counts_edisp(skydir, ltc, event_class, event_types,
                      egy_bins, cth_bins, fn, nbin=64, npts=1):
    """Calculate the expected counts vs. observed energy and true
    incidence angle for a source with spectral parameterization ``fn``.

    Parameters
    ----------
    skydir : `~astropy.coordinate.SkyCoord`

    ltc : `~fermipy.irfs.LTCube`

    egy_bins : `~numpy.ndarray`
        Bin edges in observed energy in MeV.

    cth_bins : `~numpy.ndarray`
        Bin edges in cosine of the true incidence angle.

    npts : int
        Number of points by which to oversample each energy bin.

    """
    #npts = int(np.ceil(32. / bins_per_dec(egy_bins)))

    # Split energy 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)
    drm = calc_drm(skydir, ltc, event_class, event_types,
                   egy_bins, cth_bins, nbin=nbin)
    cnts_etrue = calc_counts(skydir, ltc, event_class, event_types,
                             etrue_bins, cth_bins, fn)

    cnts = np.sum(cnts_etrue[None, :, :] * drm[:, :, :], axis=1)
    cnts = sum_bins(cnts, 0, npts)
    return cnts
示例#9
0
    def interp_bin(self, egy_bins, dtheta, scale_fn=None):
        """Evaluate the bin-averaged PSF model over the energy bins ``egy_bins``.

        Parameters
        ----------
        egy_bins : array_like
            Energy bin edges in MeV.

        dtheta : array_like
            Array of angular separations in degrees.

        scale_fn : callable        
            Function that evaluates the PSF scaling function.
            Argument is energy in MeV.
        """

        npts = 4
        egy_bins = np.exp(utils.split_bin_edges(np.log(egy_bins), npts))
        egy = np.exp(utils.edge_to_center(np.log(egy_bins)))
        log_energies = np.log10(egy)

        vals = self.interp(egy[None, :], dtheta[:, None], scale_fn=scale_fn)
        wts = np.exp(self._wts_fn((log_energies, )))
        wts = wts.reshape((1, ) + wts.shape)
        vals = np.sum((vals * wts).reshape(
            (vals.shape[0], int(vals.shape[1] / npts), npts)),
                      axis=2)
        vals /= np.sum(wts.reshape(wts.shape[0], int(wts.shape[1] / npts),
                                   npts),
                       axis=2)
        return vals
示例#10
0
文件: irfs.py 项目: sarabuson/fermipy
def create_avg_rsp(rsp_fn,
                   skydir,
                   ltc,
                   event_class,
                   event_types,
                   x,
                   egy,
                   cth_bins,
                   npts=None):

    if npts is None:
        npts = int(np.ceil(np.max(cth_bins[1:] - cth_bins[:-1]) / 0.05))

    wrsp = np.zeros((len(x), len(egy), len(cth_bins) - 1))
    exps = np.zeros((len(egy), len(cth_bins) - 1))

    cth_bins = utils.split_bin_edges(cth_bins, npts)
    cth = edge_to_center(cth_bins)
    ltw = ltc.get_skydir_lthist(skydir, cth_bins)
    ltw = ltw.reshape(-1, npts)

    for et in event_types:
        rsp = rsp_fn(event_class, et, x, egy, cth)
        aeff = create_aeff(event_class, et, egy, cth)
        rsp = rsp.reshape(wrsp.shape + (npts, ))
        aeff = aeff.reshape(exps.shape + (npts, ))
        wrsp += np.sum(rsp * aeff[np.newaxis, :, :, :] *
                       ltw[np.newaxis, np.newaxis, :, :],
                       axis=-1)
        exps += np.sum(aeff * ltw[np.newaxis, :, :], axis=-1)

    wrsp /= exps[np.newaxis, :, :]
    return wrsp
示例#11
0
文件: irfs.py 项目: NAH8/fermipy
def calc_counts_edisp(skydir, ltc, event_class, event_types,
                      egy_bins, cth_bins, fn, nbin=64, npts=1):
    """Calculate the expected counts vs. observed energy and true
    incidence angle for a source with spectral parameterization ``fn``.

    Parameters
    ----------
    skydir : `~astropy.coordinate.SkyCoord`

    ltc : `~fermipy.irfs.LTCube`

    egy_bins : `~numpy.ndarray`
        Bin edges in observed energy in MeV.

    cth_bins : `~numpy.ndarray`
        Bin edges in cosine of the true incidence angle.

    npts : int
        Number of points by which to oversample each energy bin.

    """
    #npts = int(np.ceil(32. / bins_per_dec(egy_bins)))
    
    # Split energy 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)
    drm = calc_drm(skydir, ltc, event_class, event_types,
                   egy_bins, cth_bins, nbin=nbin)
    cnts_etrue = calc_counts(skydir, ltc, event_class, event_types,
                             etrue_bins, cth_bins, fn)

    cnts = np.sum(cnts_etrue[None,:,:] * drm[:, :, :], axis=1)
    cnts = sum_bins(cnts,0,npts)
    return cnts
示例#12
0
    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
示例#13
0
def create_wtd_psf(skydir, ltc, event_class, event_types, dtheta,
                   egy_bins, cth_bins, fn, nbin=64, npts=1):
    """Create an exposure- and dispersion-weighted PSF model for a source
    with spectral parameterization ``fn``.  The calculation performed
    by this method accounts for the influence of energy dispersion on
    the PSF.

    Parameters
    ----------
    dtheta : `~numpy.ndarray`

    egy_bins : `~numpy.ndarray`
        Bin edges in observed energy.

    cth_bins : `~numpy.ndarray`
        Bin edges in cosine of the true incidence angle.

    nbin : int
        Number of bins per decade in true energy.

    npts : int
        Number of points by which to oversample each energy bin.

    """
    #npts = int(np.ceil(32. / 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)
    etrue = 10**utils.edge_to_center(np.log10(etrue_bins))

    psf = create_avg_psf(skydir, ltc, event_class, event_types, dtheta,
                         etrue, cth_bins)
    drm = calc_drm(skydir, ltc, event_class, event_types,
                   egy_bins, cth_bins, nbin=nbin)
    cnts = calc_counts(skydir, ltc, event_class, event_types,
                       etrue_bins, cth_bins, fn)

    wts = drm * cnts[None, :, :]
    wts_norm = np.sum(wts, axis=1)
    wts_norm[wts_norm == 0] = 1.0
    wts = wts / wts_norm[:, None, :]
    wpsf = np.sum(wts[None, :, :, :] * psf[:, None, :, :], axis=2)
    wts = np.sum(wts[None, :, :, :], axis=2)

    if npts > 1:
        shape = (wpsf.shape[0], int(wpsf.shape[1] / npts), npts, wpsf.shape[2])
        wpsf = np.sum((wpsf * wts).reshape(shape), axis=2)
        shape = (wts.shape[0], int(wts.shape[1] / npts), npts, wts.shape[2])
        wpsf = wpsf / np.sum(wts.reshape(shape), axis=2)

    return wpsf
示例#14
0
文件: irfs.py 项目: NAH8/fermipy
def create_wtd_psf(skydir, ltc, event_class, event_types, dtheta,
                   egy_bins, cth_bins, fn, nbin=64, npts=1):
    """Create an exposure- and dispersion-weighted PSF model for a source
    with spectral parameterization ``fn``.  The calculation performed
    by this method accounts for the influence of energy dispersion on
    the PSF.

    Parameters
    ----------
    dtheta : `~numpy.ndarray`

    egy_bins : `~numpy.ndarray`
        Bin edges in observed energy.

    cth_bins : `~numpy.ndarray`
        Bin edges in cosine of the true incidence angle.

    nbin : int
        Number of bins per decade in true energy.

    npts : int
        Number of points by which to oversample each energy bin.

    """
    #npts = int(np.ceil(32. / 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)
    etrue = 10**utils.edge_to_center(np.log10(etrue_bins))

    psf = create_avg_psf(skydir, ltc, event_class, event_types, dtheta,
                         etrue, cth_bins)
    drm = calc_drm(skydir, ltc, event_class, event_types,
                   egy_bins, cth_bins, nbin=nbin)
    cnts = calc_counts(skydir, ltc, event_class, event_types,
                       etrue_bins, cth_bins, fn)
    
    wts = drm * cnts[None, :, :]
    wts_norm = np.sum(wts,axis=1)
    wts_norm[wts_norm == 0] = 1.0    
    wts = wts / wts_norm[:, None, :]
    wpsf = np.sum(wts[None, :, :, :] * psf[:, None, :, :], axis=2)
    wts = np.sum(wts[None, :, :, :],axis=2)
    
    if npts > 1:
        shape = (wpsf.shape[0], int(wpsf.shape[1] / npts), npts, wpsf.shape[2])
        wpsf = np.sum((wpsf * wts).reshape(shape), axis=2)
        shape = (wts.shape[0], int(wts.shape[1] / npts), npts, wts.shape[2])
        wpsf = wpsf / np.sum(wts.reshape(shape), axis=2)

    return wpsf
示例#15
0
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
示例#16
0
文件: irfs.py 项目: NAH8/fermipy
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