Ejemplo n.º 1
0
    def residmap(self, prefix='', **kwargs):
        """Generate 2-D spatial residual maps using the current ROI
        model and the convolution kernel defined with the `model`
        argument.

        Parameters
        ----------
        prefix : str
            String that will be prefixed to the output residual map files.

        {options}

        Returns
        -------
        maps : dict
           A dictionary containing the `~fermipy.utils.Map` objects
           for the residual significance and amplitude.    

        """
        timer = Timer.create(start=True)
        self.logger.info('Generating residual maps')

        schema = ConfigSchema(self.defaults['residmap'])

        config = schema.create_config(self.config['residmap'], **kwargs)

        # Defining default properties of test source model
        config['model'].setdefault('Index', 2.0)
        config['model'].setdefault('SpectrumType', 'PowerLaw')
        config['model'].setdefault('SpatialModel', 'PointSource')
        config['model'].setdefault('Prefactor', 1E-13)

        o = self._make_residual_map(prefix, **config)

        if config['make_plots']:
            plotter = plotting.AnalysisPlotter(self.config['plotting'],
                                               fileio=self.config['fileio'],
                                               logging=self.config['logging'])

            plotter.make_residmap_plots(o, self.roi)

        self.logger.info('Finished residual maps')

        outfile = utils.format_filename(self.workdir,
                                        'residmap',
                                        prefix=[o['name']])

        if config['write_fits']:
            o['file'] = os.path.basename(outfile) + '.fits'
            self._make_residmap_fits(o, outfile + '.fits')

        if config['write_npy']:
            np.save(outfile + '.npy', o)

        self.logger.info('Execution time: %.2f s', timer.elapsed_time)
        return o
Ejemplo n.º 2
0
    def residmap(self, prefix='', **kwargs):
        """Generate 2-D spatial residual maps using the current ROI
        model and the convolution kernel defined with the `model`
        argument.

        Parameters
        ----------
        prefix : str
            String that will be prefixed to the output residual map files.

        {options}

        Returns
        -------
        maps : dict
           A dictionary containing the `~fermipy.utils.Map` objects
           for the residual significance and amplitude.    

        """
        timer = Timer.create(start=True)
        self.logger.info('Generating residual maps')

        schema = ConfigSchema(self.defaults['residmap'])

        config = schema.create_config(self.config['residmap'], **kwargs)

        # Defining default properties of test source model
        config['model'].setdefault('Index', 2.0)
        config['model'].setdefault('SpectrumType', 'PowerLaw')
        config['model'].setdefault('SpatialModel', 'PointSource')
        config['model'].setdefault('Prefactor', 1E-13)

        o = self._make_residual_map(prefix, **config)

        if config['make_plots']:
            plotter = plotting.AnalysisPlotter(self.config['plotting'],
                                               fileio=self.config['fileio'],
                                               logging=self.config['logging'])

            plotter.make_residmap_plots(o, self.roi)

        self.logger.info('Finished residual maps')

        outfile = utils.format_filename(self.workdir, 'residmap',
                                        prefix=[o['name']])

        if config['write_fits']:
            o['file'] = os.path.basename(outfile) + '.fits'
            self._make_residmap_fits(o, outfile + '.fits')

        if config['write_npy']:
            np.save(outfile + '.npy', o)

        self.logger.info('Execution time: %.2f s', timer.elapsed_time)
        return o
