LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
Public Types | Public Member Functions | Public Attributes | List of all members
lsst::afw::fits::Fits Class Reference

A simple struct that combines the two arguments that must be passed to most cfitsio routines and contains thin and/or templated wrappers around common cfitsio routines. More...

#include <fits.h>

Public Types

enum  BehaviorFlags { AUTO_CLOSE = 0x01, AUTO_CHECK = 0x02 }
 

Public Member Functions

std::string getFileName () const
 Return the file name associated with the FITS object or "<unknown>" if there is none. More...
 
int getHdu ()
 Return the current HDU (0-indexed; 0 is the Primary HDU). More...
 
void setHdu (int hdu, bool relative=false)
 Set the current HDU. More...
 
int countHdus ()
 Return the number of HDUs in the file. More...
 
void writeMetadata (daf::base::PropertySet const &metadata)
 Read a FITS header into a PropertySet or PropertyList. More...
 
void readMetadata (daf::base::PropertySet &metadata, bool strip=false)
 Read a FITS header into a PropertySet or PropertyList. More...
 
template<typename T >
void readKey (std::string const &key, T &value)
 Read a FITS header key into the given reference. More...
 
void forEachKey (HeaderIterationFunctor &functor)
 Call a polymorphic functor for every key in the header. More...
 
void createEmpty ()
 Create an empty image HDU with NAXIS=0 at the end of the file. More...
 
template<typename PixelT , int N>
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 defined by an ndarray index. More...
 
template<int N>
void createImage (int bitpix, ndarray::Vector< ndarray::Size, N > const &shape)
 
template<typename PixelT >
void createImage (long x, long y)
 Create a 2-d image with pixel type provided by the given explicit PixelT template parameter. More...
 
template<typename T , int N, int C>
void writeImage (ndarray::Array< T const, N, C > const &array)
 Write an ndarray::Array to a FITS image HDU. More...
 
template<typename T >
void writeImage (image::ImageBase< T > const &image, ImageWriteOptions const &options, std::shared_ptr< daf::base::PropertySet const > header=std::shared_ptr< daf::base::PropertyList >(), std::shared_ptr< image::Mask< image::MaskPixel > const > mask=std::shared_ptr< image::Mask< image::MaskPixel >>())
 Write an image to FITS. More...
 
int getImageDim ()
 Return the number of dimensions in the current HDU. More...
 
template<int N>
ndarray::Vector< ndarray::Size, N > getImageShape ()
 Return the shape of the current (image) HDU. More...
 
template<typename T >
bool checkImageType ()
 Return true if the current HDU is compatible with the given pixel type. More...
 
