Source code for gammapy.image.catalog

# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""Make an image from a source catalog, or simulated catalog, e.g 1FHL 2FGL etc
"""
from __future__ import absolute_import, division, print_function, unicode_literals
from collections import OrderedDict
import numpy as np
from astropy.wcs import WCS
from astropy.units import Quantity
from astropy import units as u
from astropy.table import Table
from .core import SkyImage
from .lists import SkyImageList

__all__ = [
    'CatalogImageEstimator',
]

BBOX_DELTA2D_PIX = 5


[docs]class CatalogImageEstimator(object): """Compute model image for given energy band from a catalog. Sources are only filled when their center lies within the image boundaries. Parameters ---------- reference : `~gammapy.image.SkyImage` Reference sky image. emin : `~astropy.units.Quantity` Lower bound of energy range. emax : `~astropy.units.Quantity` Upper bound of energy range. Examples -------- Here is an example how to compute a flux image from a catalog: from astropy import units as u from gammapy.image import SkyImage, CatalogImageEstimator from gammapy.catalog import SourceCatalogGammaCat reference = SkyImage.empty(xref=265, yref=-1.5, nxpix=201, nypix=201, binsz=0.04) image_estimator = CatalogImageEstimator(reference=reference, emin=1 * u.TeV, emax=10 * u.TeV) catalog = SourceCatalogGammaCat() result = image_estimator.run(catalog) result['flux'].show() Currently the `CatalogImageEstimator` class does not support to compute model cubes of catalogs. But this can achieved with only a little more of python code: from astropy import units as u from gammapy.image import CatalogImageEstimator, SkyImage from gammapy.cube import SkyCube from gammapy.catalog import SourceCatalogGammaCat from gammapy.utils.energy import EnergyBounds reference = SkyImage.empty(xref=265, yref=-1.5, nxpix=201, nypix=201, binsz=0.04) energies = EnergyBounds.equal_log_spacing(1 * u.TeV, 100 * u.TeV, 3) flux_cube = SkyCube.empty_like(reference=reference, energies=energies) catalog = SourceCatalogGammaCat() for idx in range(energies.size - 1): image_estimator = CatalogImageEstimator(reference=reference, emin=energies[idx], emax=energies[idx + 1]) result = image_estimator.run(catalog) flux_cube.data[idx, :, :] = result['flux'].data flux_cube.show() """ def __init__(self, reference, emin, emax): self.reference = reference self.parameters = OrderedDict(emin=emin, emax=emax)
[docs] def flux(self, catalog): """Compute flux image from catalog. Sources are only filled when their center lies within the image boundaries. Parameters ---------- catalog : `~gammapy.catalog.SourceCatalog` Source catalog instance. Returns ------- image : `~gammapy.image.SkyImage` Flux sky image. """ from ..catalog.gammacat import NoDataAvailableError p = self.parameters image = SkyImage.empty_like(self.reference) selection = catalog.select_image_region(image) for source in selection: try: spatial_model = source.spatial_model(emin=p['emin'], emax=p['emax']) # TODO: remove this error handling and add selection to SourceCatalog # class except (NotImplementedError, NoDataAvailableError): continue if source.is_pointlike: # use 5 pixel bbox for point-like models size = BBOX_DELTA2D_PIX * image.wcs_pixel_scale().to('deg') else: height, width = np.diff(spatial_model.bounding_box) size = (float(height) * u.deg, float(width) * u.deg) cutout = image.cutout(source.position, size=size) if source.is_pointlike: solid_angle = 1. else: solid_angle = cutout.solid_angle().to('deg2').value # evaluate model on smaller image and paste c = cutout.coordinates() l, b = c.galactic.l.wrap_at('180d'), c.galactic.b cutout.data = spatial_model(l.deg, b.deg) * solid_angle image.paste(cutout) return image
[docs] def run(self, catalog, which='flux'): """Run catalog image estimator. Parameters ---------- catalog : `~gammapy.catalog.SourceCatalog` Source catalog instance. Returns ------- sky_images : `~gammapy.image.SkyImageList` List of sky images """ result = SkyImageList() # TODO: add input image list and computed derived quantities such as # excess, psf convolution etc. if 'flux' in which: result['flux'] = self.flux(catalog) return result