Source code for kbmod.standardizers.fits_standardizers.multi_extension_fits
"""Standardizer for FITS files containing multiple extensions."""
from astropy.io.fits import CompImageHDU, PrimaryHDU, ImageHDU
from .fits_standardizer import FitsStandardizer, FitsStandardizerConfig
__all__ = [
"MultiExtensionFits",
]
[docs]class MultiExtensionFits(FitsStandardizer):
"""Suppports processing of a single, multi-extension FITS file.
Extensions for which it's possible to extract WCS, bounding boxes and masks
are required to be places in the ``exts`` attribute. For single extension
FITS files this is the primary header, as it contains the image data.
Parameters
----------
location : `str`
Location of the FITS file, can be an URI or local filesystem path.
set_exts : `bool`
When `True`, finds all HDUs that are image-like and sets them as
elements of `exts` list. Note that using the default `_isImageLike`
implementation is rather costly as it loads the whole data into memory.
Attributes
----------
hdulist : `~astropy.io.fits.HDUList`
All HDUs found in the FITS file
primary : `~astropy.io.fits.PrimaryHDU`
The primary HDU.
exts : `list`
All HDUs from `hdulist` marked as "image-like" for further processing
with KBMOD. Does not include the primary HDU, when it doesn't contain
any image data. Contains at least 1 entry.
wcs : `list`
WCSs associated with the processable image data. Will contain at least
1 WCS.
bbox : `list`
Bounding boxes associated with each WCS.
"""
# Standardizers we don't want to register themselves we leave nameless
# Since FitsStd isn't usable by itself - we do not register it.
# name = "MultiExtensionFitsStandardizer"
# priority = 1
configClass = FitsStandardizerConfig
@staticmethod
def _isImageLikeHDU(hdu):
"""If the given HDU contains an image, returns `True`, otherwise
`False`.
HDU is determined to be an image if it's one of the primary, image or
compressed image types in Astropy and its ``.data`` attribute is not
empty, but a 2D array with dimensions less than 6000 rows and columns.
This is a generic best-guess implementation and there are no guarantees
that the retrieved extensions are science images, i.e. images
containing the actual sky, and not a small table-like HDU, guider or
focus chip images.
Parameters
----------
hdu : `astropy.fits.HDU`
Header unit to inspect.
Returns
-------
image_like : `bool`
True if HDU is image-like, False otherwise.
"""
# This is already a pretty good basic test
if not any((isinstance(hdu, CompImageHDU), isinstance(hdu, PrimaryHDU), isinstance(hdu, ImageHDU))):
return False
# The problem is that all kinds of things are stored as ImageHDUs, say
# a 120k x 8000k table (I'm looking at you SDSS!). To avoid that we
# need to check the data shape. The problem is that causes the data to
# load from disk and that is very expensive
if len(hdu.shape) != 2:
return False
if hdu.shape[0] > 6000 or hdu.shape[1] > 6000:
return False
if hdu.data is None:
return False
return True
[docs] @classmethod
def resolveTarget(cls, tgt):
parentCanStandardize, res = super().resolveTarget(tgt)
if not parentCanStandardize:
return False, {}
canStandardize = parentCanStandardize and len(res["hdulist"]) > 1
return canStandardize, res
def __init__(self, location=None, hdulist=None, config=None, set_processable=False, **kwargs):
super().__init__(location=location, hdulist=hdulist, config=config, **kwargs)
# do not load images from disk unless requested
if set_processable:
for hdu in self.hdulist:
if self._isImageLikeHDU(hdu):
self.processable.append(hdu)