std::string getImageDType ()
 Return the numpy dtype equivalent of the image pixel type (e.g. More...
 
template<typename T , int N>
void readImage (ndarray::Array< T, N, N > const &array, ndarray::Vector< int, N > const &offset)
 Read an array from a FITS image. More...
 
void createTable ()
 Create a new binary table extension. More...
 
template<typename T >
int addColumn (std::string const &ttype, int size, std::string const &comment)
 Add a column to a table. More...
 
template<typename T >
int addColumn (std::string const &ttype, int size)
 Add a column to a table. More...
 
std::size_t addRows (std::size_t nRows)
 Append rows to a table, and return the index of the first new row. More...
 
std::size_t countRows ()
 Return the number of row in a table. More...
 
template<typename T >
void writeTableArray (std::size_t row, int col, int nElements, T const *value)
 Write an array value to a binary table. More...
 
template<typename T >
void writeTableScalar (std::size_t row, int col, T value)
 Write a scalar value to a binary table. More...
 
void writeTableScalar (std::size_t row, int col, std::string const &value)
 Write a string to a binary table. More...
 
template<typename T >
void readTableArray (std::size_t row, int col, int nElements, T *value)
 Read an array value from a binary table. More...
 
template<typename T >
void readTableScalar (std::size_t row, int col, T &value)
 Read an array scalar from a binary table. More...
 
void readTableScalar (std::size_t row, int col, std::string &value, bool isVariableLength)
 Read a string from a binary table. More...
 
long getTableArraySize (int col)
 Return the size of an array column. More...
 
long getTableArraySize (std::size_t row, int col)
 Return the size of an variable-length array field. More...
 
 Fits ()
 Default constructor; set all data members to 0. More...
 
 Fits (std::string const &filename, std::string const &mode, int behavior)
 Open or create a FITS file from disk. More...
 
 Fits (MemFileManager &manager, std::string const &mode, int behavior)
 Open or create a FITS file from an in-memory file. More...
 
void closeFile ()
 Close a FITS file. More...
 
void setImageCompression (ImageCompressionOptions const &options)
 Set compression options for writing FITS images. More...
 
ImageCompressionOptions getImageCompression ()
 Return the current image compression settings. More...
 
bool checkCompressedImagePhu ()
 Go to the first image header in the FITS file. More...
 
 ~Fits ()
 
 Fits (const Fits &)=delete
 
Fitsoperator= (const Fits &)=delete
 
 Fits (Fits &&)=delete
 
Fitsoperator= (Fits &&)=delete
 
template<typename T >
void updateKey (std::string const &key, T const &value, std::string const &comment)
 Set a FITS header key, editing if it already exists and appending it if not. More...
 
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. More...
 
template<typename T >
void updateKey (std::string const &key, T const &value)
 Set a FITS header key, editing if it already exists and appending it if not. More...
 
void updateKey (std::string const &key, char const *value)
 Set a FITS header key, editing if it already exists and appending it if not. More...
 
template<typename T >
void writeKey (std::string const &key, T const &value, std::string const &comment)
 Add a FITS header key to the bottom of the header. More...
 
void writeKey (std::string const &key, char const *value, std::string const &comment)
 Add a FITS header key to the bottom of the header. More...
 
template<typename T >
void writeKey (std::string const &key, T const &value)
 Add a FITS header key to the bottom of the header. More...
 
void writeKey (std::string const &key, char const *value)
 Add a FITS header key to the bottom of the header. More...
 
template<typename T >
void updateColumnKey (std::string const &prefix, int n, T const &value, std::string const &comment)
 Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number. More...
 
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. More...
 
template<typename T >
void updateColumnKey (std::string const &prefix, int n, T const &value)
 Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number. More...
 
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. More...
 
template<typename T >
void writeColumnKey (std::string const &prefix, int n, T const &value, std::string const &comment)
 Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number. More...
 
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. More...
 
template<typename T >
void writeColumnKey (std::string const &prefix, int n, T const &value)
 Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number. More...
 
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. More...
 

Public Attributes

void * fptr
 
int status
 
int behavior
 

Detailed Description

A simple struct that combines the two arguments that must be passed to most cfitsio routines and contains thin and/or templated wrappers around common cfitsio routines.

This is NOT intended to be an object-oriented C++ wrapper around cfitsio; it's simply a thin layer that saves a lot of repetition, const/reinterpret casts, and replaces void pointer args and type codes with templates and overloads.

Like a cfitsio pointer, a Fits object always considers one HDU the "active" one, and most operations will be applied to that HDU.

All member functions are non-const because they may modify the 'status' data member.

Note
All functions that take a row or column number below are 0-indexed; the internal cfitsio calls are all 1-indexed.

Definition at line 297 of file fits.h.

Member Enumeration Documentation

◆ BehaviorFlags

Enumerator
AUTO_CLOSE 
AUTO_CHECK 

Definition at line 306 of file fits.h.

306  {
307  AUTO_CLOSE = 0x01, // Close files when the Fits object goes out of scope if fptr != NULL
308  AUTO_CHECK = 0x02 // Call LSST_FITS_CHECK_STATUS after every cfitsio call
309  };

Constructor & Destructor Documentation

◆ Fits() [1/5]

lsst::afw::fits::Fits::Fits ( )
inline

Default constructor; set all data members to 0.

Definition at line 609 of file fits.h.

609 : fptr(0), status(0), behavior(0) {}

◆ Fits() [2/5]

lsst::afw::fits::Fits::Fits ( std::string const &  filename,
std::string const &  mode,
int  behavior 
)

Open or create a FITS file from disk.

Definition at line 1535 of file fits.cc.

1536  : fptr(0), status(0), behavior(behavior_) {
1537  if (mode == "r" || mode == "rb") {
1538  fits_open_file(reinterpret_cast<fitsfile **>(&fptr), const_cast<char *>(filename.c_str()), READONLY,
1539  &status);
1540  } else if (mode == "w" || mode == "wb") {
1541  boost::filesystem::remove(filename); // cfitsio doesn't like over-writing files
1542  fits_create_file(reinterpret_cast<fitsfile **>(&fptr), const_cast<char *>(filename.c_str()), &status);
1543  } else if (mode == "a" || mode == "ab") {
1544  fits_open_file(reinterpret_cast<fitsfile **>(&fptr), const_cast<char *>(filename.c_str()), READWRITE,
1545  &status);
1546  int nHdu = 0;
1547  fits_get_num_hdus(reinterpret_cast<fitsfile *>(fptr), &nHdu, &status);
1548  fits_movabs_hdu(reinterpret_cast<fitsfile *>(fptr), nHdu, NULL, &status);
1549  if ((behavior & AUTO_CHECK) && (behavior & AUTO_CLOSE) && (status) && (fptr)) {
1550  // We're about to throw an exception, and the destructor won't get called
1551  // because we're in the constructor, so cleanup here first.
1552  int tmpStatus = 0;
1553  fits_close_file(reinterpret_cast<fitsfile *>(fptr), &tmpStatus);
1554  }
1555  } else {
1556  throw LSST_EXCEPT(
1557  FitsError,
1558  (boost::format("Invalid mode '%s' given when opening file '%s'") % mode % filename).str());
1559  }
1560  if (behavior & AUTO_CHECK) {
1561  LSST_FITS_CHECK_STATUS(*this, boost::format("Opening file '%s' with mode '%s'") % filename % mode);
1562  }
1563 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48

◆ Fits() [3/5]

lsst::afw::fits::Fits::Fits ( MemFileManager manager,
std::string const &  mode,
int  behavior 
)

Open or create a FITS file from an in-memory file.

Definition at line 1565 of file fits.cc.

1566  : fptr(0), status(0), behavior(behavior_) {
1567  typedef void *(*Reallocator)(void *, std::size_t);
1568  // It's a shame this logic is essentially a duplicate of above, but the innards are different enough
1569  // we can't really reuse it.
1570  if (mode == "r" || mode == "rb") {
1571  fits_open_memfile(reinterpret_cast<fitsfile **>(&fptr), "unused", READONLY, &manager._ptr,
1572  &manager._len, 0, 0, // no reallocator or deltasize necessary for READONLY
1573  &status);
1574  } else if (mode == "w" || mode == "wb") {
1575  Reallocator reallocator = 0;
1576  if (manager._managed) reallocator = &std::realloc;
1577  fits_create_memfile(reinterpret_cast<fitsfile **>(&fptr), &manager._ptr, &manager._len, 0,
1578  reallocator, // use default deltasize
1579  &status);
1580  } else if (mode == "a" || mode == "ab") {
1581  Reallocator reallocator = 0;
1582  if (manager._managed) reallocator = &std::realloc;
1583  fits_open_memfile(reinterpret_cast<fitsfile **>(&fptr), "unused", READWRITE, &manager._ptr,
1584  &manager._len, 0, reallocator, &status);
1585  int nHdu = 0;
1586  fits_get_num_hdus(reinterpret_cast<fitsfile *>(fptr), &nHdu, &status);
1587  fits_movabs_hdu(reinterpret_cast<fitsfile *>(fptr), nHdu, NULL, &status);
1588  if ((behavior & AUTO_CHECK) && (behavior & AUTO_CLOSE) && (status) && (fptr)) {
1589  // We're about to throw an exception, and the destructor won't get called
1590  // because we're in the constructor, so cleanup here first.
1591  int tmpStatus = 0;
1592  fits_close_file(reinterpret_cast<fitsfile *>(fptr), &tmpStatus);
1593  }
1594  } else {
1595  throw LSST_EXCEPT(FitsError,
1596  (boost::format("Invalid mode '%s' given when opening memory file at '%s'") % mode %
1597  manager._ptr)
1598  .str());
1599  }
1600  if (behavior & AUTO_CHECK) {
1602  *this, boost::format("Opening memory file at '%s' with mode '%s'") % manager._ptr % mode);
1603  }
1604 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
T realloc(T... args)

◆ ~Fits()

lsst::afw::fits::Fits::~Fits ( )
inline

Definition at line 637 of file fits.h.

637  {
638  if ((fptr) && (behavior & AUTO_CLOSE)) closeFile();
639  }
void closeFile()
Close a FITS file.
Definition: fits.cc:1606

◆ Fits() [4/5]

lsst::afw::fits::Fits::Fits ( const Fits )
delete

◆ Fits() [5/5]

lsst::afw::fits::Fits::Fits ( Fits &&  )
delete

Member Function Documentation

◆ addColumn() [1/2]

template<typename T >
int lsst::afw::fits::Fits::addColumn ( std::string const &  ttype,
int  size,
std::string const &  comment 
)

Add a column to a table.

If size <= 0, the field will be a variable length array, with max set by (-size), or left unknown if size == 0.

Definition at line 1123 of file fits.cc.

1123  {
1124  int nCols = addColumn<T>(ttype, size);
1125  updateColumnKey("TTYPE", nCols, ttype, comment);
1126  if (behavior & AUTO_CHECK) {
1127  LSST_FITS_CHECK_STATUS(*this, boost::format("Adding column '%s' with size %d") % ttype % size);
1128  }
1129  return nCols;
1130 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
void updateColumnKey(std::string const &prefix, int n, T 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.cc:690

◆ addColumn() [2/2]

template<typename T >
int lsst::afw::fits::Fits::addColumn ( std::string const &  ttype,
int  size 
)

Add a column to a table.

If size <= 0, the field will be a variable length array, with max set by (-size), or left unknown if size == 0.

Definition at line 1110 of file fits.cc.

1110  {
1111  int nCols = 0;
1112  fits_get_num_cols(reinterpret_cast<fitsfile *>(fptr), &nCols, &status);
1113  std::string tform = makeColumnFormat<T>(size);
1114  fits_insert_col(reinterpret_cast<fitsfile *>(fptr), nCols + 1, const_cast<char *>(ttype.c_str()),
1115  const_cast<char *>(tform.c_str()), &status);
1116  if (behavior & AUTO_CHECK) {
1117  LSST_FITS_CHECK_STATUS(*this, boost::format("Adding column '%s' with size %d") % ttype % size);
1118  }
1119  return nCols;
1120 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
STL class.
T c_str(T... args)

◆ addRows()

std::size_t lsst::afw::fits::Fits::addRows ( std::size_t  nRows)

Append rows to a table, and return the index of the first new row.

Definition at line 1132 of file fits.cc.

1132  {
1133  long first = 0;
1134  fits_get_num_rows(reinterpret_cast<fitsfile *>(fptr), &first, &status);
1135  fits_insert_rows(reinterpret_cast<fitsfile *>(fptr), first, nRows, &status);
1136  if (behavior & AUTO_CHECK) {
1137  LSST_FITS_CHECK_STATUS(*this, boost::format("Adding %d rows to binary table") % nRows);
1138  }
1139  return first;
1140 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ checkCompressedImagePhu()

bool lsst::afw::fits::Fits::checkCompressedImagePhu ( )

Go to the first image header in the FITS file.

If a single image is written compressed, it appears as an extension, rather than the primary HDU (PHU). This method is useful before reading an image, as it checks whether we are positioned on an empty PHU and if the next HDU is a compressed image; if so, it leaves the file pointer on the compresed image, ready for reading.

Definition at line 1709 of file fits.cc.

1709  {
1710  auto fits = reinterpret_cast<fitsfile *>(fptr);
1711  if (getHdu() != 0 || countHdus() == 1) {
1712  return false; // Can't possibly be the PHU leading a compressed image
1713  }
1714  // Check NAXIS = 0
1715  int naxis;
1716  fits_get_img_dim(fits, &naxis, &status);
1717  if (behavior & AUTO_CHECK) {
1718  LSST_FITS_CHECK_STATUS(*this, "Checking NAXIS of PHU");
1719  }
1720  if (naxis != 0) {
1721  return false;
1722  }
1723  // Check first extension (and move back there when we're done if we're not compressed)
1724  HduMoveGuard move(*this, 1);
1725  bool isCompressed = fits_is_compressed_image(fits, &status);
1726  if (behavior & AUTO_CHECK) {
1727  LSST_FITS_CHECK_STATUS(*this, "Checking compression");
1728  }
1729  if (isCompressed) {
1730  move.disable();
1731  }
1732  return isCompressed;
1733 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
Fits * fits
Definition: FitsWriter.cc:90
T move(T... args)
int getHdu()
Return the current HDU (0-indexed; 0 is the Primary HDU).
Definition: fits.cc:506
int countHdus()
Return the number of HDUs in the file.
Definition: fits.cc:533

◆ checkImageType()

template<typename T >
bool lsst::afw::fits::Fits::checkImageType ( )

Return true if the current HDU is compatible with the given pixel type.

This takes into account the BSCALE and BZERO keywords, which can allow integer images to be interpreted as floating point.

Definition at line 1418 of file fits.cc.

1418  {
1419  int imageType = 0;
1420  fits_get_img_equivtype(reinterpret_cast<fitsfile *>(fptr), &imageType, &status);
1421  if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting image type");
1423  if (imageType < 0) {
1424  return false; // can't represent floating-point with integer
1425  }
1427  if (isFitsImageTypeSigned(imageType)) {
1428  return FitsBitPix<T>::CONSTANT >= imageType;
1429  } else {
1430  // need extra bits to safely convert unsigned to signed
1431  return FitsBitPix<T>::CONSTANT > imageType;
1432  }
1433  } else {
1434  if (!isFitsImageTypeSigned(imageType)) {
1435  return FitsBitPix<T>::CONSTANT >= imageType;
1436  } else if (imageType == LONGLONG_IMG) {
1437  // workaround for CFITSIO not recognizing uint64 as
1438  // unsigned
1439  return FitsBitPix<T>::CONSTANT >= imageType;
1440  } else {
1441  return false;
1442  }
1443  }
1444  }
1445  // we allow all conversions to float and double, even if they lose precision
1446  return true;
1447 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ closeFile()

void lsst::afw::fits::Fits::closeFile ( )

Close a FITS file.

Definition at line 1606 of file fits.cc.

1606  {
1607  fits_close_file(reinterpret_cast<fitsfile *>(fptr), &status);
1608  fptr = nullptr;
1609 }

◆ countHdus()

int lsst::afw::fits::Fits::countHdus ( )

Return the number of HDUs in the file.

Definition at line 533 of file fits.cc.

533  {
534  int n = 0;
535  fits_get_num_hdus(reinterpret_cast<fitsfile *>(fptr), &n, &status);
536  if (behavior & AUTO_CHECK) {
537  LSST_FITS_CHECK_STATUS(*this, "Getting number of HDUs in file.");
538  }
539  return n;
540 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ countRows()

std::size_t lsst::afw::fits::Fits::countRows ( )

Return the number of row in a table.

Definition at line 1142 of file fits.cc.

1142  {
1143  long r = 0;
1144  fits_get_num_rows(reinterpret_cast<fitsfile *>(fptr), &r, &status);
1145  if (behavior & AUTO_CHECK) {
1146  LSST_FITS_CHECK_STATUS(*this, "Checking how many rows are in table");
1147  }
1148  return r;
1149 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ createEmpty()

void lsst::afw::fits::Fits::createEmpty ( )

Create an empty image HDU with NAXIS=0 at the end of the file.

This is primarily useful to force the first "real" HDU to be an extension HDU by creating an empty Primary HDU. The new HDU is set as the active one.

Definition at line 1223 of file fits.cc.

1223  {
1224  long naxes = 0;
1225  fits_create_img(reinterpret_cast<fitsfile *>(fptr), 8, 0, &naxes, &status);
1226  if (behavior & AUTO_CHECK) {
1227  LSST_FITS_CHECK_STATUS(*this, "Creating empty image HDU");
1228  }
1229 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ createImage() [1/3]

template<typename PixelT , int N>
void lsst::afw::fits::Fits::createImage ( ndarray::Vector< ndarray::Size, N > const &  shape)
inline

Create an image with pixel type provided by the given explicit PixelT template parameter and shape defined by an ndarray index.

Note
The shape parameter is ordered fastest-dimension last (i.e. [y, x]) as is conventional with ndarray.

The new image will be in a new HDU at the end of the file, which may be the Primary HDU if the FITS file is empty.

Definition at line 444 of file fits.h.

444  {
445  ndarray::Vector<long, N> nAxes(shape.reverse());
446  createImageImpl(detail::Bitpix<PixelT>::value, N, nAxes.elems);
447  }

◆ createImage() [2/3]

template<int N>
void lsst::afw::fits::Fits::createImage ( int  bitpix,
ndarray::Vector< ndarray::Size, N > const &  shape 
)
inline

Definition at line 450 of file fits.h.

450  {
451  ndarray::Vector<long, N> nAxes(shape.reverse());
452  createImageImpl(bitpix, N, nAxes.elems);
453  }

◆ createImage() [3/3]

template<typename PixelT >
void lsst::afw::fits::Fits::createImage ( long  x,
long  y 
)
inline

Create a 2-d image with pixel type provided by the given explicit PixelT template parameter.

The new image will be in a new HDU at the end of the file, which may be the Primary HDU if the FITS file is empty.

Definition at line 462 of file fits.h.

462  {
463  long naxes[2] = {x, y};
464  createImageImpl(detail::Bitpix<PixelT>::value, 2, naxes);
465  }
int y
Definition: SpanSet.cc:49
double x

◆ createTable()

void lsst::afw::fits::Fits::createTable ( )

Create a new binary table extension.

Definition at line 1100 of file fits.cc.

1100  {
1101  char *ttype = 0;
1102  char *tform = 0;
1103  fits_create_tbl(reinterpret_cast<fitsfile *>(fptr), BINARY_TBL, 0, 0, &ttype, &tform, 0, 0, &status);
1104  if (behavior & AUTO_CHECK) {
1105  LSST_FITS_CHECK_STATUS(*this, "Creating binary table");
1106  }
1107 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ forEachKey()

void lsst::afw::fits::Fits::forEachKey ( HeaderIterationFunctor functor)

Call a polymorphic functor for every key in the header.

Each value is passed in as a string, and the single quotes that mark an actual string value are not removed (neither are extra spaces). However, long strings that make use of the CONTINUE keyword are concatenated to look as if they were on a single line.

Definition at line 780 of file fits.cc.

780  {
781  char key[81]; // allow for terminating NUL
782  char value[81];
783  char comment[81];
784  int nKeys = 0;
785  fits_get_hdrspace(reinterpret_cast<fitsfile *>(fptr), &nKeys, 0, &status);
786  std::string keyStr;
787  std::string valueStr;
788  std::string commentStr;
789  int i = 1;
790  while (i <= nKeys) {
791  fits_read_keyn(reinterpret_cast<fitsfile *>(fptr), i, key, value, comment, &status);
792  keyStr = key;
793  valueStr = value;
794  commentStr = comment;
795  ++i;
796  while (valueStr.size() > 2 && valueStr[valueStr.size() - 2] == '&' && i <= nKeys) {
797  // we're using key to hold the entire record here; the actual key is safe in keyStr
798  fits_read_record(reinterpret_cast<fitsfile *>(fptr), i, key, &status);
799  if (strncmp(key, "CONTINUE", 8) != 0) {
800  // require both trailing '&' and CONTINUE to invoke long-string handling
801  break;
802  }
803  std::string card = key;
804  valueStr.erase(valueStr.size() - 2);
805  std::size_t firstQuote = card.find('\'');
806  if (firstQuote == std::string::npos) {
807  throw LSST_EXCEPT(
808  FitsError,
810  fptr, status,
811  boost::format("Invalid CONTINUE at header key %d: \"%s\".") % i % card));
812  }
813  std::size_t lastQuote = card.find('\'', firstQuote + 1);
814  if (lastQuote == std::string::npos) {
815  throw LSST_EXCEPT(
816  FitsError,
818  fptr, status,
819  boost::format("Invalid CONTINUE at header key %d: \"%s\".") % i % card));
820  }
821  valueStr += card.substr(firstQuote + 1, lastQuote - firstQuote);
822  std::size_t slash = card.find('/', lastQuote + 1);
823  if (slash != std::string::npos) {
824  commentStr += strip(card.substr(slash + 1));
825  }
826  ++i;
827  }
828  if (behavior & AUTO_CHECK) {
829  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading key '%s'") % keyStr);
830  }
831  functor(keyStr, valueStr, commentStr);
832  }
833 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
STL class.
T erase(T... args)
Key< U > key
Definition: Schema.cc:281
T find(T... args)
T size(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
T strncmp(T... args)
T substr(T... args)
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:425
bool strip
Definition: fits.cc:901

◆ getFileName()

std::string lsst::afw::fits::Fits::getFileName ( ) const

Return the file name associated with the FITS object or "<unknown>" if there is none.

Definition at line 497 of file fits.cc.

497  {
498  std::string fileName = "<unknown>";
499  fitsfile *fd = reinterpret_cast<fitsfile *>(fptr);
500  if (fd != 0 && fd->Fptr != 0 && fd->Fptr->filename != 0) {
501  fileName = fd->Fptr->filename;
502  }
503  return fileName;
504 }
STL class.

◆ getHdu()

int lsst::afw::fits::Fits::getHdu ( )

Return the current HDU (0-indexed; 0 is the Primary HDU).

Definition at line 506 of file fits.cc.

506  {
507  int n = 1;
508  fits_get_hdu_num(reinterpret_cast<fitsfile *>(fptr), &n);
509  return n - 1;
510 }

◆ getImageCompression()

ImageCompressionOptions lsst::afw::fits::Fits::getImageCompression ( )

Return the current image compression settings.

Definition at line 1478 of file fits.cc.

1478  {
1479  auto fits = reinterpret_cast<fitsfile *>(fptr);
1480  int compType = 0; // cfitsio compression type
1481  fits_get_compression_type(fits, &compType, &status);
1482  if (behavior & AUTO_CHECK) {
1483  LSST_FITS_CHECK_STATUS(*this, "Getting compression type");
1484  }
1485 
1486  ImageCompressionOptions::Tiles tiles = ndarray::allocate(MAX_COMPRESS_DIM);
1487  fits_get_tile_dim(fits, tiles.getNumElements(), tiles.getData(), &status);
1488  if (behavior & AUTO_CHECK) {
1489  LSST_FITS_CHECK_STATUS(*this, "Getting tile dimensions");
1490  }
1491 
1492  float quantizeLevel;
1493  fits_get_quantize_level(fits, &quantizeLevel, &status);
1494  if (behavior & AUTO_CHECK) {
1495  LSST_FITS_CHECK_STATUS(*this, "Getting quantizeLevel");
1496  }
1497 
1498  return ImageCompressionOptions(compressionAlgorithmFromCfitsio(compType), tiles, quantizeLevel);
1499 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
Fits * fits
Definition: FitsWriter.cc:90
ndarray::Array< long, 1, 1 > Tiles
ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromCfitsio(int cfitsio)
Convert compression algorithm from cfitsio to ImageCompressionOptions::CompressionAlgorithm.

◆ getImageDim()

int lsst::afw::fits::Fits::getImageDim ( )

Return the number of dimensions in the current HDU.

Definition at line 1405 of file fits.cc.

1405  {
1406  int nAxis = 0;
1407  fits_get_img_dim(reinterpret_cast<fitsfile *>(fptr), &nAxis, &status);
1408  if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting NAXIS");
1409  return nAxis;
1410 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ getImageDType()

std::string lsst::afw::fits::Fits::getImageDType ( )

Return the numpy dtype equivalent of the image pixel type (e.g.

"uint16", "float64").

Definition at line 1449 of file fits.cc.

1449  {
1450  int bitpix = 0;
1451  fits_get_img_equivtype(reinterpret_cast<fitsfile *>(fptr), &bitpix, &status);
1452  if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting image type");
1453  // FITS' 'BITPIX' key is the number of bits in a pixel, but negative for
1454  // floats. But the above CFITSIO routine adds support for unsigned
1455  // integers by checking BZERO for an offset as well. So the 'bitpix' value
1456  // we get back from that should be the raw value for signed integers and
1457  // floats, but may be something else (still positive) for unsigned, and
1458  // hence we'll compare to some FITSIO constants to be safe looking at
1459  // integers.
1460  if (bitpix < 0) {
1461  return "float" + std::to_string(-bitpix);
1462  }
1463  switch (bitpix) {
1464  case BYTE_IMG: return "uint8";
1465  case SBYTE_IMG: return "int8";
1466  case SHORT_IMG: return "int16";
1467  case USHORT_IMG: return "uint16";
1468  case LONG_IMG: return "int32";
1469  case ULONG_IMG: return "uint32";
1470  case LONGLONG_IMG: return "int64";
1471  }
1472  throw LSST_EXCEPT(
1473  FitsError,
1474  (boost::format("Unrecognized BITPIX value: %d") % bitpix).str()
1475  );
1476 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
T to_string(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48

◆ getImageShape()

template<int N>
ndarray::Vector<ndarray::Size, N> lsst::afw::fits::Fits::getImageShape ( )
inline

Return the shape of the current (image) HDU.

The order of dimensions is reversed from the FITS ordering, reflecting the usual (y,x) ndarray convention.

The template parameter must match the actual number of dimension in the image.

Definition at line 512 of file fits.h.

512  {
513  ndarray::Vector<long, N> nAxes(1);
514  getImageShapeImpl(N, nAxes.elems);
515  ndarray::Vector<ndarray::Size, N> shape;
516  for (int i = 0; i < N; ++i) shape[i] = nAxes[N - i - 1];
517  return shape;
518  }

◆ getTableArraySize() [1/2]

long lsst::afw::fits::Fits::getTableArraySize ( int  col)

Return the size of an array column.

Definition at line 1200 of file fits.cc.

1200  {
1201  int typecode = 0;
1202  long result = 0;
1203  long width = 0;
1204  fits_get_coltype(reinterpret_cast<fitsfile *>(fptr), col + 1, &typecode, &result, &width, &status);
1205  if (behavior & AUTO_CHECK) {
1206  LSST_FITS_CHECK_STATUS(*this, boost::format("Looking up array size for column %d") % col);
1207  }
1208  return result;
1209 }
int col
Definition: CR.cc:144
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
py::object result
Definition: _schema.cc:429

◆ getTableArraySize() [2/2]

long lsst::afw::fits::Fits::getTableArraySize ( std::size_t  row,
int  col 
)

Return the size of an variable-length array field.

Definition at line 1211 of file fits.cc.

1211  {
1212  long result = 0;
1213  long offset = 0;
1214  fits_read_descript(reinterpret_cast<fitsfile *>(fptr), col + 1, row + 1, &result, &offset, &status);
1215  if (behavior & AUTO_CHECK) {
1216  LSST_FITS_CHECK_STATUS(*this, boost::format("Looking up array size for cell (%d, %d)") % row % col);
1217  }
1218  return result;
1219 }
int col
Definition: CR.cc:144
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
py::object result
Definition: _schema.cc:429

◆ operator=() [1/2]

Fits& lsst::afw::fits::Fits::operator= ( const Fits )
delete

◆ operator=() [2/2]

Fits& lsst::afw::fits::Fits::operator= ( Fits &&  )
delete

◆ readImage()

template<typename T , int N>
void lsst::afw::fits::Fits::readImage ( ndarray::Array< T, N, N > const &  array,
ndarray::Vector< int, N > const &  offset 
)
inline

Read an array from a FITS image.

Parameters
[out]arrayArray to be filled. Must already be allocated to the desired shape.
[in]offsetIndices of the first pixel to be read from the image.

Definition at line 541 of file fits.h.

541  {
542  ndarray::Vector<long, N> begin(offset.reverse());
543  ndarray::Vector<long, N> end(begin);
544  end += array.getShape().reverse();
545  ndarray::Vector<long, N> increment(1);
546  begin += increment; // first FITS pixel is 1, not 0
547  readImageImpl(N, array.getData(), begin.elems, end.elems, increment.elems);
548  }
T begin(T... args)
int end

◆ readKey()

template<typename T >
void lsst::afw::fits::Fits::readKey ( std::string const &  key,
T &  value 
)

Read a FITS header key into the given reference.

Definition at line 773 of file fits.cc.

773  {
774  readKeyImpl(*this, key.c_str(), value);
775  if (behavior & AUTO_CHECK) {
776  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading key '%s'") % key);
777  }
778 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
Key< U > key
Definition: Schema.cc:281

◆ readMetadata()

void lsst::afw::fits::Fits::readMetadata ( daf::base::PropertySet metadata,
bool  strip = false 
)

Read a FITS header into a PropertySet or PropertyList.

Parameters
[in,out]metadataA PropertySet or PropertyList that FITS header items will be added to.
[in]stripIf true, common FITS keys that usually have non-metadata intepretations (e.g. NAXIS, BITPIX) will be ignored.

Order will preserved if and only if the metadata object is actually a PropertyList.

Definition at line 1070 of file fits.cc.

1070  {
1071  MetadataIterationFunctor f;
1072  f.strip = strip;
1073  f.set = &metadata;
1074  f.list = dynamic_cast<daf::base::PropertyList *>(&metadata);
1075  forEachKey(f);
1076 }
void forEachKey(HeaderIterationFunctor &functor)
Call a polymorphic functor for every key in the header.
Definition: fits.cc:780
bool strip
Definition: fits.cc:901

◆ readTableArray()

template<typename T >
void lsst::afw::fits::Fits::readTableArray ( std::size_t  row,
int  col,
int  nElements,
T *  value 
)

Read an array value from a binary table.

Definition at line 1175 of file fits.cc.

1175  {
1176  int anynul = false;
1177  fits_read_col(reinterpret_cast<fitsfile *>(fptr), FitsTableType<T>::CONSTANT, col + 1, row + 1, 1,
1178  nElements, 0, value, &anynul, &status);
1179  if (behavior & AUTO_CHECK) {
1180  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading value at table cell (%d, %d)") % row % col);
1181  }
1182 }
int col
Definition: CR.cc:144
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ readTableScalar() [1/2]

template<typename T >
void lsst::afw::fits::Fits::readTableScalar ( std::size_t  row,
int  col,
T &  value 
)
inline

Read an array scalar from a binary table.

Definition at line 595 of file fits.h.

595  {
596  readTableArray(row, col, 1, &value);
597  }
int col
Definition: CR.cc:144
void readTableArray(std::size_t row, int col, int nElements, T *value)
Read an array value from a binary table.
Definition: fits.cc:1175

◆ readTableScalar() [2/2]

void lsst::afw::fits::Fits::readTableScalar ( std::size_t  row,
int  col,
std::string value,
bool  isVariableLength 
)

Read a string from a binary table.

Definition at line 1184 of file fits.cc.

1184  {
1185  int anynul = false;
1186  long size = isVariableLength ? getTableArraySize(row, col) : getTableArraySize(col);
1187  // We can't directly write into a std::string until C++17.
1188  std::vector<char> buf(size + 1, 0);
1189  // cfitsio wants a char** because they imagine we might want an array of strings,
1190  // but we only want one element.
1191  char *tmp = &buf.front();
1192  fits_read_col(reinterpret_cast<fitsfile *>(fptr), TSTRING, col + 1, row + 1, 1, 1, 0, &tmp, &anynul,
1193  &status);
1194  if (behavior & AUTO_CHECK) {
1195  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading value at table cell (%d, %d)") % row % col);
1196  }
1197  value = std::string(tmp);
1198 }
int col
Definition: CR.cc:144
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
long getTableArraySize(int col)
Return the size of an array column.
Definition: fits.cc:1200
STL class.
STL class.

◆ setHdu()

void lsst::afw::fits::Fits::setHdu ( int  hdu,
bool  relative = false 
)

Set the current HDU.

Parameters
[in]hduThe HDU to move to (0-indexed; 0 is the Primary HDU). The special value of DEFAULT_HDU moves to the first extension if the Primary HDU is empty (has NAXIS==0) and the the Primary HDU is the current one.
[in]relativeIf true, move relative to the current HDU.

Definition at line 512 of file fits.cc.

512  {
513  if (relative) {
514  fits_movrel_hdu(reinterpret_cast<fitsfile *>(fptr), hdu, 0, &status);
515  if (behavior & AUTO_CHECK) {
516  LSST_FITS_CHECK_STATUS(*this, boost::format("Incrementing HDU by %d") % hdu);
517  }
518  } else {
519  if (hdu != DEFAULT_HDU) {
520  fits_movabs_hdu(reinterpret_cast<fitsfile *>(fptr), hdu + 1, 0, &status);
521  }
522  if (hdu == DEFAULT_HDU && getHdu() == 0 && getImageDim() == 0) {
523  // want a silent failure here
524  int tmpStatus = status;
525  fits_movrel_hdu(reinterpret_cast<fitsfile *>(fptr), 1, 0, &tmpStatus);
526  }
527  if (behavior & AUTO_CHECK) {
528  LSST_FITS_CHECK_STATUS(*this, boost::format("Moving to HDU %d") % hdu);
529  }
530  }
531 }
int getImageDim()
Return the number of dimensions in the current HDU.
Definition: fits.cc:1405
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
int getHdu()
Return the current HDU (0-indexed; 0 is the Primary HDU).
Definition: fits.cc:506
const int DEFAULT_HDU
Specify that the default HDU should be read.
Definition: fitsDefaults.h:18

◆ setImageCompression()

void lsst::afw::fits::Fits::setImageCompression ( ImageCompressionOptions const &  options)

Set compression options for writing FITS images.

See also
ImageCompressionContext

Definition at line 1501 of file fits.cc.

1501  {
1502  auto fits = reinterpret_cast<fitsfile *>(fptr);
1503  fits_unset_compression_request(fits, &status); // wipe the slate and start over
1505  allowImageCompression ? comp.algorithm : ImageCompressionOptions::NONE;
1506  fits_set_compression_type(fits, compressionAlgorithmToCfitsio(algorithm), &status);
1507  if (behavior & AUTO_CHECK) {
1508  LSST_FITS_CHECK_STATUS(*this, "Setting compression type");
1509  }
1510 
1511  if (algorithm == ImageCompressionOptions::NONE) {
1512  // Nothing else worth doing
1513  return;
1514  }
1515 
1516  fits_set_tile_dim(fits, comp.tiles.getNumElements(), comp.tiles.getData(), &status);
1517  if (behavior & AUTO_CHECK) {
1518  LSST_FITS_CHECK_STATUS(*this, "Setting tile dimensions");
1519  }
1520 
1521  if (comp.algorithm != ImageCompressionOptions::PLIO && std::isfinite(comp.quantizeLevel)) {
1522  fits_set_quantize_level(fits, comp.quantizeLevel, &status);
1523  if (behavior & AUTO_CHECK) {
1524  LSST_FITS_CHECK_STATUS(*this, "Setting quantization level");
1525  }
1526  }
1527 }
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
int compressionAlgorithmToCfitsio(ImageCompressionOptions::CompressionAlgorithm algorithm)
Convert ImageCompressionOptions::CompressionAlgorithm to cfitsio.
CompressionAlgorithm
Compression algorithms.
Fits * fits
Definition: FitsWriter.cc:90
T isfinite(T... args)

◆ updateColumnKey() [1/4]

template<typename T >
void lsst::afw::fits::Fits::updateColumnKey ( std::string const &  prefix,
int  n,
T 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 at line 690 of file fits.cc.

690  {
691  updateKey((boost::format("%s%d") % prefix % (n + 1)).str(), value, comment);
692  if (behavior & AUTO_CHECK) {
693  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s%d': '%s'") % prefix % (n + 1) % value);
694  }
695 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
void updateKey(std::string const &key, T const &value, std::string const &comment)
Set a FITS header key, editing if it already exists and appending it if not.
Definition: fits.cc:658
std::string prefix
Definition: SchemaMapper.cc:79

◆ updateColumnKey() [2/4]

void lsst::afw::fits::Fits::updateColumnKey ( std::string const &  prefix,
int  n,
char const *  value,
std::string const &  comment 
)
inline

Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.

Definition at line 365 of file fits.h.

365  {
366  updateColumnKey(prefix, n, std::string(value), comment);
367  }
void updateColumnKey(std::string const &prefix, int n, T 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.cc:690
STL class.
std::string prefix
Definition: SchemaMapper.cc:79

◆ updateColumnKey() [3/4]

template<typename T >
void lsst::afw::fits::Fits::updateColumnKey ( std::string const &  prefix,
int  n,
T const &  value 
)

Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.

Definition at line 706 of file fits.cc.

706  {
707  updateKey((boost::format("%s%d") % prefix % (n + 1)).str(), value);
708  if (behavior & AUTO_CHECK) {
709  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s%d': '%s'") % prefix % (n + 1) % value);
710  }
711 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
void updateKey(std::string const &key, T const &value, std::string const &comment)
Set a FITS header key, editing if it already exists and appending it if not.
Definition: fits.cc:658
std::string prefix
Definition: SchemaMapper.cc:79

◆ updateColumnKey() [4/4]

void lsst::afw::fits::Fits::updateColumnKey ( std::string const &  prefix,
int  n,
char const *  value 
)
inline

Update a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.

Definition at line 370 of file fits.h.

370  {
371  updateColumnKey(prefix, n, std::string(value));
372  }
void updateColumnKey(std::string const &prefix, int n, T 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.cc:690
STL class.
std::string prefix
Definition: SchemaMapper.cc:79

◆ updateKey() [1/4]

template<typename T >
void lsst::afw::fits::Fits::updateKey ( std::string const &  key,
T const &  value,
std::string const &  comment 
)

Set a FITS header key, editing if it already exists and appending it if not.

Definition at line 658 of file fits.cc.

658  {
659  updateKeyImpl(*this, key.c_str(), value, comment.c_str());
660  if (behavior & AUTO_CHECK) {
661  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s': '%s'") % key % value);
662  }
663 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
Key< U > key
Definition: Schema.cc:281

◆ updateKey() [2/4]

void lsst::afw::fits::Fits::updateKey ( std::string const &  key,
char const *  value,
std::string const &  comment 
)
inline

Set a FITS header key, editing if it already exists and appending it if not.

Definition at line 335 of file fits.h.

335  {
336  updateKey(key, std::string(value), comment);
337  }
void updateKey(std::string const &key, T const &value, std::string const &comment)
Set a FITS header key, editing if it already exists and appending it if not.
Definition: fits.cc:658
STL class.
Key< U > key
Definition: Schema.cc:281

◆ updateKey() [3/4]

template<typename T >
void lsst::afw::fits::Fits::updateKey ( std::string const &  key,
T const &  value 
)

Set a FITS header key, editing if it already exists and appending it if not.

Definition at line 674 of file fits.cc.

674  {
675  updateKeyImpl(*this, key.c_str(), value, 0);
676  if (behavior & AUTO_CHECK) {
677  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s': '%s'") % key % value);
678  }
679 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
Key< U > key
Definition: Schema.cc:281

◆ updateKey() [4/4]

void lsst::afw::fits::Fits::updateKey ( std::string const &  key,
char const *  value 
)
inline

Set a FITS header key, editing if it already exists and appending it if not.

Definition at line 340 of file fits.h.

340 { updateKey(key, std::string(value)); }
void updateKey(std::string const &key, T const &value, std::string const &comment)
Set a FITS header key, editing if it already exists and appending it if not.
Definition: fits.cc:658
STL class.
Key< U > key
Definition: Schema.cc:281

◆ writeColumnKey() [1/4]

template<typename T >
void lsst::afw::fits::Fits::writeColumnKey ( std::string const &  prefix,
int  n,
T 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 at line 698 of file fits.cc.

698  {
699  writeKey((boost::format("%s%d") % prefix % (n + 1)).str(), value, comment);
700  if (behavior & AUTO_CHECK) {
701  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s%d': '%s'") % prefix % (n + 1) % value);
702  }
703 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
std::string prefix
Definition: SchemaMapper.cc:79
void writeKey(std::string const &key, T const &value, std::string const &comment)
Add a FITS header key to the bottom of the header.
Definition: fits.cc:666

◆ writeColumnKey() [2/4]

void lsst::afw::fits::Fits::writeColumnKey ( std::string const &  prefix,
int  n,
char const *  value,
std::string const &  comment 
)
inline

Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.

Definition at line 379 of file fits.h.

379  {
380  writeColumnKey(prefix, n, std::string(value), comment);
381  }
void writeColumnKey(std::string const &prefix, int n, T 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.cc:698
STL class.
std::string prefix
Definition: SchemaMapper.cc:79

◆ writeColumnKey() [3/4]

template<typename T >
void lsst::afw::fits::Fits::writeColumnKey ( std::string const &  prefix,
int  n,
T const &  value 
)

Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.

Definition at line 714 of file fits.cc.

714  {
715  writeKey((boost::format("%s%d") % prefix % (n + 1)).str(), value);
716  if (behavior & AUTO_CHECK) {
717  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s%d': '%s'") % prefix % (n + 1) % value);
718  }
719 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
std::string prefix
Definition: SchemaMapper.cc:79
void writeKey(std::string const &key, T const &value, std::string const &comment)
Add a FITS header key to the bottom of the header.
Definition: fits.cc:666

◆ writeColumnKey() [4/4]

void lsst::afw::fits::Fits::writeColumnKey ( std::string const &  prefix,
int  n,
char const *  value 
)
inline

Write a key of the form XXXXXnnn, where XXXXX is the prefix and nnn is a column number.

Definition at line 384 of file fits.h.

384  {
385  writeColumnKey(prefix, n, std::string(value));
386  }
void writeColumnKey(std::string const &prefix, int n, T 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.cc:698
STL class.
std::string prefix
Definition: SchemaMapper.cc:79

◆ writeImage() [1/2]

template<typename T , int N, int C>
void lsst::afw::fits::Fits::writeImage ( ndarray::Array< T const, N, C > const &  array)
inline

Write an ndarray::Array to a FITS image HDU.

The HDU must already exist and have the correct bitpix.

An extra deep-copy may be necessary if the array is not fully contiguous.

No compression or scaling is performed.

Definition at line 477 of file fits.h.

477  {
478  writeImageImpl(makeContiguousArray(array).getData(), array.getNumElements());
479  }
ndarray::Array< T const, N, N > const makeContiguousArray(ndarray::Array< T, N, C > const &array)
Construct a contiguous ndarray.
Definition: fits.h:208

◆ writeImage() [2/2]

template<typename T >
void lsst::afw::fits::Fits::writeImage ( image::ImageBase< T > const &  image,
ImageWriteOptions const &  options,
std::shared_ptr< daf::base::PropertySet const >  header = std::shared_ptr<daf::base::PropertyList>(),
std::shared_ptr< image::Mask< image::MaskPixel > const >  mask = std::shared_ptr<image::Mask<image::MaskPixel>>() 
)

Write an image to FITS.

This method is all-inclusive, and covers creating the HDU (with the correct BITPIX), writing the header and optional scaling and compression of the image.

Parameters
[in]imageImage to write to FITS.
[in]optionsOptions controlling the write (scaling, compression).
[in]headerFITS header to write.
[in]maskMask for image (used for statistics when scaling).

Definition at line 1279 of file fits.cc.

1281  {
1282  auto fits = reinterpret_cast<fitsfile *>(fptr);
1283  ImageCompressionOptions const &compression =
1284  image.getBBox().getArea() > 0
1285  ? options.compression
1286  : ImageCompressionOptions(
1287  ImageCompressionOptions::NONE); // cfitsio can't compress empty images
1288  ImageCompressionContext comp(*this, compression); // RAII
1289  if (behavior & AUTO_CHECK) {
1290  LSST_FITS_CHECK_STATUS(*this, "Activating compression for write image");
1291  }
1292 
1293  ImageScale scale = options.scaling.determine(image, mask);
1294 
1295  // We need a place to put the image+header, and CFITSIO needs to know the dimenions.
1296  ndarray::Vector<long, 2> dims(image.getArray().getShape().reverse());
1297  createImageImpl(scale.bitpix == 0 ? detail::Bitpix<T>::value : scale.bitpix, 2, dims.elems);
1298 
1299  // Write the header
1302  if (header) {
1303  std::shared_ptr<daf::base::PropertySet> copy = header->deepCopy();
1304  copy->combine(wcsMetadata);
1305  header = copy;
1306  } else {
1307  header = wcsMetadata;
1308  }
1309  writeMetadata(*header);
1310 
1311  // Scale the image how we want it on disk
1312  ndarray::Array<T const, 2, 2> array = makeContiguousArray(image.getArray());
1313  auto pixels = scale.toFits(array, compression.quantizeLevel != 0, options.scaling.fuzz,
1314  options.compression.tiles, options.scaling.seed);
1315 
1316  // We only want cfitsio to do the scale and zero for unsigned 64-bit integer types. For those,
1317  // "double bzero" has sufficient precision to represent the appropriate value. We'll let
1318  // cfitsio handle it itself.
1319  // In all other cases, we will convert the image to use the appropriate scale and zero
1320  // (because we want to fuzz the numbers in the quantisation), so we don't want cfitsio
1321  // rescaling.
1323  fits_set_bscale(fits, 1.0, 0.0, &status);
1324  if (behavior & AUTO_CHECK) {
1325  LSST_FITS_CHECK_STATUS(*this, "Setting bscale,bzero");
1326  }
1327  }
1328 
1329  // Write the pixels
1330  int const fitsType = scale.bitpix == 0 ? FitsType<T>::CONSTANT : fitsTypeForBitpix(scale.bitpix);
1331  fits_write_img(fits, fitsType, 1, pixels->getNumElements(), const_cast<void *>(pixels->getData()),
1332  &status);
1333  if (behavior & AUTO_CHECK) {
1334  LSST_FITS_CHECK_STATUS(*this, "Writing image");
1335  }
1336 
1337  // Now write the headers we didn't want cfitsio to know about when we were writing the pixels
1338  // (because we don't want it using them to modify the pixels, and we don't want it overwriting
1339  // these values).
1341  std::isfinite(scale.bzero) && std::isfinite(scale.bscale) && (scale.bscale != 0.0)) {
1343  if (scale.bzero != 0.0) {
1344  fits_write_key_lng(fits, "BZERO", static_cast<long>(scale.bzero),
1345  "Scaling: MEMORY = BZERO + BSCALE * DISK", &status);
1346  }
1347  if (scale.bscale != 1.0) {
1348  fits_write_key_lng(fits, "BSCALE", static_cast<long>(scale.bscale),
1349  "Scaling: MEMORY = BZERO + BSCALE * DISK", &status);
1350  }
1351  } else {
1352  fits_write_key_dbl(fits, "BZERO", scale.bzero, 12, "Scaling: MEMORY = BZERO + BSCALE * DISK",
1353  &status);
1354  fits_write_key_dbl(fits, "BSCALE", scale.bscale, 12, "Scaling: MEMORY = BZERO + BSCALE * DISK",
1355  &status);
1356  }
1357  if (behavior & AUTO_CHECK) {
1358  LSST_FITS_CHECK_STATUS(*this, "Writing BSCALE,BZERO");
1359  }
1360  }
1361 
1362  if (scale.bitpix > 0 && !std::numeric_limits<T>::is_integer) {
1363  fits_write_key_lng(fits, "BLANK", scale.blank, "Value for undefined pixels", &status);
1364  fits_write_key_lng(fits, "ZDITHER0", options.scaling.seed, "Dithering seed", &status);
1365  fits_write_key_str(fits, "ZQUANTIZ", "SUBTRACTIVE_DITHER_1", "Dithering algorithm", &status);
1366  if (behavior & AUTO_CHECK) {
1367  LSST_FITS_CHECK_STATUS(*this, "Writing [Z]BLANK");
1368  }
1369  }
1370 
1371  // cfitsio says this is deprecated, but Pan-STARRS found that it was sometimes necessary, writing:
1372  // "This forces a re-scan of the header to ensure everything's kosher.
1373  // Without this, compressed HDUs have been written out with PCOUNT=0 and TFORM1 not correctly set."
1374  fits_set_hdustruc(fits, &status);
1375  if (behavior & AUTO_CHECK) {
1376  LSST_FITS_CHECK_STATUS(*this, "Finalizing header");
1377  }
1378 }
T copy(T... args)
void writeMetadata(daf::base::PropertySet const &metadata)
Read a FITS header into a PropertySet or PropertyList.
Definition: fits.cc:1078
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
def scale(algorithm, min, max=None, frame=None)
Definition: ds9.py:109
Fits * fits
Definition: FitsWriter.cc:90
ndarray::Array< T const, N, N > const makeContiguousArray(ndarray::Array< T, N, C > const &array)
Construct a contiguous ndarray.
Definition: fits.h:208
lsst::geom::Box2I getBBox(ImageOrigin origin=PARENT) const
Definition: ImageBase.h:482
std::shared_ptr< daf::base::PropertyList > createTrivialWcsMetadata(std::string const &wcsName, lsst::geom::Point2I const &xy0)
Definition: wcsUtils.cc:51
int getArea() const
Definition: Box.h:189
T isfinite(T... args)
lsst::geom::Point2I getXY0() const
Return the image&#39;s origin.
Definition: ImageBase.h:360
std::string const wcsNameForXY0
Definition: ImageBase.h:70

◆ writeKey() [1/4]

template<typename T >
void lsst::afw::fits::Fits::writeKey ( std::string const &  key,
T const &  value,
std::string const &  comment 
)

Add a FITS header key to the bottom of the header.

If the key is HISTORY or COMMENT and the value is a std::string or C-string, a special HISTORY or COMMENT key will be appended (and the comment argument will be ignored if present).

Definition at line 666 of file fits.cc.

666  {
667  writeKeyImpl(*this, key.c_str(), value, comment.c_str());
668  if (behavior & AUTO_CHECK) {
669  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s': '%s'") % key % value);
670  }
671 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
Key< U > key
Definition: Schema.cc:281

◆ writeKey() [2/4]

void lsst::afw::fits::Fits::writeKey ( std::string const &  key,
char const *  value,
std::string const &  comment 
)
inline

Add a FITS header key to the bottom of the header.

If the key is HISTORY or COMMENT and the value is a std::string or C-string, a special HISTORY or COMMENT key will be appended (and the comment argument will be ignored if present).

Definition at line 353 of file fits.h.

353  {
354  writeKey(key, std::string(value), comment);
355  }
STL class.
Key< U > key
Definition: Schema.cc:281
void writeKey(std::string const &key, T const &value, std::string const &comment)
Add a FITS header key to the bottom of the header.
Definition: fits.cc:666

◆ writeKey() [3/4]

template<typename T >
void lsst::afw::fits::Fits::writeKey ( std::string const &  key,
T const &  value 
)

Add a FITS header key to the bottom of the header.

If the key is HISTORY or COMMENT and the value is a std::string or C-string, a special HISTORY or COMMENT key will be appended (and the comment argument will be ignored if present).

Definition at line 682 of file fits.cc.

682  {
683  writeKeyImpl(*this, key.c_str(), value, 0);
684  if (behavior & AUTO_CHECK) {
685  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s': '%s'") % key % value);
686  }
687 }
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111
Key< U > key
Definition: Schema.cc:281

◆ writeKey() [4/4]

void lsst::afw::fits::Fits::writeKey ( std::string const &  key,
char const *  value 
)
inline

Add a FITS header key to the bottom of the header.

If the key is HISTORY or COMMENT and the value is a std::string or C-string, a special HISTORY or COMMENT key will be appended (and the comment argument will be ignored if present).

Definition at line 358 of file fits.h.

358 { writeKey(key, std::string(value)); }
STL class.
Key< U > key
Definition: Schema.cc:281
void writeKey(std::string const &key, T const &value, std::string const &comment)
Add a FITS header key to the bottom of the header.
Definition: fits.cc:666

◆ writeMetadata()

void lsst::afw::fits::Fits::writeMetadata ( daf::base::PropertySet const &  metadata)

Read a FITS header into a PropertySet or PropertyList.

Parameters
[in]metadataA PropertySet or PropertyList whose items will be appended to the FITS header.

All keys will be appended to the FITS header rather than used to update existing keys. Order of keys will be preserved if and only if the metadata object is actually a PropertyList.

Definition at line 1078 of file fits.cc.

1078  {
1079  typedef std::vector<std::string> NameList;
1080  daf::base::PropertyList const *pl = dynamic_cast<daf::base::PropertyList const *>(&metadata);
1081  NameList paramNames;
1082  if (pl) {
1083  paramNames = pl->getOrderedNames();
1084  } else {
1085  paramNames = metadata.paramNames(false);
1086  }
1087  for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1088  if (!isKeyIgnored(*i, true)) {
1089  if (pl) {
1090  writeKeyFromProperty(*this, metadata, *i, pl->getComment(*i).c_str());
1091  } else {
1092  writeKeyFromProperty(*this, metadata, *i);
1093  }
1094  }
1095  }
1096 }

◆ writeTableArray()

template<typename T >
void lsst::afw::fits::Fits::writeTableArray ( std::size_t  row,
int  col,
int  nElements,
T const *  value 
)

Write an array value to a binary table.

Definition at line 1152 of file fits.cc.

1152  {
1153  fits_write_col(reinterpret_cast<fitsfile *>(fptr), FitsTableType<T>::CONSTANT, col + 1, row + 1, 1,
1154  nElements, const_cast<T *>(value), &status);
1155  if (behavior & AUTO_CHECK) {
1156  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing %d-element array at table cell (%d, %d)") %
1157  nElements % row % col);
1158  }
1159 }
int col
Definition: CR.cc:144
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

◆ writeTableScalar() [1/2]

template<typename T >
void lsst::afw::fits::Fits::writeTableScalar ( std::size_t  row,
int  col,
value 
)
inline

Write a scalar value to a binary table.

Definition at line 583 of file fits.h.

583  {
584  writeTableArray(row, col, 1, &value);
585  }
int col
Definition: CR.cc:144
void writeTableArray(std::size_t row, int col, int nElements, T const *value)
Write an array value to a binary table.
Definition: fits.cc:1152

◆ writeTableScalar() [2/2]

void lsst::afw::fits::Fits::writeTableScalar ( std::size_t  row,
int  col,
std::string const &  value 
)

Write a string to a binary table.

Definition at line 1161 of file fits.cc.

1161  {
1162  // cfitsio doesn't let us specify the size of a string, it just looks for null terminator.
1163  // Using std::string::c_str() guarantees that we have one. But we can't store arbitrary
1164  // data in a string field because cfitsio will also chop off anything after the first null
1165  // terminator.
1166  char const *tmp = value.c_str();
1167  fits_write_col(reinterpret_cast<fitsfile *>(fptr), TSTRING, col + 1, row + 1, 1, 1,
1168  const_cast<char const **>(&tmp), &status);
1169  if (behavior & AUTO_CHECK) {
1170  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing value at table cell (%d, %d)") % row % col);
1171  }
1172 }
int col
Definition: CR.cc:144
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:174
#define LSST_FITS_CHECK_STATUS(fitsObj,...)
Throw a FitsError exception if the status of the given Fits object is nonzero.
Definition: fits.h:111

Member Data Documentation

◆ behavior

int lsst::afw::fits::Fits::behavior

Definition at line 651 of file fits.h.

◆ fptr

void* lsst::afw::fits::Fits::fptr

Definition at line 649 of file fits.h.

◆ status

int lsst::afw::fits::Fits::status

Definition at line 650 of file fits.h.


The documentation for this class was generated from the following files: