fits.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # -*- coding: utf-8 -*-
  2. # imageio is distributed under the terms of the (new) BSD License.
  3. """Read FITS files.
  4. Backend Library: `Astropy <https://www.astropy.org/>`_
  5. .. note::
  6. To use this plugin you have to install its backend::
  7. pip install imageio[fits]
  8. Flexible Image Transport System (FITS) is an open standard defining a
  9. digital file format useful for storage, transmission and processing of
  10. scientific and other images. FITS is the most commonly used digital
  11. file format in astronomy.
  12. Parameters
  13. ----------
  14. cache : bool
  15. If the file name is a URL, `~astropy.utils.data.download_file` is used
  16. to open the file. This specifies whether or not to save the file
  17. locally in Astropy's download cache (default: `True`).
  18. uint : bool
  19. Interpret signed integer data where ``BZERO`` is the
  20. central value and ``BSCALE == 1`` as unsigned integer
  21. data. For example, ``int16`` data with ``BZERO = 32768``
  22. and ``BSCALE = 1`` would be treated as ``uint16`` data.
  23. Note, for backward compatibility, the kwarg **uint16** may
  24. be used instead. The kwarg was renamed when support was
  25. added for integers of any size.
  26. ignore_missing_end : bool
  27. Do not issue an exception when opening a file that is
  28. missing an ``END`` card in the last header.
  29. checksum : bool or str
  30. If `True`, verifies that both ``DATASUM`` and
  31. ``CHECKSUM`` card values (when present in the HDU header)
  32. match the header and data of all HDU's in the file. Updates to a
  33. file that already has a checksum will preserve and update the
  34. existing checksums unless this argument is given a value of
  35. 'remove', in which case the CHECKSUM and DATASUM values are not
  36. checked, and are removed when saving changes to the file.
  37. disable_image_compression : bool, optional
  38. If `True`, treats compressed image HDU's like normal
  39. binary table HDU's.
  40. do_not_scale_image_data : bool
  41. If `True`, image data is not scaled using BSCALE/BZERO values
  42. when read.
  43. ignore_blank : bool
  44. If `True`, the BLANK keyword is ignored if present.
  45. scale_back : bool
  46. If `True`, when saving changes to a file that contained scaled
  47. image data, restore the data to the original type and reapply the
  48. original BSCALE/BZERO values. This could lead to loss of accuracy
  49. if scaling back to integer values after performing floating point
  50. operations on the data.
  51. """
  52. from ..core import Format
  53. _fits = None # lazily loaded
  54. def load_lib():
  55. global _fits
  56. try:
  57. from astropy.io import fits as _fits
  58. except ImportError:
  59. raise ImportError(
  60. "The FITS format relies on the astropy package."
  61. "Please refer to http://www.astropy.org/ "
  62. "for further instructions."
  63. )
  64. return _fits
  65. class FitsFormat(Format):
  66. """See :mod:`imageio.plugins.fits`"""
  67. def _can_read(self, request):
  68. # We return True if ext matches, because this is the only plugin
  69. # that can. If astropy is not installed, a useful error follows.
  70. return request.extension in self.extensions
  71. def _can_write(self, request):
  72. # No write support
  73. return False
  74. # -- reader
  75. class Reader(Format.Reader):
  76. def _open(self, cache=False, **kwargs):
  77. if not _fits:
  78. load_lib()
  79. hdulist = _fits.open(self.request.get_file(), cache=cache, **kwargs)
  80. self._index = []
  81. allowed_hdu_types = (_fits.ImageHDU, _fits.PrimaryHDU, _fits.CompImageHDU)
  82. for n, hdu in zip(range(len(hdulist)), hdulist):
  83. if isinstance(hdu, allowed_hdu_types):
  84. # Ignore (primary) header units with no data (use '.size'
  85. # rather than '.data' to avoid actually loading the image):
  86. if hdu.size > 0:
  87. self._index.append(n)
  88. self._hdulist = hdulist
  89. def _close(self):
  90. self._hdulist.close()
  91. def _get_length(self):
  92. return len(self._index)
  93. def _get_data(self, index):
  94. # Get data
  95. if index < 0 or index >= len(self._index):
  96. raise IndexError("Index out of range while reading from fits")
  97. im = self._hdulist[self._index[index]].data
  98. # Return array and empty meta data
  99. return im, {}
  100. def _get_meta_data(self, index):
  101. # Get the meta data for the given index
  102. raise RuntimeError("The fits format does not support meta data.")