Ejemplo n.º 3
0
    def find_sources(self, prefix='', **kwargs):
        """An iterative source-finding algorithm that uses likelihood
        ratio (TS) maps of the region of interest to find new sources.
        After each iteration a new TS map is generated incorporating
        sources found in the previous iteration.  The method stops
        when the number of iterations exceeds ``max_iter`` or no
        sources exceeding ``sqrt_ts_threshold`` are found.

        Parameters
        ----------
        {options}

        tsmap : dict
           Keyword arguments dictionary for tsmap method.

        tscube : dict
           Keyword arguments dictionary for tscube method.

        Returns
        -------

        peaks : list
           List of peak objects.

        sources : list
           List of source objects.

        """
        timer = Timer.create(start=True)
        self.logger.info('Starting.')

        schema = ConfigSchema(self.defaults['sourcefind'],
                              tsmap=self.defaults['tsmap'],
                              tscube=self.defaults['tscube'])

        schema.add_option('search_skydir', None, '', SkyCoord)
        schema.add_option('search_minmax_radius', [None, 1.0], '', list)

        config = utils.create_dict(self.config['sourcefind'],
                                   tsmap=self.config['tsmap'],
                                   tscube=self.config['tscube'])
        config = schema.create_config(config, **kwargs)

        # Defining default properties of test source model
        config['model'].setdefault('Index', 2.0)
        config['model'].setdefault('SpectrumType', 'PowerLaw')
        config['model'].setdefault('SpatialModel', 'PointSource')
        config['model'].setdefault('Prefactor', 1E-13)

        o = {'sources': [], 'peaks': []}

        for i in range(config['max_iter']):
            srcs, peaks = self._find_sources_iterate(prefix, i, **config)

            self.logger.info('Found %i sources in iteration %i.' %
                             (len(srcs), i))

            o['sources'] += srcs
            o['peaks'] += peaks
            if len(srcs) == 0:
                break

        self.logger.info('Done.')
        self.logger.info('Execution time: %.2f s', timer.elapsed_time)

        return o
Ejemplo n.º 4
0
    def localize(self, name, **kwargs):
        """Find the best-fit position of a source.  Localization is
        performed in two steps.  First a TS map is computed centered
        on the source with half-width set by ``dtheta_max``.  A fit is
        then performed to the maximum TS peak in this map.  The source
        position is then further refined by scanning the likelihood in
        the vicinity of the peak found in the first step.  The size of
        the scan region is set to encompass the 99% positional
        uncertainty contour as determined from the peak fit.

        Parameters
        ----------
        name : str
            Source name.

        {options}

        optimizer : dict
            Dictionary that overrides the default optimizer settings.

        Returns
        -------
        localize : dict
            Dictionary containing results of the localization
            analysis.

        """
        timer = Timer.create(start=True)
        name = self.roi.get_source_by_name(name).name

        schema = ConfigSchema(self.defaults['localize'],
                              optimizer=self.defaults['optimizer'])
        schema.add_option('use_cache', True)
        schema.add_option('prefix', '')
        config = utils.create_dict(self.config['localize'],
                                   optimizer=self.config['optimizer'])
        config = schema.create_config(config, **kwargs)

        self.logger.info('Running localization for %s' % name)

        free_state = FreeParameterState(self)
        loc = self._localize(name, **config)
        free_state.restore()

        self.logger.info('Finished localization.')

        if config['make_plots']:
            self._plotter.make_localization_plots(loc, self.roi,
                                                  prefix=config['prefix'])

        outfile = \
            utils.format_filename(self.workdir, 'loc',
                                  prefix=[config['prefix'],
                                          name.lower().replace(' ', '_')])

        if config['write_fits']:
            loc['file'] = os.path.basename(outfile) + '.fits'
            self._make_localize_fits(loc, outfile + '.fits',
                                     **config)

        if config['write_npy']:
            np.save(outfile + '.npy', dict(loc))

        self.logger.info('Execution time: %.2f s', timer.elapsed_time)
        return loc
