Exemple #1
0
    def _fit_position_tsmap(self, name, **kwargs):
        """Localize a source from its TS map."""

        prefix = kwargs.get('prefix', '')
        dtheta_max = kwargs.get('dtheta_max', 0.5)
        zmin = kwargs.get('zmin', -3.0)

        kw = {
            'map_size': 2.0 * dtheta_max,
            'write_fits':  kwargs.get('write_fits', False),
            'write_npy':  kwargs.get('write_npy', False),
            'use_pylike': kwargs.get('use_pylike', True),
            'max_kernel_radius': self.config['tsmap']['max_kernel_radius'],
            'loglevel': logging.DEBUG
        }

        src = self.roi.copy_source(name)

        if src['SpatialModel'] in ['RadialDisk', 'RadialGaussian']:
            kw['max_kernel_radius'] = max(kw['max_kernel_radius'],
                                          2.0 * src['SpatialWidth'])

        skydir = kwargs.get('skydir', src.skydir)
        tsmap = self.tsmap(utils.join_strings([prefix, name.lower().
                                               replace(' ', '_')]),
                           model=src.data,
                           map_skydir=skydir,
                           exclude=[name],
                           make_plots=False, **kw)

        # Find peaks with TS > 4
        peaks = find_peaks(tsmap['ts'], 4.0, 0.2)
        peak_best = None
        o = {}
        for p in sorted(peaks, key=lambda t: t['amp'], reverse=True):
            xy = p['ix'], p['iy']
            ts_value = tsmap['ts'].data[xy[1], xy[0]]
            posfit = fit_error_ellipse(tsmap['ts'], xy=xy, dpix=2,
                                       zmin=max(zmin, -ts_value * 0.5))
            offset = posfit['skydir'].separation(self.roi[name].skydir).deg
            if posfit['fit_success'] and posfit['fit_inbounds']:
                peak_best = p
                break

        if peak_best is None:
            ts_value = np.max(tsmap['ts'].data)
            posfit = fit_error_ellipse(tsmap['ts'], dpix=2,
                                       zmin=max(zmin, -ts_value * 0.5))

        o.update(posfit)
        pix = posfit['skydir'].to_pixel(self.geom.wcs)
        o['xpix'] = float(pix[0])
        o['ypix'] = float(pix[1])
        o['skydir'] = posfit['skydir'].transform_to('icrs')
        o['pos_offset'] = posfit['skydir'].separation(
            self.roi[name].skydir).deg
        o['loglike'] = 0.5 * posfit['zoffset']
        o['tsmap'] = tsmap['ts']

        return o
Exemple #2
0
    def _localize_tscube(self, name, **kwargs):
        """Localize a source from a TS map generated with
        `~fermipy.gtanalysis.GTAnalysis.tscube`. """
        import matplotlib.pyplot as plt
        from fermipy.plotting import ROIPlotter

        prefix = kwargs.get('prefix', '')

        src = self.roi.copy_source(name)
        skydir = src.skydir

        wp = wcs_utils.WCSProj.create(skydir, 0.0125, 20, coordsys='GAL')

        self.zero_source(name)
        tscube = self.tscube(utils.join_strings(
            [prefix, name.lower().replace(' ', '_')]),
                             wcs=wp.wcs,
                             npix=wp.npix,
                             remake_test_source=False)
        self.unzero_source(name)

        tsmap_renorm = copy.deepcopy(tscube['ts'])
        tsmap_renorm._counts -= np.max(tsmap_renorm._counts)

        plt.figure()

        p = ROIPlotter(tsmap_renorm, roi=self.roi)

        p.plot(levels=[-200, -100, -50, -20, -9.21, -5.99, -2.3],
               cmap='BuGn',
               vmin=-50.0,
               interpolation='bicubic',
               cb_label='2$\\times\Delta\ln$L')

        plt.savefig('tscube_localize.png')
