LSSTApplications  16.0-10-g0ee56ad+5,16.0-11-ga33d1f2+5,16.0-12-g3ef5c14+3,16.0-12-g71e5ef5+18,16.0-12-gbdf3636+3,16.0-13-g118c103+3,16.0-13-g8f68b0a+3,16.0-15-gbf5c1cb+4,16.0-16-gfd17674+3,16.0-17-g7c01f5c+3,16.0-18-g0a50484+1,16.0-20-ga20f992+8,16.0-21-g0e05fd4+6,16.0-21-g15e2d33+4,16.0-22-g62d8060+4,16.0-22-g847a80f+4,16.0-25-gf00d9b8+1,16.0-28-g3990c221+4,16.0-3-gf928089+3,16.0-32-g88a4f23+5,16.0-34-gd7987ad+3,16.0-37-gc7333cb+2,16.0-4-g10fc685+2,16.0-4-g18f3627+26,16.0-4-g5f3a788+26,16.0-5-gaf5c3d7+4,16.0-5-gcc1f4bb+1,16.0-6-g3b92700+4,16.0-6-g4412fcd+3,16.0-6-g7235603+4,16.0-69-g2562ce1b+2,16.0-8-g14ebd58+4,16.0-8-g2df868b+1,16.0-8-g4cec79c+6,16.0-8-gadf6c7a+1,16.0-8-gfc7ad86,16.0-82-g59ec2a54a+1,16.0-9-g5400cdc+2,16.0-9-ge6233d7+5,master-g2880f2d8cf+3,v17.0.rc1
LSSTDataManagementBasePackage
fits.h
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 #ifndef LSST_AFW_fits_h_INCLUDED
3 #define LSST_AFW_fits_h_INCLUDED
4 
5 /*
6  * Utilities for working with FITS files. These are mostly thin wrappers around
7  * cfitsio calls, and their main purpose is to transform functions signatures from
8  * void pointers and cfitsio's preprocessor type enums to a more type-safe and
9  * convenient interface using overloads and templates.
10  *
11  * This was written as part of implementing the afw/table library. Someday
12  * the afw/image FITS I/O should be modified to use some of these with the goal
13  * of eliminating a lot of code between the two.
14  */
15 
16 #include <climits>
17 #include <string>
18 
19 #include <boost/format.hpp>
20 
21 #include "lsst/base.h"
22 #include "lsst/pex/exceptions.h"
23 #include "lsst/daf/base.h"
24 #include "ndarray.h"
26 #include "lsst/afw/fitsDefaults.h"
27 
28 namespace lsst {
29 namespace afw {
30 namespace fits {
31 
36 
37 
41 
49 public:
50  virtual void operator()(std::string const& key, std::string const& value, std::string const& comment) = 0;
51 
53 };
54 
63 std::string makeErrorMessage(std::string const& fileName = "", int status = 0, std::string const& msg = "");
64 inline std::string makeErrorMessage(std::string const& fileName, int status, boost::format const& msg) {
65  return makeErrorMessage(fileName, status, msg.str());
66 }
67 
77 std::string makeErrorMessage(void* fptr, int status = 0, std::string const& msg = "");
78 inline std::string makeErrorMessage(void* fptr, int status, boost::format const& msg) {
79  return makeErrorMessage(fptr, status, msg.str());
80 }
81 
98  std::set<std::string> const& excludeNames = {});
99 
104 #define LSST_FITS_EXCEPT(type, fitsObj, ...) \
105  type(LSST_EXCEPT_HERE, lsst::afw::fits::makeErrorMessage((fitsObj).fptr, (fitsObj).status, __VA_ARGS__))
106 
110 #define LSST_FITS_CHECK_STATUS(fitsObj, ...) \
111  if ((fitsObj).status != 0) throw LSST_FITS_EXCEPT(lsst::afw::fits::FitsError, fitsObj, __VA_ARGS__)
112 
114 template <typename T>
115 int getBitPix();
116 
121 public:
128  MemFileManager() : _ptr(0), _len(0), _managed(true) {}
129 
136  explicit MemFileManager(std::size_t len) : _ptr(0), _len(0), _managed(true) { reset(len); }
137 
145  MemFileManager(void* ptr, std::size_t len) : _ptr(ptr), _len(len), _managed(false) {}
146 
152  void reset();
153 
162  void reset(std::size_t len);
163 
172  void reset(void* ptr, std::size_t len) {
173  reset();
174  _ptr = ptr;
175  _len = len;
176  _managed = false;
177  }
178 
180 
181  // No copying
182  MemFileManager(const MemFileManager&) = delete;
183  MemFileManager& operator=(const MemFileManager&) = delete;
184 
185  // No moving
186  MemFileManager(MemFileManager&&) = delete;
188 
190  void* getData() const { return _ptr; }
191 
193  std::size_t getLength() const { return _len; }
194 
195 private:
196  friend class Fits;
197 
198  void* _ptr;
199  std::size_t _len;
200  bool _managed;
201 };
202 
206 template <typename T, int N, int C>
207 ndarray::Array<T const, N, N> const makeContiguousArray(ndarray::Array<T, N, C> const& array) {
208  ndarray::Array<T const, N, N> contiguous = ndarray::dynamic_dimension_cast<N>(array);
209  if (contiguous.empty()) contiguous = ndarray::copy(array);
210  return contiguous;
211 }
212 
221 
223  template <typename T>
224  explicit ImageWriteOptions(image::Image<T> const& image) : compression(image) {}
225 
227  template <typename T>
228  explicit ImageWriteOptions(image::Mask<T> const& mask) : compression(mask) {}
229 
231  explicit ImageWriteOptions(ImageCompressionOptions const& compression_ =
233  ImageScalingOptions const& scaling_ = ImageScalingOptions())
234  : compression(compression_), scaling(scaling_) {}
235 
237  explicit ImageWriteOptions(ImageScalingOptions const& scaling_)
238  : compression(ImageCompressionOptions::NONE), scaling(scaling_) {}
239 
265 
278 };
279 
296 class Fits {
297  void createImageImpl(int bitpix, int nAxis, long const* nAxes);
298  template <typename T>
299  void writeImageImpl(T const* data, int nElements);
300  template <typename T>
301  void readImageImpl(int nAxis, T* data, long* begin, long* end, long* increment);
302  void getImageShapeImpl(int maxDim, long* nAxes);
303 
304 public:
306  AUTO_CLOSE = 0x01, // Close files when the Fits object goes out of scope if fptr != NULL
307  AUTO_CHECK = 0x02 // Call LSST_FITS_CHECK_STATUS after every cfitsio call
308  };
309 
311  std::string getFileName() const;
312 
314  int getHdu();
315 
325  void setHdu(int hdu, bool relative = false);
326 
328  int countHdus();
329 
331  template <typename T>
333  void updateKey(std::string const& key, T const& value, std::string const& comment);
334  void updateKey(std::string const& key, char const* value, std::string const& comment) {
335  updateKey(key, std::string(value), comment);
336  }
337  template <typename T>
338  void updateKey(std::string const& key, T const& value);
339  void updateKey(std::string const& key, char const* value) { updateKey(key, std::string(value)); }
341 
343 
350  template <typename T>
351  void writeKey(std::string const& key, T const& value, std::string const& comment);
352  void writeKey(std::string const& key, char const* value, std::string const& comment) {
353  writeKey(key, std::string(value), comment);
354  }
355  template <typename T>
356  void writeKey(std::string const& key, T const& value);
357  void writeKey(std::string const& key, char const* value) { writeKey(key, std::string(value)); }
359 
361  template <typename T>
363  void updateColumnKey(std::string const& prefix, int n, T const& value, std::string const& comment);
364  void updateColumnKey(std::string const& prefix, int n, char const* value, std::string const& comment) {
365  updateColumnKey(prefix, n, std::string(value), comment);
366  }
367  template <typename T>
368  void updateColumnKey(std::string const& prefix, int n, T const& value);
369  void updateColumnKey(std::string const& prefix, int n, char const* value) {
370  updateColumnKey(prefix, n, std::string(value));
371  }
373 
375  template <typename T>
377  void writeColumnKey(std::string const& prefix, int n, T const& value, std::string const& comment);
378  void writeColumnKey(std::string const& prefix, int n, char const* value, std::string const& comment) {
379  writeColumnKey(prefix, n, std::string(value), comment);
380  }
381  template <typename T>
382  void writeColumnKey(std::string const& prefix, int n, T const& value);
383  void writeColumnKey(std::string const& prefix, int n, char const* value) {
384  writeColumnKey(prefix, n, std::string(value));
385  }
387 
397  void writeMetadata(daf::base::PropertySet const& metadata);
398 
408  void readMetadata(daf::base::PropertySet& metadata, bool strip = false);
409 
411  template <typename T>
412  void readKey(std::string const& key, T& value);
413 
422  void forEachKey(HeaderIterationFunctor& functor);
423 
430  void createEmpty();
431 
442  template <typename PixelT, int N>
443  void createImage(ndarray::Vector<ndarray::Size, N> const& shape) {
444  ndarray::Vector<long, N> nAxes(shape.reverse());
445  createImageImpl(detail::Bitpix<PixelT>::value, N, nAxes.elems);
446  }
447 
448  template <int N>
449  void createImage(int bitpix, ndarray::Vector<ndarray::Size, N> const& shape) {
450  ndarray::Vector<long, N> nAxes(shape.reverse());
451  createImageImpl(bitpix, N, nAxes.elems);
452  }
453 
460  template <typename PixelT>
461  void createImage(long x, long y) {
462  long naxes[2] = {x, y};
463  createImageImpl(detail::Bitpix<PixelT>::value, 2, naxes);
464  }
465 
475  template <typename T, int N, int C>
476  void writeImage(ndarray::Array<T const, N, C> const& array) {
477  writeImageImpl(makeContiguousArray(array).getData(), array.getNumElements());
478  }
479 
492  template <typename T>
493  void writeImage(
498 
500  int getImageDim();
501 
510  template <int N>
511  ndarray::Vector<ndarray::Size, N> getImageShape() {
512  ndarray::Vector<long, N> nAxes(1);
513  getImageShapeImpl(N, nAxes.elems);
514  ndarray::Vector<ndarray::Size, N> shape;
515  for (int i = 0; i < N; ++i) shape[i] = nAxes[N - i - 1];
516  return shape;
517  }
518 
525  template <typename T>
526  bool checkImageType();
527 
531  std::string getImageDType();
532 
539  template <typename T, int N>
540  void readImage(ndarray::Array<T, N, N> const& array, ndarray::Vector<int, N> const& offset) {
541  ndarray::Vector<long, N> begin(offset.reverse());
542  ndarray::Vector<long, N> end(begin);
543  end += array.getShape().reverse();
544  ndarray::Vector<long, N> increment(1);
545  begin += increment; // first FITS pixel is 1, not 0
546  readImageImpl(N, array.getData(), begin.elems, end.elems, increment.elems);
547  }
548 
550  void createTable();
551 
558  template <typename T>
559  int addColumn(std::string const& ttype, int size, std::string const& comment);
560 
567  template <typename T>
568  int addColumn(std::string const& ttype, int size);
569 
571  std::size_t addRows(std::size_t nRows);
572 
574  std::size_t countRows();
575 
577  template <typename T>
578  void writeTableArray(std::size_t row, int col, int nElements, T const* value);
579 
581  template <typename T>
582  void writeTableScalar(std::size_t row, int col, T value) {
583  writeTableArray(row, col, 1, &value);
584  }
586  void writeTableScalar(std::size_t row, int col, std::string const& value);
587 
589  template <typename T>
590  void readTableArray(std::size_t row, int col, int nElements, T* value);
591 
593  template <typename T>
594  void readTableScalar(std::size_t row, int col, T& value) {
595  readTableArray(row, col, 1, &value);
596  }
597 
599  void readTableScalar(std::size_t row, int col, std::string& value, bool isVariableLength);
600 
602  long getTableArraySize(int col);
603 
605  long getTableArraySize(std::size_t row, int col);
606 
608  Fits() : fptr(0), status(0), behavior(0) {}
609 
611  Fits(std::string const& filename, std::string const& mode, int behavior);
612 
614  Fits(MemFileManager& manager, std::string const& mode, int behavior);
615 
617  void closeFile();
618 
622  void setImageCompression(ImageCompressionOptions const& options);
623 
625  ImageCompressionOptions getImageCompression();
626 
634  bool checkCompressedImagePhu();
635 
636  ~Fits() {
637  if ((fptr) && (behavior & AUTO_CLOSE)) closeFile();
638  }
639 
640  // No copying
641  Fits(const Fits&) = delete;
642  Fits& operator=(const Fits&) = delete;
643 
644  // No moving
645  Fits(Fits&&) = delete;
646  Fits& operator=(Fits&&) = delete;
647 
648  void* fptr; // the actual cfitsio fitsfile pointer; void to avoid including fitsio.h here.
649  int status; // the cfitsio status indicator that gets passed to every cfitsio call.
650  int behavior; // bitwise OR of BehaviorFlags
651 };
652 
673 
685  bool strip = false);
697  bool strip = false);
708 
709 void setAllowImageCompression(bool allow);
711 
712 
713 
724 public:
725 
726  HduMoveGuard() = delete;
727 
728  HduMoveGuard(HduMoveGuard const &) = delete;
729  HduMoveGuard(HduMoveGuard &&) = delete;
730 
731  HduMoveGuard & operator=(HduMoveGuard const &) = delete;
732  HduMoveGuard & operator=(HduMoveGuard &&) = delete;
733 
745  HduMoveGuard(Fits & fits, int hdu, bool relative=false);
746 
747  ~HduMoveGuard();
748 
750  void disable() { _enabled = false; }
751 
752 private:
753  Fits & _fits;
754  int _oldHdu;
755  bool _enabled;
756 };
757 
758 
759 } // namespace fits
760 } // namespace afw
761 } // namespace lsst
762 
763 #endif // !LSST_AFW_fits_h_INCLUDED
int col
Definition: CR.cc:144
void createImage(int bitpix, ndarray::Vector< ndarray::Size, N > const &shape)
Definition: fits.h:449
void writeKey(std::string const &key, char const *value)
Add a FITS header key to the bottom of the header.
Definition: fits.h:357
MemFileManager(std::size_t len)
Construct a MemFileManager with (len) bytes of initial memory.
Definition: fits.h:136
void updateKey(std::string const &key, char const *value)
Set a FITS header key, editing if it already exists and appending it if not.
Definition: fits.h:339
void writeColumnKey(std::string const &prefix, int n, char const *value)
Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.
Definition: fits.h:383
std::shared_ptr< daf::base::PropertyList > combineMetadata(std::shared_ptr< const daf::base::PropertyList > first, std::shared_ptr< const daf::base::PropertyList > second)
Combine two sets of metadata in a FITS-appropriate fashion.
Definition: fits.cc:1521
uint64_t * ptr
Definition: RangeSet.cc:88
char * data
Definition: BaseTable.cc:205
ImageCompressionOptions compression
Options controlling compression.
Definition: fits.h:219
Options for writing an image to FITS.
Definition: fits.h:218
void writeKey(std::string const &key, char const *value, std::string const &comment)
Add a FITS header key to the bottom of the header.
Definition: fits.h:352
int getBitPix()
Return the cfitsio integer BITPIX code for the given data type.
Definition: fits.cc:469
void readTableScalar(std::size_t row, int col, T &value)
Read an array scalar from a binary table.
Definition: fits.h:594
MemFileManager(void *ptr, std::size_t len)
Construct a MemFileManager that references and does not manage external memory.
Definition: fits.h:145
ImageWriteOptions(ImageCompressionOptions const &compression_=ImageCompressionOptions(ImageCompressionOptions::NONE), ImageScalingOptions const &scaling_=ImageScalingOptions())
Construct with specific compression and scaling options.
Definition: fits.h:231
ImageWriteOptions(image::Mask< T > const &mask)
Construct with default options for masks.
Definition: fits.h:228
int y
Definition: SpanSet.cc:49
void writeColumnKey(std::string const &prefix, int n, char const *value, std::string const &comment)
Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.
Definition: fits.h:378
tuple options
Definition: lsstimport.py:47
std::string prefix
Definition: SchemaMapper.cc:79
A simple struct that combines the two arguments that must be passed to most cfitsio routines and cont...
Definition: fits.h:296
The base class for all image classed (Image, Mask, MaskedImage, ...)
Definition: ImageBase.h:103
FITS BITPIX header value by C++ type.
Fits * fits
Definition: FitsWriter.cc:90
void updateKey(std::string const &key, char const *value, std::string const &comment)
Set a FITS header key, editing if it already exists and appending it if not.
Definition: fits.h:334
Reports errors in external input/output operations.
Definition: Runtime.h:160
STL class.
void readImage(ndarray::Array< T, N, N > const &array, ndarray::Vector< int, N > const &offset)
Read an array from a FITS image.
Definition: fits.h:540
MemFileManager()
Construct a MemFileManager with no initial memory buffer.
Definition: fits.h:128
ndarray::Array< T const, N, N > const makeContiguousArray(ndarray::Array< T, N, C > const &array)
Construct a contiguous ndarray.
Definition: fits.h:207
An exception thrown when problems are found when reading or writing FITS files.
Definition: fits.h:35
ndarray::Vector< ndarray::Size, N > getImageShape()
Return the shape of the current (image) HDU.
Definition: fits.h:511
Options for tile compression of image pixels.
A base class for image defects.
void createImage(long x, long y)
Create a 2-d image with pixel type provided by the given explicit PixelT template parameter...
Definition: fits.h:461
Represent a 2-dimensional array of bitmask pixels.
Definition: Mask.h:78
Lifetime-management for memory that goes into FITS memory files.
Definition: fits.h:120
void * getData() const
Return the buffer.
Definition: fits.h:190
Fits()
Default constructor; set all data members to 0.
Definition: fits.h:608
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
void reset(void *ptr, std::size_t len)
Set the internal memory buffer to an manually-managed external block.
Definition: fits.h:172
void updateColumnKey(std::string const &prefix, int n, char const *value)
Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.
Definition: fits.h:369
Options for scaling image pixels.
ImageWriteOptions(ImageScalingOptions const &scaling_)
Construct with specific scaling options.
Definition: fits.h:237
double x
void updateColumnKey(std::string const &prefix, int n, char const *value, std::string const &comment)
Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.
Definition: fits.h:364
STL class.
afw::table::Key< afw::table::Array< MaskPixelT > > mask
ImageScalingOptions scaling
Options controlling scaling.
Definition: fits.h:220
void disable()
Disable the guard, leaving the HDU at its current state at destruction.
Definition: fits.h:750
Key< U > key
Definition: Schema.cc:281
std::size_t getLength() const
Return the buffer length.
Definition: fits.h:193
void setAllowImageCompression(bool allow)
Definition: fits.cc:1439
Class for storing generic metadata.
Definition: PropertySet.h:68
An exception thrown when a FITS file has the wrong type.
Definition: fits.h:40
void reset()
Return the manager to the same state it would be if default-constructed.
Definition: fits.cc:454
void createImage(ndarray::Vector< ndarray::Size, N > const &shape)
Create an image with pixel type provided by the given explicit PixelT template parameter and shape de...
Definition: fits.h:443
MemFileManager & operator=(const MemFileManager &)=delete
bool getAllowImageCompression()
Definition: fits.cc:1441
void writeImage(ndarray::Array< T const, N, C > const &array)
Write an ndarray::Array to a FITS image HDU.
Definition: fits.h:476
#define LSST_EXCEPTION_TYPE(t, b, c)
Macro used to define new types of exceptions without additional data.
Definition: Exception.h:69
std::string makeErrorMessage(std::string const &fileName="", int status=0, std::string const &msg="")
Return an error message reflecting FITS I/O errors.
Definition: fits.cc:405
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:59
RAII scoped guard for moving the HDU in a Fits object.
Definition: fits.h:723
Base class for polymorphic functors used to iterator over FITS key headers.
Definition: fits.h:48
int end
bool strip
Definition: fits.cc:831
void writeTableScalar(std::size_t row, int col, T value)
Write a scalar value to a binary table.
Definition: fits.h:582
std::string makeLimitedFitsHeader(lsst::daf::base::PropertySet const &metadata, std::set< std::string > const &excludeNames={})
Format a PropertySet into an FITS header string in a simplistic fashion.
Definition: fits.cc:436
const int DEFAULT_HDU
Specify that the default HDU should be read.
Definition: fitsDefaults.h:18
Basic LSST definitions.
int row
Definition: CR.cc:145
std::shared_ptr< daf::base::PropertyList > readMetadata(std::string const &fileName, int hdu=DEFAULT_HDU, bool strip=false)
Read FITS header.
Definition: fits.cc:1550
ImageWriteOptions(image::Image< T > const &image)
Construct with default options for images.
Definition: fits.h:224