Ejemplo n.º 5
0
    def tsmap(self, prefix='', **kwargs):
        """Generate a spatial TS map for a source component with
        properties defined by the `model` argument.  The TS map will
        have the same geometry as the ROI.  The output of this method
        is a dictionary containing `~fermipy.skymap.Map` objects with
        the TS and amplitude of the best-fit test source.  By default
        this method will also save maps to FITS files and render them
        as image files.

        This method uses a simplified likelihood fitting
        implementation that only fits for the normalization of the
        test source.  Before running this method it is recommended to
        first optimize the ROI model (e.g. by running
        :py:meth:`~fermipy.gtanalysis.GTAnalysis.optimize`).

        Parameters
        ----------
        prefix : str
           Optional string that will be prepended to all output files.

        {options}

        Returns
        -------
        tsmap : dict
           A dictionary containing the `~fermipy.skymap.Map` objects
           for TS and source amplitude.

        """
        timer = Timer.create(start=True)

        schema = ConfigSchema(self.defaults['tsmap'])
        schema.add_option('loglevel', logging.INFO)
        schema.add_option('map_skydir', None, '', astropy.coordinates.SkyCoord)
        schema.add_option('map_size', 1.0)
        schema.add_option('threshold', 1E-2, '', float)
        schema.add_option('use_pylike', True, '', bool)
        schema.add_option('outfile', None, '', str)
        config = schema.create_config(self.config['tsmap'], **kwargs)

        # Defining default properties of test source model
        config['model'].setdefault('Index', 2.0)
        config['model'].setdefault('SpectrumType', 'PowerLaw')
        config['model'].setdefault('SpatialModel', 'PointSource')

        self.logger.log(config['loglevel'], 'Generating TS map')

        o = self._make_tsmap_fast(prefix, **config)

        if config['make_plots']:
            plotter = plotting.AnalysisPlotter(self.config['plotting'],
                                               fileio=self.config['fileio'],
                                               logging=self.config['logging'])

            plotter.make_tsmap_plots(o, self.roi)

        self.logger.log(config['loglevel'], 'Finished TS map')

        outfile = config.get('outfile', None)
        if outfile is None:
            outfile = utils.format_filename(self.workdir,
                                            'tsmap',
                                            prefix=[o['name']])
        else:
            outfile = os.path.join(self.workdir, os.path.splitext(outfile)[0])

        if config['write_fits']:
            o['file'] = os.path.basename(outfile) + '.fits'
            self._make_tsmap_fits(o, outfile + '.fits')

        if config['write_npy']:
            np.save(outfile + '.npy', o)

        self.logger.log(config['loglevel'], 'Execution time: %.2f s',
                        timer.elapsed_time)
        return o
Ejemplo n.º 6
0
    def _fit_extension_full(self, name, **kwargs):

        skydir = self.roi[name].skydir.copy()
        src = self.roi.copy_source(name)
        spatial_model = kwargs.get('spatial_model', 'RadialGaussian')
        loglike = -self.like()

        o = MutableNamedTuple(ext=np.nan,
                              ext_ul95=np.nan,
                              ext_err_lo=np.nan,
                              ext_err_hi=np.nan,
                              ext_err=np.nan,
                              loglike_ext=np.nan,
                              ra=np.nan,
                              dec=np.nan,
                              glon=np.nan,
                              glat=np.nan,
                              ra_err=np.nan,
                              dec_err=np.nan,
                              glon_err=np.nan,
                              glat_err=np.nan,
                              pos_err=np.nan,
                              pos_r68=np.nan,
                              pos_r95=np.nan,
                              pos_r99=np.nan,
                              pos_err_semimajor=np.nan,
                              pos_err_semiminor=np.nan,
                              pos_angle=np.nan,
                              pos_offset=np.nan)

        t0 = Timer()
        t1 = Timer()

        nstep = 7
        for i in range(4):

            t0.start()
            fit_ext = self._fit_extension(name, skydir=skydir, **kwargs)
            o.update(fit_ext)
            self.set_source_morphology(
                name,
                spatial_model=spatial_model,
                spatial_pars={'SpatialWidth': max(o.ext, 0.00316)},
                use_pylike=False)
            t0.stop()

            t1.start()
            if i == 0 or not np.isfinite(o.pos_r99):
                dtheta_max = max(0.5, 1.5 * o.ext)
            else:
                dtheta_max = max(0.5, o.pos_r99)

            fit_pos0, fit_pos1 = self._fit_position(name,
                                                    nstep=nstep,
                                                    dtheta_max=dtheta_max,
                                                    zmin=-3.0,
                                                    use_pylike=False)
            o.update(fit_pos0)
            t1.stop()

            self.set_source_morphology(name,
                                       spatial_model=spatial_model,
                                       spatial_pars={
                                           'RA': o['ra'],
                                           'DEC': o['dec']
                                       },
                                       use_pylike=False)

            self.logger.debug('Elapsed Time: %.2f %.2f', t0.elapsed_time,
                              t1.elapsed_time)

            fit_output = self._fit(loglevel=logging.DEBUG,
                                   **kwargs['optimizer'])

            skydir = fit_pos0['skydir']
            o.pos_offset = skydir.separation(src.skydir).deg
            o.loglike_ext = -self.like()
            dloglike = o.loglike_ext - loglike

            self.logger.info(
                'Iter %i R68 = %8.3f Offset = %8.3f '
                'LogLikelihood = %10.2f Delta-LogLikelihood = %8.2f', i, o.ext,
                o.pos_offset, o.loglike_ext, dloglike)

            if i > 0 and dloglike < 0.1:
                break

            loglike = o.loglike_ext

        self.set_source_morphology(name,
                                   spatial_pars=src.spatial_pars,
                                   use_pylike=False)
        return o