Exemple #3
0
    def _localize_tsmap(self, name, **kwargs):
        """Localize a source from its TS map."""

        prefix = kwargs.get('prefix', '')
        dtheta_max = kwargs.get('dtheta_max', 0.5)
        write_fits = kwargs.get('write_fits', False)
        write_npy = kwargs.get('write_npy', False)

        src = self.roi.copy_source(name)
        skydir = src.skydir
        skywcs = self._skywcs
        tsmap = self.tsmap(utils.join_strings(
            [prefix, name.lower().replace(' ', '_')]),
                           model=src.data,
                           map_skydir=skydir,
                           map_size=2.0 * dtheta_max,
                           exclude=[name],
                           write_fits=write_fits,
                           write_npy=write_npy,
                           make_plots=False)

        posfit, skydir = fit_error_ellipse(tsmap['ts'], dpix=2)
        pix = skydir.to_pixel(skywcs)

        o = {}
        o.update(posfit)
        o['xpix'] = float(pix[0])
        o['ypix'] = float(pix[1])
        return o, tsmap
Exemple #4
0
    def _fit_position_tsmap(self, name, **kwargs):
        """Localize a source from its TS map."""

        prefix = kwargs.get('prefix', '')
        dtheta_max = kwargs.get('dtheta_max', 0.5)
        zmin = kwargs.get('zmin', -3.0)

        kw = {
            'map_size': 2.0 * dtheta_max,
            'write_fits':  kwargs.get('write_fits', False),
            'write_npy':  kwargs.get('write_npy', False),
            'use_pylike': kwargs.get('use_pylike', True),
            'max_kernel_radius': self.config['tsmap']['max_kernel_radius'],
            'loglevel': logging.DEBUG
        }

        src = self.roi.copy_source(name)

        if src['SpatialModel'] in ['RadialDisk', 'RadialGaussian']:
            kw['max_kernel_radius'] = max(kw['max_kernel_radius'],
                                          2.0 * src['SpatialWidth'])

        skydir = kwargs.get('skydir', src.skydir)
        tsmap = self.tsmap(utils.join_strings([prefix, name.lower().
                                               replace(' ', '_')]),
                           model=src.data,
                           map_skydir=skydir,
                           exclude=[name],
                           make_plots=False, **kw)

        # Find peaks with TS > 4
        peaks = find_peaks(tsmap['ts'], 4.0, 0.2)
        peak_best = None
        o = {}
        for p in sorted(peaks, key=lambda t: t['amp'], reverse=True):
            xy = p['ix'], p['iy']
            ts_value = tsmap['ts'].counts[xy[1], xy[0]]
            posfit = fit_error_ellipse(tsmap['ts'], xy=xy, dpix=2,
                                       zmin=max(zmin, -ts_value * 0.5))
            offset = posfit['skydir'].separation(self.roi[name].skydir).deg
            if posfit['fit_success'] and posfit['fit_inbounds']:
                peak_best = p
                break

        if peak_best is None:
            ts_value = np.max(tsmap['ts'].counts)
            posfit = fit_error_ellipse(tsmap['ts'], dpix=2,
                                       zmin=max(zmin, -ts_value * 0.5))

        o.update(posfit)
        pix = posfit['skydir'].to_pixel(self._skywcs)
        o['xpix'] = float(pix[0])
        o['ypix'] = float(pix[1])
        o['skydir'] = posfit['skydir'].transform_to('icrs')
        o['pos_offset'] = posfit['skydir'].separation(
            self.roi[name].skydir).deg
        o['loglike'] = 0.5 * posfit['zoffset']
        o['tsmap'] = tsmap['ts']

        return o
