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
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
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
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
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
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
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