Ejemplo n.º 7
0
    def extension(self, name, **kwargs):
        """Test this source for spatial extension with the likelihood
        ratio method (TS_ext).  This method will substitute an
        extended spatial model for the given source and perform a
        one-dimensional scan of the spatial extension parameter over
        the range specified with the width parameters.  The 1-D
        profile likelihood is then used to compute the best-fit value,
        upper limit, and TS for extension.  The nuisance parameters
        that will be simultaneously fit when performing the spatial
        scan can be controlled with the ``fix_shape``,
        ``free_background``, and ``free_radius`` options.  By default
        the position of the source will be fixed to its current
        position.  A simultaneous fit to position and extension can be
        performed by setting ``fit_position`` to True.

        Parameters
        ----------
        name : str
            Source name.

        {options}

        optimizer : dict
            Dictionary that overrides the default optimizer settings.

        Returns
        -------
        extension : dict
            Dictionary containing results of the extension analysis.  The same
            dictionary is also saved to the dictionary of this source under
            'extension'.
        """
        timer = Timer.create(start=True)
        name = self.roi.get_source_by_name(name).name

        schema = ConfigSchema(self.defaults['extension'],
                              optimizer=self.defaults['optimizer'])
        schema.add_option('prefix', '')
        schema.add_option('outfile', None, '', str)
        config = utils.create_dict(self.config['extension'],
                                   optimizer=self.config['optimizer'])
        config = schema.create_config(config, **kwargs)

        self.logger.info('Running extension fit for %s', name)

        free_state = FreeParameterState(self)
        ext = self._extension(name, **config)
        free_state.restore()

        self.logger.info('Finished extension fit.')

        if config['make_plots']:
            self._plotter.make_extension_plots(ext,
                                               self.roi,
                                               prefix=config['prefix'])

        outfile = config.get('outfile', None)
        if outfile is None:
            outfile = utils.format_filename(
                self.workdir,
                'ext',
                prefix=[config['prefix'],
                        name.lower().replace(' ', '_')])
        else:
            outfile = os.path.join(self.workdir, os.path.splitext(outfile)[0])

        if config['write_fits']:
            self._make_extension_fits(ext, outfile + '.fits')

        if config['write_npy']:
            o_copy = dict(ext)
            self.logger.warning(
                'Saving maps in .npy files is disabled b/c of incompatibilities in python3, remove the maps from the %s.npy'
                % outfile)
            print(o_copy)
            for xrm in ['tsmap']:
                o_copy.pop(xrm)
            np.save(outfile + '.npy', o_copy)

        self.logger.info('Execution time: %.2f s', timer.elapsed_time)
        return ext
Ejemplo n.º 8
0
    def sed(self, name, **kwargs):
        """Generate a spectral energy distribution (SED) for a source.  This
        function will fit the normalization of the source in each
        energy bin.  By default the SED will be generated with the
        analysis energy bins but a custom binning can be defined with
        the ``loge_bins`` parameter.

        Parameters
        ----------
        name : str
            Source name.

        prefix : str
            Optional string that will be prepended to all output files
            (FITS and rendered images).

        loge_bins : `~numpy.ndarray`
            Sequence of energies in log10(E/MeV) defining the edges of
            the energy bins.  If this argument is None then the
            analysis energy bins will be used.  The energies in this
            sequence must align with the bin edges of the underyling
            analysis instance.

        {options}

        optimizer : dict
            Dictionary that overrides the default optimizer settings.

        Returns
        -------
        sed : dict
            Dictionary containing output of the SED analysis.

        """
        timer = Timer.create(start=True)
        name = self.roi.get_source_by_name(name).name

        # Create schema for method configuration
        schema = ConfigSchema(self.defaults['sed'],
                              optimizer=self.defaults['optimizer'])
        schema.add_option('prefix', '')
        schema.add_option('outfile', None, '', str)
        schema.add_option('loge_bins', None, '', list)
        config = utils.create_dict(self.config['sed'],
                                   optimizer=self.config['optimizer'])
        config = schema.create_config(config, **kwargs)

        self.logger.info('Computing SED for %s' % name)

        o = self._make_sed(name, **config)

        self.logger.info('Finished SED')

        outfile = config.get('outfile', None)
        if outfile is None:
            outfile = utils.format_filename(self.workdir, 'sed',
                                            prefix=[config['prefix'],
                                                    name.lower().replace(' ', '_')])
        else:
            outfile = os.path.join(self.workdir,
                                   os.path.splitext(outfile)[0])

        o['file'] = None
        if config['write_fits']:
            o['file'] = os.path.basename(outfile) + '.fits'
            self._make_sed_fits(o, outfile + '.fits', **config)

        if config['write_npy']:
            np.save(outfile + '.npy', o)

        if config['make_plots']:
            self._plotter.make_sed_plots(o, **config)

        self.logger.info('Execution time: %.2f s', timer.elapsed_time)
        return o