Exemple #5
0
    def _make_ts_cube(self, prefix, **kwargs):

        map_skydir = kwargs.get('map_skydir')
        map_size = kwargs.get('map_size')
        exclude = kwargs.get('exclude', [])

        # We take the coordinate system and the bin size from the underlying map
        skywcs = self._geom.wcs
        galactic = wcs_utils.is_galactic(skywcs)
        pixsize = max(np.abs(skywcs.wcs.cdelt))

        # If the map_size is not specified we need to find the right number of pixels
        if map_size is None:
            npix = max(self._geom.npix)[0]
            map_size = pixsize * npix
        else:
            npix = int(np.round(map_size / pixsize))

        saved_state = LikelihoodState(self.like)

        for ex_src in exclude:
            self.zero_source(ex_src)

        if map_skydir is None:
            # Take the center of the wcs
            map_geom = self._geom.to_image()
            frame = coordsys_to_frame(map_geom.coordsys)
            map_skydir = SkyCoord(*map_geom.pix_to_coord(
                self._geom.wcs.wcs.crpix),
                                  frame=frame,
                                  unit='deg')
            map_skydir = map_skydir.transform_to('icrs')

        refdir = pyLike.SkyDir(map_skydir.ra.deg, map_skydir.dec.deg)

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

        src_dict['ra'] = map_skydir.ra.deg
        src_dict['dec'] = map_skydir.dec.deg
        src_dict.setdefault('SpatialModel', 'PointSource')
        src_dict.setdefault('SpatialWidth', 0.3)
        src_dict.setdefault('Index', 2.0)
        src_dict.setdefault('Prefactor', 1.0)
        src_dict['name'] = 'tscube_testsource'

        src = Source.create_from_dict(src_dict)
        if 'Prefactor' in src.spectral_pars:
            src.spectral_pars['Prefactor']['scale'] = 1.0e-10

        modelname = utils.create_model_name(src)
        pylike_src = self.components[0]._create_source(src)
        pylike_src.spectrum().normPar().setBounds(0, 1E6)

        skyproj = pyLike.FitScanner.buildSkyProj(str("AIT"), refdir, pixsize,
                                                 npix, galactic)

        optFactory = pyLike.OptimizerFactory_instance()
        optObject = optFactory.create(str("MINUIT"), self.like.composite)

        fitScanner = pyLike.FitScanner(self.like.composite, optObject, skyproj,
                                       npix, npix)
        fitScanner.set_quiet(True)
        fitScanner.setTestSource(pylike_src)

        self.logger.info("Running tscube")
        outfile = utils.format_filename(self.config['fileio']['workdir'],
                                        'tscube.fits',
                                        prefix=[prefix])

        fitScanner.run_tscube(True, kwargs['do_sed'], kwargs['nnorm'],
                              kwargs['norm_sigma'], kwargs['cov_scale_bb'],
                              kwargs['cov_scale'], kwargs['tol'],
                              kwargs['max_iter'], kwargs['tol_type'],
                              kwargs['remake_test_source'],
                              kwargs['st_scan_level'], str(''),
                              kwargs['init_lambda'])

        self.logger.info("Writing FITS output")

        fitScanner.writeFitsFile(str(outfile), str("gttscube"), "", False,
                                 pyLike.FitScanner.TSMAP_ONLY)
        saved_state.restore()

        convert_tscube(str(outfile), str(outfile))

        tscube = castro.TSCube.create_from_fits(outfile)
        ts_map = tscube.tsmap
        norm_map = tscube.normmap
        npred_map = copy.deepcopy(norm_map)
        npred_map.data *= tscube.refSpec.ref_npred.sum()
        amp_map = copy.deepcopy(norm_map)
        amp_map.data *= pylike_src.spectrum().normPar().getValue()
        sqrt_ts_map = copy.deepcopy(ts_map)
        sqrt_ts_map.data[...] = np.abs(sqrt_ts_map.data)**0.5

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

        if not kwargs['write_fits']:
            os.remove(outfile)
            o['file'] = None

        self.logger.info("Done")
        return o
