Source code for gammapy.maps.maps

# Licensed under a 3-clause BSD style license - see LICENSE.rst
from collections.abc import MutableMapping
from astropy.io import fits
from gammapy.maps import Map
from gammapy.utils.scripts import make_path

__all__ = ["Maps"]


[docs]class Maps(MutableMapping): """A Dictionary containing Map objects sharing the same geometry. This class simplifies handling and I/O of maps collections. For maps with different geometries, use a regular dict. """ def __init__(self, **kwargs): self._geom = None self._data = {} for key, value in kwargs.items(): self.__setitem__(key, value) @property def geom(self): """Map geometry (`Geom`)""" return self._geom def __setitem__(self, key, value): if value is not None and not isinstance(value, Map): raise ValueError( f"MapDict can only contain Map objects, got {type(value)} instead." ) # TODO: which criterion to apply? Broadcastability? # if len(self._data) > 0: # if value.geom != self._geom: # raise ValueError( # f"MapDict items must share the same geometry. Expected {self._geom} got {value.geom}" # ) else: self._geom = value.geom self._data[key] = value def __getitem__(self, key): return self._data[key] def __len__(self): """Returns length of MapDict.""" return len(self._data) def __delitem__(self, key): del self._data[key] def __iter__(self): return iter(self._data) def __repr__(self): return f"{type(self).__name__}({self._data})" def __str__(self): str_ = f"{self.__class__.__name__}\n" str_ += "-" * len(self.__class__.__name__) + "\n" str_ += "\n" str_ += self._geom.__repr__() str_ += "\n" for name, value in self.items(): str_ += f"{name} \n" str_ += f"\t unit\t : {value.unit} \n" str_ += f"\t dtype\t : {value.data.dtype}\n" str_ += "\n" return str_
[docs] def to_hdulist(self, hdu_bands="BANDS"): """Convert map dictionary to list of HDUs. Parameters ---------- hdu_bands : str Name of the HDU with the BANDS table. Default is 'BANDS' If set to None, each map will have its own hdu_band Returns ------- hdulist : `~astropy.io.fits.HDUList` Map dataset list of HDUs. """ exclude_primary = slice(1, None) hdu_primary = fits.PrimaryHDU() hdulist = fits.HDUList([hdu_primary]) for key, m in self.items(): hdulist += m.to_hdulist(hdu=key, hdu_bands=hdu_bands)[exclude_primary] return hdulist
[docs] @classmethod def from_hdulist(cls, hdulist, hdu_bands="BANDS"): """Create map dictionary from list of HDUs. Because FITS keywords are case insensitive, all key names will return as lower-case. Parameters ---------- hdulist : `~astropy.io.fits.HDUList` List of HDUs. hdu_bands : str Name of the HDU with the BANDS table. Default is 'BANDS' If set to None, each map should have its own hdu_band Returns ------- maps : `~gammapy.maps.Maps` Maps object. """ maps = cls() for hdu in hdulist: if hdu.is_image and hdu.data is not None: map_name = hdu.name.lower() maps[map_name] = Map.from_hdulist( hdulist, hdu=map_name, hdu_bands=hdu_bands ) return maps
[docs] @classmethod def read(cls, filename): """Read map dictionary from file. Because FITS keywords are case insensitive, all key names will return as lower-case. Parameters ---------- filename : str Filename to read from. Returns ------- maps : `~gammapy.maps.Maps` Maps object. """ with fits.open(str(make_path(filename)), memmap=False) as hdulist: return cls.from_hdulist(hdulist)
[docs] def write(self, filename, overwrite=False): """Write map dictionary to file. Parameters ---------- filename : str Filename to write to. overwrite : bool Overwrite file if it exists. """ filename = make_path(filename) hdulist = self.to_hdulist() hdulist.writeto(filename, overwrite=overwrite)
[docs] @classmethod def from_geom(cls, geom, names, kwargs_list=None): """Create map dictionary from geometry. Parameters ---------- geom : `~gammapy.maps.Geom` the input geometry that will be used by all maps names : list of str the list of all map names kwargs_list : list of dict the list of arguments to be passed to `~gammapy.maps.Map.from_geom()` Returns ------- maps : `~gammapy.maps.Maps` Maps object. """ mapdict = {} if kwargs_list is None: kwargs_list = [{}] * len(names) for name, kwargs in zip(names, kwargs_list): mapdict[name] = Map.from_geom(geom, **kwargs) return cls(**mapdict)