Ejemplo n.º 9
0
    def tsmap(self, prefix='', **kwargs):
        """Generate a spatial TS map for a source component with
        properties defined by the `model` argument.  The TS map will
        have the same geometry as the ROI.  The output of this method
        is a dictionary containing `~fermipy.skymap.Map` objects with
        the TS and amplitude of the best-fit test source.  By default
        this method will also save maps to FITS files and render them
        as image files.

        This method uses a simplified likelihood fitting
        implementation that only fits for the normalization of the
        test source.  Before running this method it is recommended to
        first optimize the ROI model (e.g. by running
        :py:meth:`~fermipy.gtanalysis.GTAnalysis.optimize`).

        Parameters
        ----------
        prefix : str
           Optional string that will be prepended to all output files.

        {options}

        Returns
        -------
        tsmap : dict
           A dictionary containing the `~fermipy.skymap.Map` objects
           for TS and source amplitude.

        """
        timer = Timer.create(start=True)

        schema = ConfigSchema(self.defaults['tsmap'])
        schema.add_option('loglevel', logging.INFO)
        schema.add_option('map_skydir', None, '', astropy.coordinates.SkyCoord)
        schema.add_option('map_size', 1.0)
        schema.add_option('threshold', 1E-2, '', float)
        schema.add_option('use_pylike', True, '', bool)
        schema.add_option('outfile', None, '', str)
        config = schema.create_config(self.config['tsmap'], **kwargs)

        # Defining default properties of test source model
        config['model'].setdefault('Index', 2.0)
        config['model'].setdefault('SpectrumType', 'PowerLaw')
        config['model'].setdefault('SpatialModel', 'PointSource')

        self.logger.log(config['loglevel'], 'Generating TS map')

        o = self._make_tsmap_fast(prefix, **config)

        if config['make_plots']:
            plotter = plotting.AnalysisPlotter(self.config['plotting'],
                                               fileio=self.config['fileio'],
                                               logging=self.config['logging'])

            plotter.make_tsmap_plots(o, self.roi)

        self.logger.log(config['loglevel'], 'Finished TS map')

        outfile = config.get('outfile', None)
        if outfile is None:
            outfile = utils.format_filename(self.workdir, 'tsmap',
                                            prefix=[o['name']])
        else:
            outfile = os.path.join(self.workdir,
                                   os.path.splitext(outfile)[0])

        if config['write_fits']:
            o['file'] = os.path.basename(outfile) + '.fits'
            self._make_tsmap_fits(o, outfile + '.fits')

        if config['write_npy']:
            np.save(outfile + '.npy', o)

        self.logger.log(config['loglevel'],
                        'Execution time: %.2f s', timer.elapsed_time)
        return o