Exemple #6
0
    def _find_sources_iterate(self, prefix, iiter, **kwargs):

        src_dict_template = kwargs.pop('model')

        threshold = kwargs.get('sqrt_ts_threshold')
        multithread = kwargs.get('multithread', False)
        min_separation = kwargs.get('min_separation')
        sources_per_iter = kwargs.get('sources_per_iter')
        search_skydir = kwargs.get('search_skydir', None)
        search_minmax_radius = kwargs.get('search_minmax_radius', [None, 1.0])
        tsmap_fitter = kwargs.get('tsmap_fitter', 'tsmap')
        free_params = kwargs.get('free_params', None)
        if not free_params:
            free_params = None

        if tsmap_fitter == 'tsmap':
            kw = kwargs.get('tsmap', {})
            kw['model'] = src_dict_template
            kw['multithread'] = multithread
            m = self.tsmap(utils.join_strings([prefix,
                                               'sourcefind_%02i' % iiter]),
                           **kw)

        elif tsmap_fitter == 'tscube':
            kw = kwargs.get('tscube', {})
            kw['model'] = src_dict_template
            m = self.tscube(utils.join_strings([prefix,
                                                'sourcefind_%02i' % iiter]),
                            **kw)
        else:
            raise Exception(
                'Unrecognized option for fitter: %s.' % tsmap_fitter)

        if tsmap_fitter == 'tsmap':
            peaks = find_peaks(m['sqrt_ts'], threshold, min_separation)
            (names, src_dicts) = \
                self._build_src_dicts_from_peaks(peaks, m, src_dict_template)
        elif tsmap_fitter == 'tscube':
            sd = m['tscube'].find_sources(threshold ** 2, min_separation,
                                          use_cumul=False,
                                          output_src_dicts=True,
                                          output_peaks=True)
            peaks = sd['Peaks']
            names = sd['Names']
            src_dicts = sd['SrcDicts']

        # Loop over the seeds and add them to the model
        new_src_names = []
        for name, src_dict in zip(names, src_dicts):
            # Protect against finding the same source twice
            if self.roi.has_source(name):
                self.logger.info('Source %s found again.  Ignoring it.' % name)
                continue
            # Skip the source if it's outside the search region
            if search_skydir is not None:

                skydir = SkyCoord(src_dict['ra'], src_dict['dec'], unit='deg')
                separation = search_skydir.separation(skydir).deg

                if not utils.apply_minmax_selection(separation,
                                                    search_minmax_radius):
                    self.logger.info('Source %s outside of '
                                     'search region.  Ignoring it.',
                                     name)
                    continue

            self.add_source(name, src_dict, free=True)
            self.free_source(name, False)
            new_src_names.append(name)

            if len(new_src_names) >= sources_per_iter:
                break

        # Re-fit spectral parameters of each source individually
        for name in new_src_names:
            self.logger.info('Performing spectral fit for %s.', name)
            self.logger.debug(pprint.pformat(self.roi[name].params))
            self.free_source(name, True, pars=free_params)
            self.fit()
            self.logger.info(pprint.pformat(self.roi[name].params))
            self.free_source(name, False)

        srcs = []
        for name in new_src_names:
            srcs.append(self.roi[name])

        return srcs, peaks
