示例#1
0
文件: residmap.py 项目: tuoyl/fermipy
    def _make_residual_map_hpx(self, prefix, **kwargs):
        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        exclude = kwargs.setdefault('exclude', None)
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_weights = kwargs.setdefault('use_weights', False)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None else
                              self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None else
                              self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        kernel = None

        gauss_width = np.radians(0.3)

        hpxsky = self.counts_map().geom.to_image()

        mmst = HpxNDMap.from_geom(hpxsky)
        cmst = HpxNDMap.from_geom(hpxsky)
        emst = HpxNDMap.from_geom(hpxsky)
        ts = HpxNDMap.from_geom(hpxsky)
        sigma = HpxNDMap.from_geom(hpxsky)
        excess = HpxNDMap.from_geom(hpxsky)

        for i, c in enumerate(self.components):

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            cc = c.counts_map()
            mc = c.model_counts_map(exclude=exclude)
            ec = HpxNDMap(cc.geom, cc.data - mc.data)

            if use_weights:
                wmap = c.weight_map()
                mask = wmap.sum_over_axes()
                mask.data = np.where(mask.data > 0., 1., 0.)
            else:
                wmap = None
                mask = None

            sigmas = gauss_width * np.ones(cc.data.shape[0])
            ccs = convolve_map_hpx_gauss(cc,
                                         sigmas,
                                         imin=imin,
                                         imax=imax,
                                         wmap=wmap)
            mcs = convolve_map_hpx_gauss(mc,
                                         sigmas,
                                         imin=imin,
                                         imax=imax,
                                         wmap=wmap)
            ecs = convolve_map_hpx_gauss(ec,
                                         sigmas,
                                         imin=imin,
                                         imax=imax,
                                         wmap=wmap)

            cms = ccs.sum_over_axes()
            mms = mcs.sum_over_axes()
            ems = ecs.sum_over_axes()

            if cms.geom.order != hpxsky.order:
                cms = cms.to_ud_graded(hpxsky.nside, preserve_counts=True)
                mms = mms.to_ud_graded(hpxsky.nside, preserve_counts=True)
                ems = ems.to_ud_graded(hpxsky.nside, preserve_counts=True)

            cmst.data += cms.data
            mmst.data += mms.data
            emst.data += ems.data

        ts.data = 2.0 * (poisson_lnl(cmst.data, cmst.data) -
                         poisson_lnl(cmst.data, mmst.data))
        sigma.data = np.sqrt(ts.data)
        sigma.data[emst.data < 0] *= -1
        modelname = 'gauss_0p3'

        o = {
            'name': utils.join_strings([prefix, modelname]),
            'projtype': 'HPX',
            'file': None,
            'sigma': sigma,
            'model': mmst,
            'data': cmst,
            'excess': emst,
            'mask': mask,
            'config': kwargs
        }

        return o