Ejemplo n.º 10
0
    def find_sources(self, prefix='', **kwargs):
        """An iterative source-finding algorithm that uses likelihood
        ratio (TS) maps of the region of interest to find new sources.
        After each iteration a new TS map is generated incorporating
        sources found in the previous iteration.  The method stops
        when the number of iterations exceeds ``max_iter`` or no
        sources exceeding ``sqrt_ts_threshold`` are found.

        Parameters
        ----------
        {options}

        tsmap : dict
           Keyword arguments dictionary for tsmap method.

        tscube : dict
           Keyword arguments dictionary for tscube method.

        Returns
        -------

        peaks : list
           List of peak objects.

        sources : list
           List of source objects.

        """
        timer = Timer.create(start=True)
        self.logger.info('Starting.')

        schema = ConfigSchema(self.defaults['sourcefind'],
                              tsmap=self.defaults['tsmap'],
                              tscube=self.defaults['tscube'])

        schema.add_option('search_skydir', None, '', SkyCoord)
        schema.add_option('search_minmax_radius', [None, 1.0], '', list)

        config = utils.create_dict(self.config['sourcefind'],
                                   tsmap=self.config['tsmap'],
                                   tscube=self.config['tscube'])
        config = schema.create_config(config, **kwargs)

        # Defining default properties of test source model
        config['model'].setdefault('Index', 2.0)
        config['model'].setdefault('SpectrumType', 'PowerLaw')
        config['model'].setdefault('SpatialModel', 'PointSource')
        config['model'].setdefault('Prefactor', 1E-13)

        o = {'sources': [], 'peaks': []}

        for i in range(config['max_iter']):
            srcs, peaks = self._find_sources_iterate(prefix, i, **config)

            self.logger.info('Found %i sources in iteration %i.' %
                             (len(srcs), i))

            o['sources'] += srcs
            o['peaks'] += peaks
            if len(srcs) == 0:
                break

        self.logger.info('Done.')
        self.logger.info('Execution time: %.2f s', timer.elapsed_time)

        return o
Ejemplo n.º 11
0
    def localize(self, name, **kwargs):
        """Find the best-fit position of a source.  Localization is
        performed in two steps.  First a TS map is computed centered
        on the source with half-width set by ``dtheta_max``.  A fit is
        then performed to the maximum TS peak in this map.  The source
        position is then further refined by scanning the likelihood in
        the vicinity of the peak found in the first step.  The size of
        the scan region is set to encompass the 99% positional
        uncertainty contour as determined from the peak fit.

        Parameters
        ----------
        name : str
            Source name.

        {options}

        optimizer : dict
            Dictionary that overrides the default optimizer settings.

        Returns
        -------
        localize : dict
            Dictionary containing results of the localization
            analysis.

        """
        timer = Timer.create(start=True)
        name = self.roi.get_source_by_name(name).name

        schema = ConfigSchema(self.defaults['localize'],
                              optimizer=self.defaults['optimizer'])
        schema.add_option('use_cache', True)
        schema.add_option('prefix', '')
        config = utils.create_dict(self.config['localize'],
                                   optimizer=self.config['optimizer'])
        config = schema.create_config(config, **kwargs)

        self.logger.info('Running localization for %s' % name)

        free_state = FreeParameterState(self)
        loc = self._localize(name, **config)
        free_state.restore()

        self.logger.info('Finished localization.')

        if config['make_plots']:
            self._plotter.make_localization_plots(loc, self.roi,
                                                  prefix=config['prefix'])

        outfile = \
            utils.format_filename(self.workdir, 'loc',
                                  prefix=[config['prefix'],
                                          name.lower().replace(' ', '_')])

        if config['write_fits']:
            loc['file'] = os.path.basename(outfile) + '.fits'
            self._make_localize_fits(loc, outfile + '.fits',
                                     **config)

        if config['write_npy']:
            np.save(outfile + '.npy', dict(loc))

        self.logger.info('Execution time: %.2f s', timer.elapsed_time)
        return loc