Exemple #7
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
Exemple #8
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[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
Exemple #9
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
Exemple #10
0
    def _make_ts_cube(self, prefix, **kwargs):

        skywcs = kwargs.get('wcs', self.geom.wcs)
        npix = kwargs.get('npix', self.npix)

        galactic = wcs_utils.is_galactic(skywcs)
        ref_skydir = wcs_utils.wcs_to_skydir(skywcs)
        refdir = pyLike.SkyDir(ref_skydir.ra.deg, ref_skydir.dec.deg)
        pixsize = np.abs(skywcs.wcs.cdelt[0])

        skyproj = pyLike.FitScanner.buildSkyProj(str("AIT"), refdir, pixsize,
                                                 npix, galactic)

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

        xpix, ypix = (np.round(
            (self.npix - 1.0) / 2.), np.round((self.npix - 1.0) / 2.))
        skydir = wcs_utils.pix_to_skydir(xpix, ypix, 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)
        src_dict['name'] = 'tscube_testsource'

        src = Source.create_from_dict(src_dict)

        modelname = utils.create_model_name(src)

        optFactory = pyLike.OptimizerFactory_instance()
        optObject = optFactory.create(str("MINUIT"),
                                      self.components[0].like.logLike)

        pylike_src = self.components[0]._create_source(src)
        fitScanner = pyLike.FitScanner(self.like.composite, optObject, skyproj,
                                       npix, npix)

        pylike_src.spectrum().normPar().setBounds(0, 1E6)

        fitScanner.setTestSource(pylike_src)

        self.logger.info("Running tscube")
        outfile = utils.format_filename(self.config['fileio']['workdir'],
                                        'tscube.fits',
                                        prefix=[prefix])

        try:
            fitScanner.run_tscube(True, kwargs['do_sed'], kwargs['nnorm'],
                                  kwargs['norm_sigma'], kwargs['cov_scale_bb'],
                                  kwargs['cov_scale'], kwargs['tol'],
                                  kwargs['max_iter'], kwargs['tol_type'],
                                  kwargs['remake_test_source'],
                                  kwargs['st_scan_level'], str(''),
                                  kwargs['init_lambda'])
        except Exception:
            fitScanner.run_tscube(True, kwargs['do_sed'], kwargs['nnorm'],
                                  kwargs['norm_sigma'], kwargs['cov_scale_bb'],
                                  kwargs['cov_scale'], kwargs['tol'],
                                  kwargs['max_iter'], kwargs['tol_type'],
                                  kwargs['remake_test_source'],
                                  kwargs['st_scan_level'])

        self.logger.info("Writing FITS output")

        fitScanner.writeFitsFile(str(outfile), str("gttscube"))

        convert_tscube(str(outfile), str(outfile))

        tscube = castro.TSCube.create_from_fits(outfile)
        ts_map = tscube.tsmap
        norm_map = tscube.normmap
        npred_map = copy.deepcopy(norm_map)
        npred_map.data *= tscube.refSpec.ref_npred.sum()
        amp_map = copy.deepcopy(norm_map)
        amp_map.data *= src_dict['Prefactor']

        sqrt_ts_map = copy.deepcopy(ts_map)
        sqrt_ts_map.data[...] = np.abs(sqrt_ts_map.data)**0.5

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

        if not kwargs['write_fits']:
            os.remove(outfile)
            os['file'] = None

        self.logger.info("Done")
        return o
Exemple #11
0
    def _find_sources_iterate(self, prefix, iiter, **kwargs):

        src_dict_template = kwargs.pop('model')

        threshold = kwargs.get('sqrt_ts_threshold')
        multithread = kwargs.get('multithread', False)
        min_separation = kwargs.get('min_separation')
        sources_per_iter = kwargs.get('sources_per_iter')
        search_skydir = kwargs.get('search_skydir', None)
        search_minmax_radius = kwargs.get('search_minmax_radius', [None, 1.0])
        tsmap_fitter = kwargs.get('tsmap_fitter', 'tsmap')
        free_params = kwargs.get('free_params', None)
        if not free_params:
            free_params = None

        if tsmap_fitter == 'tsmap':
            kw = kwargs.get('tsmap', {})
            kw['model'] = src_dict_template
            kw['multithread'] = multithread
            m = self.tsmap(utils.join_strings([prefix,
                                               'sourcefind_%02i' % iiter]),
                           **kw)

        elif tsmap_fitter == 'tscube':
            kw = kwargs.get('tscube', {})
            kw['model'] = src_dict_template
            m = self.tscube(utils.join_strings([prefix,
                                                'sourcefind_%02i' % iiter]),
                            **kw)
        else:
            raise Exception(
                'Unrecognized option for fitter: %s.' % tsmap_fitter)

        if tsmap_fitter == 'tsmap':
            peaks = find_peaks(m['sqrt_ts'], threshold, min_separation)
            (names, src_dicts) = \
                self._build_src_dicts_from_peaks(peaks, m, src_dict_template)
        elif tsmap_fitter == 'tscube':
            sd = m['tscube'].find_sources(threshold ** 2, min_separation,
                                          use_cumul=False,
                                          output_src_dicts=True,
                                          output_peaks=True)
            peaks = sd['Peaks']
            names = sd['Names']
            src_dicts = sd['SrcDicts']

        # Loop over the seeds and add them to the model
        new_src_names = []
        for name, src_dict in zip(names, src_dicts):
            # Protect against finding the same source twice
            if self.roi.has_source(name):
                self.logger.info('Source %s found again.  Ignoring it.' % name)
                continue
            # Skip the source if it's outside the search region
            if search_skydir is not None:

                skydir = SkyCoord(src_dict['ra'], src_dict['dec'], unit='deg')
                separation = search_skydir.separation(skydir).deg

                if not utils.apply_minmax_selection(separation,
                                                    search_minmax_radius):
                    self.logger.info('Source %s outside of '
                                     'search region.  Ignoring it.',
                                     name)
                    continue

            self.add_source(name, src_dict, free=True)
            self.free_source(name, False)
            new_src_names.append(name)

            if len(new_src_names) >= sources_per_iter:
                break

        # Re-fit spectral parameters of each source individually
        for name in new_src_names:
            self.logger.info('Performing spectral fit for %s.', name)
            self.logger.debug(pprint.pformat(self.roi[name].params))
            self.free_source(name, True, pars=free_params)
            self.fit()
            self.logger.info(pprint.pformat(self.roi[name].params))
            self.free_source(name, False)

        srcs = []
        for name in new_src_names:
            srcs.append(self.roi[name])

        return srcs, peaks
Exemple #12
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
Exemple #13
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
Exemple #14
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
Exemple #15
0
    def _make_ts_cube(self, prefix, **kwargs):

        skywcs = kwargs.get('wcs', self.geom.wcs)
        npix = kwargs.get('npix', self.npix)

        galactic = wcs_utils.is_galactic(skywcs)
        ref_skydir = wcs_utils.wcs_to_skydir(skywcs)
        refdir = pyLike.SkyDir(ref_skydir.ra.deg,
                               ref_skydir.dec.deg)
        pixsize = np.abs(skywcs.wcs.cdelt[0])

        skyproj = pyLike.FitScanner.buildSkyProj(str("AIT"),
                                                 refdir, pixsize, npix,
                                                 galactic)

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

        xpix, ypix = (np.round((self.npix - 1.0) / 2.),
                      np.round((self.npix - 1.0) / 2.))
        skydir = wcs_utils.pix_to_skydir(xpix, ypix, 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)
        src_dict['name'] = 'tscube_testsource'

        src = Source.create_from_dict(src_dict)

        modelname = utils.create_model_name(src)

        optFactory = pyLike.OptimizerFactory_instance()
        optObject = optFactory.create(str("MINUIT"),
                                      self.components[0].like.logLike)

        pylike_src = self.components[0]._create_source(src)
        fitScanner = pyLike.FitScanner(self.like.composite, optObject, skyproj,
                                       npix, npix)

        pylike_src.spectrum().normPar().setBounds(0, 1E6)

        fitScanner.setTestSource(pylike_src)

        self.logger.info("Running tscube")
        outfile = utils.format_filename(self.config['fileio']['workdir'],
                                        'tscube.fits',
                                        prefix=[prefix])

        try:
            fitScanner.run_tscube(True,
                                  kwargs['do_sed'], kwargs['nnorm'],
                                  kwargs['norm_sigma'],
                                  kwargs['cov_scale_bb'], kwargs['cov_scale'],
                                  kwargs['tol'], kwargs['max_iter'],
                                  kwargs['tol_type'],
                                  kwargs['remake_test_source'],
                                  kwargs['st_scan_level'],
                                  str(''),
                                  kwargs['init_lambda'])
        except Exception:
            fitScanner.run_tscube(True,
                                  kwargs['do_sed'], kwargs['nnorm'],
                                  kwargs['norm_sigma'],
                                  kwargs['cov_scale_bb'], kwargs['cov_scale'],
                                  kwargs['tol'], kwargs['max_iter'],
                                  kwargs['tol_type'],
                                  kwargs['remake_test_source'],
                                  kwargs['st_scan_level'])

        self.logger.info("Writing FITS output")

        fitScanner.writeFitsFile(str(outfile), str("gttscube"))

        convert_tscube(str(outfile), str(outfile))

        tscube = castro.TSCube.create_from_fits(outfile)
        ts_map = tscube.tsmap
        norm_map = tscube.normmap
        npred_map = copy.deepcopy(norm_map)
        npred_map.data *= tscube.refSpec.ref_npred.sum()
        amp_map = copy.deepcopy(norm_map)
        amp_map.data *= src_dict['Prefactor']

        sqrt_ts_map = copy.deepcopy(ts_map)
        sqrt_ts_map.data[...] = np.abs(sqrt_ts_map.data)**0.5

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

        if not kwargs['write_fits']:
            os.remove(outfile)
            os['file'] = None

        self.logger.info("Done")
        return o
Exemple #16
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
Exemple #17
0
    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