示例#2
0
    def _make_tsmap_fast(self, prefix, **kwargs):
        """
        Make a TS map from a GTAnalysis instance.  This is a
        simplified implementation optimized for speed that only fits
        for the source normalization (all background components are
        kept fixed). The spectral/spatial characteristics of the test
        source can be defined with the src_dict argument.  By default
        this method will generate a TS map for a point source with an
        index=2.0 power-law spectrum.

        Parameters
        ----------
        model : dict or `~fermipy.roi_model.Source`
           Dictionary or Source object defining the properties of the
           test source that will be used in the scan.

        """
        loglevel = kwargs.get('loglevel', self.loglevel)

        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        src_dict = {} if src_dict is None else src_dict

        multithread = kwargs.setdefault('multithread', False)
        threshold = kwargs.setdefault('threshold', 1E-2)
        max_kernel_radius = kwargs.get('max_kernel_radius')
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_pylike = kwargs.setdefault('use_pylike', True)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None else
                              self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None else
                              self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round(
            (self.npix - 1.0) / 2.), np.round((self.npix - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        map_geom = self._geom.to_image()
        frame = coordsys_to_frame(map_geom.coordsys)
        skydir = SkyCoord(*map_geom.pix_to_coord((cpix[0], cpix[1])),
                          frame=frame,
                          unit='deg')
        skydir = skydir.transform_to('icrs')

        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)
        src_dict.setdefault('Prefactor', 1E-13)

        counts = []
        bkg = []
        model = []
        c0_map = []
        eslices = []
        enumbins = []
        model_npred = 0
        for c in self.components:

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            eslice = slice(imin, imax)
            bm = c.model_counts_map(
                exclude=kwargs['exclude']).data.astype('float')[eslice, ...]
            cm = c.counts_map().data.astype('float')[eslice, ...]

            bkg += [bm]
            counts += [cm]
            c0_map += [cash(cm, bm)]
            eslices += [eslice]
            enumbins += [cm.shape[0]]

        self.add_source('tsmap_testsource',
                        src_dict,
                        free=True,
                        init_source=False,
                        use_single_psf=True,
                        use_pylike=use_pylike,
                        loglevel=logging.DEBUG)
        src = self.roi['tsmap_testsource']
        # self.logger.info(str(src_dict))
        modelname = utils.create_model_name(src)
        for c, eslice in zip(self.components, eslices):
            mm = c.model_counts_map('tsmap_testsource').data.astype('float')[
                eslice, ...]
            model_npred += np.sum(mm)
            model += [mm]

        self.delete_source('tsmap_testsource', loglevel=logging.DEBUG)

        for i, mm in enumerate(model):

            dpix = 3
            for j in range(mm.shape[0]):

                ix, iy = np.unravel_index(np.argmax(mm[j, ...]), mm[j,
                                                                    ...].shape)

                mx = mm[j, ix, :] > mm[j, ix, iy] * threshold
                my = mm[j, :, iy] > mm[j, ix, iy] * threshold
                dpix = max(dpix, np.round(np.sum(mx) / 2.))
                dpix = max(dpix, np.round(np.sum(my) / 2.))

            if max_kernel_radius is not None and \
                    dpix > int(max_kernel_radius / self.components[i].binsz):
                dpix = int(max_kernel_radius / self.components[i].binsz)

            xslice = slice(max(int(xpix - dpix), 0),
                           min(int(xpix + dpix + 1), self.npix))
            model[i] = model[i][:, xslice, xslice]

        ts_values = np.zeros((self.npix, self.npix))
        amp_values = np.zeros((self.npix, self.npix))

        wrap = functools.partial(_ts_value_newton,
                                 counts=counts,
                                 bkg=bkg,
                                 model=model,
                                 C_0_map=c0_map)

        if kwargs['map_skydir'] is not None:

            map_offset = wcs_utils.skydir_to_pix(kwargs['map_skydir'],
                                                 map_geom.wcs)

            map_delta = 0.5 * kwargs['map_size'] / self.components[0].binsz
            xmin = max(int(np.ceil(map_offset[1] - map_delta)), 0)
            xmax = min(int(np.floor(map_offset[1] + map_delta)) + 1, self.npix)
            ymin = max(int(np.ceil(map_offset[0] - map_delta)), 0)
            ymax = min(int(np.floor(map_offset[0] + map_delta)) + 1, self.npix)

            xslice = slice(xmin, xmax)
            yslice = slice(ymin, ymax)
            xyrange = [range(xmin, xmax), range(ymin, ymax)]

            wcs = map_geom.wcs.deepcopy()
            npix = (ymax - ymin, xmax - xmin)
            crpix = (map_geom._crpix[0] - ymin, map_geom._crpix[1] - xmin)
            wcs.wcs.crpix[0] -= ymin
            wcs.wcs.crpix[1] -= xmin

            # FIXME: We should implement this with a proper cutout method
            map_geom = WcsGeom(wcs, npix, crpix=crpix)
        else:
            xyrange = [range(self.npix), range(self.npix)]
            xslice = slice(0, self.npix)
            yslice = slice(0, self.npix)

        positions = []
        for i, j in itertools.product(xyrange[0], xyrange[1]):
            p = [[k // 2, i, j] for k in enumbins]
            positions += [p]

        self.logger.log(loglevel, 'Fitting test source.')
        if multithread:
            pool = Pool()
            results = pool.map(wrap, positions)
            pool.close()
            pool.join()
        else:
            results = map(wrap, positions)

        for i, r in enumerate(results):
            ix = positions[i][0][1]
            iy = positions[i][0][2]
            ts_values[ix, iy] = r[0]
            amp_values[ix, iy] = r[1]

        ts_values = ts_values[xslice, yslice]
        amp_values = amp_values[xslice, yslice]

        ts_map = WcsNDMap(map_geom, ts_values)
        sqrt_ts_map = WcsNDMap(map_geom, ts_values**0.5)
        npred_map = WcsNDMap(map_geom, amp_values * model_npred)
        amp_map = WcsNDMap(map_geom, amp_values * src.get_norm())

        o = {
            'name': utils.join_strings([prefix, modelname]),
            'src_dict': copy.deepcopy(src_dict),
            'file': None,
            'ts': ts_map,
            'sqrt_ts': sqrt_ts_map,
            'npred': npred_map,
            'amplitude': amp_map,
            'loglike': -self.like(),
            'config': kwargs
        }

        return o
示例#3
0
文件: residmap.py 项目: tuoyl/fermipy
    def _make_residual_map_wcs(self, prefix, **kwargs):
        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        exclude = kwargs.setdefault('exclude', None)
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_weights = kwargs.setdefault('use_weights', False)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None else
                              self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None else
                              self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round(
            (self.npix[0] - 1.0) / 2.), np.round((self.npix[1] - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        geom = self.geom.to_image()
        skywcs = self.geom.wcs
        skydir = wcs_utils.pix_to_skydir(cpix[0], cpix[1], skywcs)

        if src_dict is None:
            src_dict = {}
        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)

        kernel = None

        if src_dict['SpatialModel'] == 'Gaussian':
            kernel = utils.make_gaussian_kernel(src_dict['SpatialWidth'],
                                                cdelt=self.binsz,
                                                npix=101)
            kernel /= np.sum(kernel)
            cpix = [50, 50]

        self.add_source('residmap_testsource',
                        src_dict,
                        free=True,
                        init_source=False,
                        save_source_maps=False)
        src = self.roi.get_source_by_name('residmap_testsource')

        modelname = utils.create_model_name(src)

        mmst = np.zeros(self.npix[::-1])
        cmst = np.zeros(self.npix[::-1])
        emst = np.zeros(self.npix[::-1])

        sm = get_source_kernel(self, 'residmap_testsource', kernel)
        ts = np.zeros(self.npix[::-1])
        sigma = np.zeros(self.npix[::-1])
        excess = np.zeros(self.npix[::-1])

        self.delete_source('residmap_testsource')

        for i, c in enumerate(self.components):

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            mc = c.model_counts_map(exclude=exclude).data.astype('float')
            cc = c.counts_map().data.astype('float')
            ec = np.ones(mc.shape)

            if use_weights:
                wmap = c.weight_map().data
                mask = np.where(wmap > 0, 1., 0.)
            else:
                wmap = None
                mask = None

            ccs = convolve_map(cc,
                               sm[i],
                               cpix,
                               imin=imin,
                               imax=imax,
                               wmap=wmap)
            mcs = convolve_map(mc,
                               sm[i],
                               cpix,
                               imin=imin,
                               imax=imax,
                               wmap=wmap)
            ecs = convolve_map(ec,
                               sm[i],
                               cpix,
                               imin=imin,
                               imax=imax,
                               wmap=wmap)

            cms = np.sum(ccs, axis=0)
            mms = np.sum(mcs, axis=0)
            ems = np.sum(ecs, axis=0)

            cmst += cms
            mmst += mms
            emst += ems

            # cts = 2.0 * (poisson_lnl(cms, cms) - poisson_lnl(cms, mms))
            excess += cms - mms

        ts = 2.0 * (poisson_lnl(cmst, cmst) - poisson_lnl(cmst, mmst))
        sigma = np.sqrt(ts)
        sigma[excess < 0] *= -1
        emst /= np.max(emst)

        sigma_map = WcsNDMap(geom, sigma)
        model_map = WcsNDMap(geom, mmst / emst)
        data_map = WcsNDMap(geom, cmst / emst)
        excess_map = WcsNDMap(geom, excess / emst)

        o = {
            'name': utils.join_strings([prefix, modelname]),
            'projtype': 'WCS',
            'file': None,
            'sigma': sigma_map,
            'model': model_map,
            'data': data_map,
            'excess': excess_map,
            'mask': mask,
            'config': kwargs
        }

        return o
示例#4
0
    def _make_residual_map_hpx(self, prefix, **kwargs):
        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        exclude = kwargs.setdefault('exclude', None)
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_weights = kwargs.setdefault('use_weights', False)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None
                              else self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None
                              else self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        kernel = None

        gauss_width = np.radians(0.3)

        hpxsky = self.counts_map().geom.to_image()

        mmst = HpxNDMap.from_geom(hpxsky)
        cmst = HpxNDMap.from_geom(hpxsky)
        emst = HpxNDMap.from_geom(hpxsky)
        ts = HpxNDMap.from_geom(hpxsky)
        sigma = HpxNDMap.from_geom(hpxsky)
        excess = HpxNDMap.from_geom(hpxsky)

        for i, c in enumerate(self.components):

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            cc = c.counts_map()
            mc = c.model_counts_map(exclude=exclude)
            ec = HpxNDMap(cc.geom, cc.data - mc.data)

            if use_weights:
                wmap = c.weight_map()
                mask = wmap.sum_over_axes()
                mask.data = np.where(mask.data > 0., 1., 0.)
            else:
                wmap = None
                mask = None

            sigmas = gauss_width * np.ones(cc.data.shape[0])
            ccs = convolve_map_hpx_gauss(
                cc, sigmas, imin=imin, imax=imax, wmap=wmap)
            mcs = convolve_map_hpx_gauss(
                mc, sigmas, imin=imin, imax=imax, wmap=wmap)
            ecs = convolve_map_hpx_gauss(
                ec, sigmas, imin=imin, imax=imax, wmap=wmap)

            cms = ccs.sum_over_axes()
            mms = mcs.sum_over_axes()
            ems = ecs.sum_over_axes()

            if cms.geom.order != hpxsky.order:
                cms = cms.to_ud_graded(hpxsky.nside, preserve_counts=True)
                mms = mms.to_ud_graded(hpxsky.nside, preserve_counts=True)
                ems = ems.to_ud_graded(hpxsky.nside, preserve_counts=True)

            cmst.data += cms.data
            mmst.data += mms.data
            emst.data += ems.data

        ts.data = 2.0 * (poisson_lnl(cmst.data, cmst.data) -
                         poisson_lnl(cmst.data, mmst.data))
        sigma.data = np.sqrt(ts.data)
        sigma.data[emst.data < 0] *= -1
        modelname = 'gauss_0p3'

        o = {'name': utils.join_strings([prefix, modelname]),
             'projtype': 'HPX',
             'file': None,
             'sigma': sigma,
             'model': mmst,
             'data': cmst,
             'excess': emst,
             'mask': mask,
             'config': kwargs}

        return o
示例#5
0
    def _make_residual_map_wcs(self, prefix, **kwargs):
        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        exclude = kwargs.setdefault('exclude', None)
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_weights = kwargs.setdefault('use_weights', False)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None
                              else self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None
                              else self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round((self.npix - 1.0) / 2.),
                      np.round((self.npix - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        geom = self.geom.to_image()
        skywcs = self.geom.wcs
        skydir = wcs_utils.pix_to_skydir(cpix[0], cpix[1], skywcs)

        if src_dict is None:
            src_dict = {}
        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)

        kernel = None

        if src_dict['SpatialModel'] == 'Gaussian':
            kernel = utils.make_gaussian_kernel(src_dict['SpatialWidth'],
                                                cdelt=self.components[0].binsz,
                                                npix=101)
            kernel /= np.sum(kernel)
            cpix = [50, 50]

        self.add_source('residmap_testsource', src_dict, free=True,
                        init_source=False, save_source_maps=False)
        src = self.roi.get_source_by_name('residmap_testsource')

        modelname = utils.create_model_name(src)
        npix = self.components[0].npix

        mmst = np.zeros((npix, npix))
        cmst = np.zeros((npix, npix))
        emst = np.zeros((npix, npix))

        sm = get_source_kernel(self, 'residmap_testsource', kernel)
        ts = np.zeros((npix, npix))
        sigma = np.zeros((npix, npix))
        excess = np.zeros((npix, npix))

        self.delete_source('residmap_testsource')

        for i, c in enumerate(self.components):

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            mc = c.model_counts_map(exclude=exclude).data.astype('float')
            cc = c.counts_map().data.astype('float')
            ec = np.ones(mc.shape)

            if use_weights:
                wmap = c.weight_map().data
                mask = np.where(wmap > 0, 1., 0.)
            else:
                wmap = None
                mask = None

            ccs = convolve_map(
                cc, sm[i], cpix, imin=imin, imax=imax, wmap=wmap)
            mcs = convolve_map(
                mc, sm[i], cpix, imin=imin, imax=imax, wmap=wmap)
            ecs = convolve_map(
                ec, sm[i], cpix, imin=imin, imax=imax, wmap=wmap)

            cms = np.sum(ccs, axis=0)
            mms = np.sum(mcs, axis=0)
            ems = np.sum(ecs, axis=0)

            cmst += cms
            mmst += mms
            emst += ems

            # cts = 2.0 * (poisson_lnl(cms, cms) - poisson_lnl(cms, mms))
            excess += cms - mms

        ts = 2.0 * (poisson_lnl(cmst, cmst) - poisson_lnl(cmst, mmst))
        sigma = np.sqrt(ts)
        sigma[excess < 0] *= -1
        emst /= np.max(emst)

        sigma_map = WcsNDMap(geom, sigma)
        model_map = WcsNDMap(geom, mmst / emst)
        data_map = WcsNDMap(geom, cmst / emst)
        excess_map = WcsNDMap(geom, excess / emst)

        o = {'name': utils.join_strings([prefix, modelname]),
             'projtype': 'WCS',
             'file': None,
             'sigma': sigma_map,
             'model': model_map,
             'data': data_map,
             'excess': excess_map,
             'mask': mask,
             'config': kwargs}

        return o
示例#6
0
    def _make_tsmap_fast(self, prefix, **kwargs):
        """
        Make a TS map from a GTAnalysis instance.  This is a
        simplified implementation optimized for speed that only fits
        for the source normalization (all background components are
        kept fixed). The spectral/spatial characteristics of the test
        source can be defined with the src_dict argument.  By default
        this method will generate a TS map for a point source with an
        index=2.0 power-law spectrum.

        Parameters
        ----------
        model : dict or `~fermipy.roi_model.Source`
           Dictionary or Source object defining the properties of the
           test source that will be used in the scan.

        """
        loglevel = kwargs.get('loglevel', self.loglevel)

        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        src_dict = {} if src_dict is None else src_dict

        multithread = kwargs.setdefault('multithread', False)
        threshold = kwargs.setdefault('threshold', 1E-2)
        max_kernel_radius = kwargs.get('max_kernel_radius')
        loge_bounds = kwargs.setdefault('loge_bounds', None)
        use_pylike = kwargs.setdefault('use_pylike', True)

        if loge_bounds:
            if len(loge_bounds) != 2:
                raise Exception('Wrong size of loge_bounds array.')
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None
                              else self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None
                              else self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round((self.npix - 1.0) / 2.),
                      np.round((self.npix - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        map_geom = self._geom.to_image()
        frame = coordsys_to_frame(map_geom.coordsys)
        skydir = SkyCoord(*map_geom.pix_to_coord((cpix[0], cpix[1])),
                          frame=frame, unit='deg')
        skydir = skydir.transform_to('icrs')

        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)
        src_dict.setdefault('Prefactor', 1E-13)

        counts = []
        bkg = []
        model = []
        c0_map = []
        eslices = []
        enumbins = []
        model_npred = 0
        for c in self.components:

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            eslice = slice(imin, imax)
            bm = c.model_counts_map(exclude=kwargs['exclude']).data.astype('float')[
                eslice, ...]
            cm = c.counts_map().data.astype('float')[eslice, ...]

            bkg += [bm]
            counts += [cm]
            c0_map += [cash(cm, bm)]
            eslices += [eslice]
            enumbins += [cm.shape[0]]

        self.add_source('tsmap_testsource', src_dict, free=True,
                        init_source=False, use_single_psf=True,
                        use_pylike=use_pylike,
                        loglevel=logging.DEBUG)
        src = self.roi['tsmap_testsource']
        # self.logger.info(str(src_dict))
        modelname = utils.create_model_name(src)
        for c, eslice in zip(self.components, eslices):
            mm = c.model_counts_map('tsmap_testsource').data.astype('float')[
                eslice, ...]
            model_npred += np.sum(mm)
            model += [mm]

        self.delete_source('tsmap_testsource', loglevel=logging.DEBUG)

        for i, mm in enumerate(model):

            dpix = 3
            for j in range(mm.shape[0]):

                ix, iy = np.unravel_index(
                    np.argmax(mm[j, ...]), mm[j, ...].shape)

                mx = mm[j, ix, :] > mm[j, ix, iy] * threshold
                my = mm[j, :, iy] > mm[j, ix, iy] * threshold
                dpix = max(dpix, np.round(np.sum(mx) / 2.))
                dpix = max(dpix, np.round(np.sum(my) / 2.))

            if max_kernel_radius is not None and \
                    dpix > int(max_kernel_radius / self.components[i].binsz):
                dpix = int(max_kernel_radius / self.components[i].binsz)

            xslice = slice(max(int(xpix - dpix), 0),
                           min(int(xpix + dpix + 1), self.npix))
            model[i] = model[i][:, xslice, xslice]

        ts_values = np.zeros((self.npix, self.npix))
        amp_values = np.zeros((self.npix, self.npix))

        wrap = functools.partial(_ts_value_newton, counts=counts,
                                 bkg=bkg, model=model,
                                 C_0_map=c0_map)

        if kwargs['map_skydir'] is not None:

            map_offset = wcs_utils.skydir_to_pix(kwargs['map_skydir'],
                                                 map_geom.wcs)

            map_delta = 0.5 * kwargs['map_size'] / self.components[0].binsz
            xmin = max(int(np.ceil(map_offset[1] - map_delta)), 0)
            xmax = min(int(np.floor(map_offset[1] + map_delta)) + 1, self.npix)
            ymin = max(int(np.ceil(map_offset[0] - map_delta)), 0)
            ymax = min(int(np.floor(map_offset[0] + map_delta)) + 1, self.npix)

            xslice = slice(xmin, xmax)
            yslice = slice(ymin, ymax)
            xyrange = [range(xmin, xmax), range(ymin, ymax)]

            wcs = map_geom.wcs.deepcopy()
            npix = (ymax - ymin, xmax - xmin)
            crpix = (map_geom._crpix[0] - ymin, map_geom._crpix[1] - xmin)
            wcs.wcs.crpix[0] -= ymin
            wcs.wcs.crpix[1] -= xmin

            # FIXME: We should implement this with a proper cutout method
            map_geom = WcsGeom(wcs, npix, crpix=crpix)
        else:
            xyrange = [range(self.npix), range(self.npix)]
            xslice = slice(0, self.npix)
            yslice = slice(0, self.npix)

        positions = []
        for i, j in itertools.product(xyrange[0], xyrange[1]):
            p = [[k // 2, i, j] for k in enumbins]
            positions += [p]

        self.logger.log(loglevel, 'Fitting test source.')
        if multithread:
            pool = Pool()
            results = pool.map(wrap, positions)
            pool.close()
            pool.join()
        else:
            results = map(wrap, positions)

        for i, r in enumerate(results):
            ix = positions[i][0][1]
            iy = positions[i][0][2]
            ts_values[ix, iy] = r[0]
            amp_values[ix, iy] = r[1]

        ts_values = ts_values[xslice, yslice]
        amp_values = amp_values[xslice, yslice]

        ts_map = WcsNDMap(map_geom, ts_values)
        sqrt_ts_map = WcsNDMap(map_geom, ts_values**0.5)
        npred_map = WcsNDMap(map_geom, amp_values * model_npred)
        amp_map = WcsNDMap(map_geom, amp_values * src.get_norm())

        o = {'name': utils.join_strings([prefix, modelname]),
             'src_dict': copy.deepcopy(src_dict),
             'file': None,
             'ts': ts_map,
             'sqrt_ts': sqrt_ts_map,
             'npred': npred_map,
             'amplitude': amp_map,
             'loglike': -self.like(),
             'config': kwargs
             }

        return o
示例#7
0
    def _make_tsmap_fast(self, prefix, **kwargs):
        """
        Make a TS map from a GTAnalysis instance.  This is a
        simplified implementation optimized for speed that only fits
        for the source normalization (all background components are
        kept fixed). The spectral/spatial characteristics of the test
        source can be defined with the src_dict argument.  By default
        this method will generate a TS map for a point source with an
        index=2.0 power-law spectrum.

        Parameters
        ----------
        model : dict or `~fermipy.roi_model.Source`
           Dictionary or Source object defining the properties of the
           test source that will be used in the scan.

        """

        src_dict = copy.deepcopy(kwargs.setdefault('model', {}))
        src_dict = {} if src_dict is None else src_dict

        multithread = kwargs.setdefault('multithread', False)
        threshold = kwargs.setdefault('threshold', 1E-2)
        max_kernel_radius = kwargs.get('max_kernel_radius')
        loge_bounds = kwargs.setdefault('loge_bounds', None)

        if loge_bounds is not None:
            if len(loge_bounds) == 0:
                loge_bounds = [None, None]
            elif len(loge_bounds) == 1:
                loge_bounds += [None]
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None
                              else self.log_energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None
                              else self.log_energies[-1])
        else:
            loge_bounds = [self.log_energies[0], self.log_energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round((self.npix - 1.0) / 2.),
                      np.round((self.npix - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        skywcs = self._skywcs
        skydir = wcs_utils.pix_to_skydir(cpix[0], cpix[1], skywcs)

        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)
        src_dict.setdefault('Prefactor', 1E-13)

        counts = []
        bkg = []
        model = []
        c0_map = []
        eslices = []
        enumbins = []
        model_npred = 0
        for c in self.components:

            imin = utils.val_to_edge(c.log_energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.log_energies, loge_bounds[1])[0]

            eslice = slice(imin, imax)
            bm = c.model_counts_map(exclude=kwargs['exclude']).counts.astype('float')[
                eslice, ...]
            cm = c.counts_map().counts.astype('float')[eslice, ...]

            bkg += [bm]
            counts += [cm]
            c0_map += [cash(cm, bm)]
            eslices += [eslice]
            enumbins += [cm.shape[0]]

        self.add_source('tsmap_testsource', src_dict, free=True,
                        init_source=False)
        src = self.roi['tsmap_testsource']
        # self.logger.info(str(src_dict))
        modelname = utils.create_model_name(src)
        for c, eslice in zip(self.components, eslices):
            mm = c.model_counts_map('tsmap_testsource').counts.astype('float')[
                eslice, ...]
            model_npred += np.sum(mm)
            model += [mm]

        self.delete_source('tsmap_testsource')

        for i, mm in enumerate(model):

            dpix = 3
            for j in range(mm.shape[0]):

                ix, iy = np.unravel_index(
                    np.argmax(mm[j, ...]), mm[j, ...].shape)

                mx = mm[j, ix, :] > mm[j, ix, iy] * threshold
                my = mm[j, :, iy] > mm[j, ix, iy] * threshold
                dpix = max(dpix, np.round(np.sum(mx) / 2.))
                dpix = max(dpix, np.round(np.sum(my) / 2.))

            if max_kernel_radius is not None and \
                    dpix > int(max_kernel_radius / self.components[i].binsz):
                dpix = int(max_kernel_radius / self.components[i].binsz)

            xslice = slice(max(int(xpix - dpix), 0),
                           min(int(xpix + dpix + 1), self.npix))
            model[i] = model[i][:, xslice, xslice]

        ts_values = np.zeros((self.npix, self.npix))
        amp_values = np.zeros((self.npix, self.npix))

        wrap = functools.partial(_ts_value_newton, counts=counts,
                                 bkg=bkg, model=model,
                                 C_0_map=c0_map)

        if kwargs['map_skydir'] is not None:
            map_offset = wcs_utils.skydir_to_pix(kwargs['map_skydir'],
                                                 self._skywcs)
            map_delta = 0.5 * kwargs['map_size'] / self.components[0].binsz
            xmin = max(int(np.ceil(map_offset[1] - map_delta)), 0)
            xmax = min(int(np.floor(map_offset[1] + map_delta)) + 1, self.npix)
            ymin = max(int(np.ceil(map_offset[0] - map_delta)), 0)
            ymax = min(int(np.floor(map_offset[0] + map_delta)) + 1, self.npix)

            xslice = slice(xmin, xmax)
            yslice = slice(ymin, ymax)
            xyrange = [range(xmin, xmax), range(ymin, ymax)]

            map_wcs = skywcs.deepcopy()
            map_wcs.wcs.crpix[0] -= ymin
            map_wcs.wcs.crpix[1] -= xmin
        else:
            xyrange = [range(self.npix), range(self.npix)]
            map_wcs = skywcs

            xslice = slice(0, self.npix)
            yslice = slice(0, self.npix)

        positions = []
        for i, j in itertools.product(xyrange[0], xyrange[1]):
            p = [[k // 2, i, j] for k in enumbins]
            positions += [p]

        if multithread:
            pool = Pool()
            results = pool.map(wrap, positions)
            pool.close()
            pool.join()
        else:
            results = map(wrap, positions)

        for i, r in enumerate(results):
            ix = positions[i][0][1]
            iy = positions[i][0][2]
            ts_values[ix, iy] = r[0]
            amp_values[ix, iy] = r[1]

        ts_values = ts_values[xslice, yslice]
        amp_values = amp_values[xslice, yslice]

        ts_map = Map(ts_values, map_wcs)
        sqrt_ts_map = Map(ts_values**0.5, map_wcs)
        npred_map = Map(amp_values * model_npred, map_wcs)
        amp_map = Map(amp_values * src.get_norm(), map_wcs)

        o = {'name': utils.join_strings([prefix, modelname]),
             'src_dict': copy.deepcopy(src_dict),
             'file': None,
             'ts': ts_map,
             'sqrt_ts': sqrt_ts_map,
             'npred': npred_map,
             'amplitude': amp_map,
             'config': kwargs
             }

        fits_file = utils.format_filename(self.config['fileio']['workdir'],
                                          'tsmap.fits',
                                          prefix=[prefix, modelname])

        if kwargs['write_fits']:

            fits_utils.write_maps(ts_map,
                                  {'SQRT_TS_MAP': sqrt_ts_map,
                                   'NPRED_MAP': npred_map,
                                   'N_MAP': amp_map},
                                  fits_file)
            o['file'] = os.path.basename(fits_file)

        if kwargs['write_npy']:
            np.save(os.path.splitext(fits_file)[0] + '.npy', o)

        return o
示例#8
0
文件: residmap.py 项目: NAH8/fermipy
    def _make_residual_map(self, prefix, config, **kwargs):

        write_fits = kwargs.get('write_fits', True)
        write_npy = kwargs.get('write_npy', True)

        src_dict = copy.deepcopy(config.setdefault('model', {}))
        exclude = config.setdefault('exclude', None)
        loge_bounds = config.setdefault('loge_bounds', None)

        if loge_bounds is not None:
            if len(loge_bounds) == 0:
                loge_bounds = [None, None]
            elif len(loge_bounds) == 1:
                loge_bounds += [None]
            loge_bounds[0] = (loge_bounds[0] if loge_bounds[0] is not None else
                              self.energies[0])
            loge_bounds[1] = (loge_bounds[1] if loge_bounds[1] is not None else
                              self.energies[-1])
        else:
            loge_bounds = [self.energies[0], self.energies[-1]]

        # Put the test source at the pixel closest to the ROI center
        xpix, ypix = (np.round(
            (self.npix - 1.0) / 2.), np.round((self.npix - 1.0) / 2.))
        cpix = np.array([xpix, ypix])

        skywcs = self._skywcs
        skydir = wcs_utils.pix_to_skydir(cpix[0], cpix[1], skywcs)

        if src_dict is None:
            src_dict = {}
        src_dict['ra'] = skydir.ra.deg
        src_dict['dec'] = skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)

        kernel = None

        if src_dict['SpatialModel'] == 'Gaussian':
            kernel = utils.make_gaussian_kernel(src_dict['SpatialWidth'],
                                                cdelt=self.components[0].binsz,
                                                npix=101)
            kernel /= np.sum(kernel)
            cpix = [50, 50]

        self.add_source('residmap_testsource',
                        src_dict,
                        free=True,
                        init_source=False,
                        save_source_maps=False)
        src = self.roi.get_source_by_name('residmap_testsource')

        modelname = utils.create_model_name(src)
        npix = self.components[0].npix

        mmst = np.zeros((npix, npix))
        cmst = np.zeros((npix, npix))
        emst = np.zeros((npix, npix))

        sm = get_source_kernel(self, 'residmap_testsource', kernel)
        ts = np.zeros((npix, npix))
        sigma = np.zeros((npix, npix))
        excess = np.zeros((npix, npix))

        self.delete_source('residmap_testsource')

        for i, c in enumerate(self.components):

            imin = utils.val_to_edge(c.energies, loge_bounds[0])[0]
            imax = utils.val_to_edge(c.energies, loge_bounds[1])[0]

            mc = c.model_counts_map(exclude=exclude).counts.astype('float')
            cc = c.counts_map().counts.astype('float')
            ec = np.ones(mc.shape)

            ccs = convolve_map(cc, sm[i], cpix, imin=imin, imax=imax)
            mcs = convolve_map(mc, sm[i], cpix, imin=imin, imax=imax)
            ecs = convolve_map(ec, sm[i], cpix, imin=imin, imax=imax)

            cms = np.sum(ccs, axis=0)
            mms = np.sum(mcs, axis=0)
            ems = np.sum(ecs, axis=0)

            cmst += cms
            mmst += mms
            emst += ems

            # cts = 2.0 * (poisson_lnl(cms, cms) - poisson_lnl(cms, mms))
            excess += cms - mms

        ts = 2.0 * (poisson_lnl(cmst, cmst) - poisson_lnl(cmst, mmst))
        sigma = np.sqrt(ts)
        sigma[excess < 0] *= -1
        emst /= np.max(emst)

        sigma_map = Map(sigma, skywcs)
        model_map = Map(mmst / emst, skywcs)
        data_map = Map(cmst / emst, skywcs)
        excess_map = Map(excess / emst, skywcs)

        o = {
            'name': utils.join_strings([prefix, modelname]),
            'file': None,
            'sigma': sigma_map,
            'model': model_map,
            'data': data_map,
            'excess': excess_map,
            'config': config
        }

        fits_file = utils.format_filename(self.config['fileio']['workdir'],
                                          'residmap.fits',
                                          prefix=[prefix, modelname])

        if write_fits:
            fits_utils.write_maps(
                sigma_map, {
                    'DATA_MAP': data_map,
                    'MODEL_MAP': model_map,
                    'EXCESS_MAP': excess_map
                }, fits_file)
            o['file'] = os.path.basename(fits_file)

        if write_npy:
            np.save(os.path.splitext(fits_file)[0] + '.npy', o)

        return o