Ejemplo n.º 12
0
    def _fit_extension_full(self, name, **kwargs):

        skydir = self.roi[name].skydir.copy()
        src = self.roi.copy_source(name)
        spatial_model = kwargs.get('spatial_model', 'RadialGaussian')
        loglike = -self.like()

        o = MutableNamedTuple(
            ext=np.nan, ext_ul95=np.nan,
            ext_err_lo=np.nan, ext_err_hi=np.nan,
            ext_err=np.nan,
            loglike_ext=np.nan,
            ra=np.nan, dec=np.nan, glon=np.nan, glat=np.nan,
            ra_err=np.nan, dec_err=np.nan,
            glon_err=np.nan, glat_err=np.nan,
            pos_err=np.nan, pos_r68=np.nan,
            pos_r95=np.nan, pos_r99=np.nan,
            pos_err_semimajor=np.nan, pos_err_semiminor=np.nan,
            pos_angle=np.nan, pos_offset=np.nan)

        t0 = Timer()
        t1 = Timer()

        nstep = 7
        for i in range(4):

            t0.start()
            fit_ext = self._fit_extension(name, skydir=skydir, **kwargs)
            o.update(fit_ext)
            self.set_source_morphology(name,
                                       spatial_model=spatial_model,
                                       spatial_pars={
                                           'SpatialWidth': max(o.ext, 0.00316)},
                                       use_pylike=False)
            t0.stop()

            t1.start()
            if i == 0 or not np.isfinite(o.pos_r99):
                dtheta_max = max(0.5, 1.5 * o.ext)
            else:
                dtheta_max = max(0.5, o.pos_r99)

            fit_pos0, fit_pos1 = self._fit_position(name, nstep=nstep,
                                                    dtheta_max=dtheta_max,
                                                    zmin=-3.0, use_pylike=False)
            o.update(fit_pos0)
            t1.stop()

            self.set_source_morphology(name,
                                       spatial_model=spatial_model,
                                       spatial_pars={'RA': o['ra'],
                                                     'DEC': o['dec']},
                                       use_pylike=False)

            self.logger.debug('Elapsed Time: %.2f %.2f',
                              t0.elapsed_time, t1.elapsed_time)

            fit_output = self._fit(
                loglevel=logging.DEBUG, **kwargs['optimizer'])

            skydir = fit_pos0['skydir']
            o.pos_offset = skydir.separation(src.skydir).deg
            o.loglike_ext = -self.like()
            dloglike = o.loglike_ext - loglike

            self.logger.info('Iter %i R68 = %8.3f Offset = %8.3f '
                             'LogLikelihood = %10.2f Delta-LogLikelihood = %8.2f',
                             i, o.ext, o.pos_offset, o.loglike_ext,
                             dloglike)

            if i > 0 and dloglike < 0.1:
                break

            loglike = o.loglike_ext

        self.set_source_morphology(name, spatial_pars=src.spatial_pars,
                                   use_pylike=False)
        return o
Ejemplo n.º 13
0
    def extension(self, name, **kwargs):
        """Test this source for spatial extension with the likelihood
        ratio method (TS_ext).  This method will substitute an
        extended spatial model for the given source and perform a
        one-dimensional scan of the spatial extension parameter over
        the range specified with the width parameters.  The 1-D
        profile likelihood is then used to compute the best-fit value,
        upper limit, and TS for extension.  The nuisance parameters
        that will be simultaneously fit when performing the spatial
        scan can be controlled with the ``fix_shape``,
        ``free_background``, and ``free_radius`` options.  By default
        the position of the source will be fixed to its current
        position.  A simultaneous fit to position and extension can be
        performed by setting ``fit_position`` to True.

        Parameters
        ----------
        name : str
            Source name.

        {options}

        optimizer : dict
            Dictionary that overrides the default optimizer settings.

        Returns
        -------
        extension : dict
            Dictionary containing results of the extension analysis.  The same
            dictionary is also saved to the dictionary of this source under
            'extension'.
        """
        timer = Timer.create(start=True)
        name = self.roi.get_source_by_name(name).name

        schema = ConfigSchema(self.defaults['extension'],
                              optimizer=self.defaults['optimizer'])
        schema.add_option('prefix', '')
        schema.add_option('outfile', None, '', str)
        config = utils.create_dict(self.config['extension'],
                                   optimizer=self.config['optimizer'])
        config = schema.create_config(config, **kwargs)

        self.logger.info('Running extension fit for %s', name)

        free_state = FreeParameterState(self)
        ext = self._extension(name, **config)
        free_state.restore()

        self.logger.info('Finished extension fit.')

        if config['make_plots']:
            self._plotter.make_extension_plots(ext, self.roi,
                                               prefix=config['prefix'])

        outfile = config.get('outfile', None)
        if outfile is None:
            outfile = utils.format_filename(self.workdir, 'ext',
                                            prefix=[config['prefix'],
                                                    name.lower().replace(' ', '_')])
        else:
            outfile = os.path.join(self.workdir,
                                   os.path.splitext(outfile)[0])

        if config['write_fits']:
            self._make_extension_fits(ext, outfile + '.fits')

        if config['write_npy']:
            np.save(outfile + '.npy', dict(ext))

        self.logger.info('Execution time: %.2f s', timer.elapsed_time)
        return ext