LSSTApplications  17.0+11,17.0+34,17.0+56,17.0+57,17.0+59,17.0+7,17.0-1-g377950a+33,17.0.1-1-g114240f+2,17.0.1-1-g4d4fbc4+28,17.0.1-1-g55520dc+49,17.0.1-1-g5f4ed7e+52,17.0.1-1-g6dd7d69+17,17.0.1-1-g8de6c91+11,17.0.1-1-gb9095d2+7,17.0.1-1-ge9fec5e+5,17.0.1-1-gf4e0155+55,17.0.1-1-gfc65f5f+50,17.0.1-1-gfc6fb1f+20,17.0.1-10-g87f9f3f+1,17.0.1-11-ge9de802+16,17.0.1-16-ga14f7d5c+4,17.0.1-17-gc79d625+1,17.0.1-17-gdae4c4a+8,17.0.1-2-g26618f5+29,17.0.1-2-g54f2ebc+9,17.0.1-2-gf403422+1,17.0.1-20-g2ca2f74+6,17.0.1-23-gf3eadeb7+1,17.0.1-3-g7e86b59+39,17.0.1-3-gb5ca14a,17.0.1-3-gd08d533+40,17.0.1-30-g596af8797,17.0.1-4-g59d126d+4,17.0.1-4-gc69c472+5,17.0.1-6-g5afd9b9+4,17.0.1-7-g35889ee+1,17.0.1-7-gc7c8782+18,17.0.1-9-gc4bbfb2+3,w.2019.22
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 1511 of file fits.cc.

1512  : fptr(0), status(0), behavior(behavior_) {
1513  if (mode == "r" || mode == "rb") {
1514  fits_open_file(reinterpret_cast<fitsfile **>(&fptr), const_cast<char *>(filename.c_str()), READONLY,
1515  &status);
1516  } else if (mode == "w" || mode == "wb") {
1517  boost::filesystem::remove(filename); // cfitsio doesn't like over-writing files
1518  fits_create_file(reinterpret_cast<fitsfile **>(&fptr), const_cast<char *>(filename.c_str()), &status);
1519  } else if (mode == "a" || mode == "ab") {
1520  fits_open_file(reinterpret_cast<fitsfile **>(&fptr), const_cast<char *>(filename.c_str()), READWRITE,
1521  &status);
1522  int nHdu = 0;
1523  fits_get_num_hdus(reinterpret_cast<fitsfile *>(fptr), &nHdu, &status);
1524  fits_movabs_hdu(reinterpret_cast<fitsfile *>(fptr), nHdu, NULL, &status);
1525  if ((behavior & AUTO_CHECK) && (behavior & AUTO_CLOSE) && (status) && (fptr)) {
1526  // We're about to throw an exception, and the destructor won't get called
1527  // because we're in the constructor, so cleanup here first.
1528  int tmpStatus = 0;
1529  fits_close_file(reinterpret_cast<fitsfile *>(fptr), &tmpStatus);
1530  }
1531  } else {
1532  throw LSST_EXCEPT(
1533  FitsError,
1534  (boost::format("Invalid mode '%s' given when opening file '%s'") % mode % filename).str());
1535  }
1536  if (behavior & AUTO_CHECK) {
1537  LSST_FITS_CHECK_STATUS(*this, boost::format("Opening file '%s' with mode '%s'") % filename % mode);
1538  }
1539 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
#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 1541 of file fits.cc.

1542  : fptr(0), status(0), behavior(behavior_) {
1543  typedef void *(*Reallocator)(void *, std::size_t);
1544  // It's a shame this logic is essentially a duplicate of above, but the innards are different enough
1545  // we can't really reuse it.
1546  if (mode == "r" || mode == "rb") {
1547  fits_open_memfile(reinterpret_cast<fitsfile **>(&fptr), "unused", READONLY, &manager._ptr,
1548  &manager._len, 0, 0, // no reallocator or deltasize necessary for READONLY
1549  &status);
1550  } else if (mode == "w" || mode == "wb") {
1551  Reallocator reallocator = 0;
1552  if (manager._managed) reallocator = &std::realloc;
1553  fits_create_memfile(reinterpret_cast<fitsfile **>(&fptr), &manager._ptr, &manager._len, 0,
1554  reallocator, // use default deltasize
1555  &status);
1556  } else if (mode == "a" || mode == "ab") {
1557  Reallocator reallocator = 0;
1558  if (manager._managed) reallocator = &std::realloc;
1559  fits_open_memfile(reinterpret_cast<fitsfile **>(&fptr), "unused", READWRITE, &manager._ptr,
1560  &manager._len, 0, reallocator, &status);
1561  int nHdu = 0;
1562  fits_get_num_hdus(reinterpret_cast<fitsfile *>(fptr), &nHdu, &status);
1563  fits_movabs_hdu(reinterpret_cast<fitsfile *>(fptr), nHdu, NULL, &status);
1564  if ((behavior & AUTO_CHECK) && (behavior & AUTO_CLOSE) && (status) && (fptr)) {
1565  // We're about to throw an exception, and the destructor won't get called
1566  // because we're in the constructor, so cleanup here first.
1567  int tmpStatus = 0;
1568  fits_close_file(reinterpret_cast<fitsfile *>(fptr), &tmpStatus);
1569  }
1570  } else {
1571  throw LSST_EXCEPT(FitsError,
1572  (boost::format("Invalid mode '%s' given when opening memory file at '%s'") % mode %
1573  manager._ptr)
1574  .str());
1575  }
1576  if (behavior & AUTO_CHECK) {
1578  *this, boost::format("Opening memory file at '%s' with mode '%s'") % manager._ptr % mode);
1579  }
1580 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
#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:1582

◆ 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 1099 of file fits.cc.

1099  {
1100  int nCols = addColumn<T>(ttype, size);
1101  updateColumnKey("TTYPE", nCols, ttype, comment);
1102  if (behavior & AUTO_CHECK) {
1103  LSST_FITS_CHECK_STATUS(*this, boost::format("Adding column '%s' with size %d") % ttype % size);
1104  }
1105  return nCols;
1106 }
#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:672
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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 1086 of file fits.cc.

1086  {
1087  int nCols = 0;
1088  fits_get_num_cols(reinterpret_cast<fitsfile *>(fptr), &nCols, &status);
1089  std::string tform = makeColumnFormat<T>(size);
1090  fits_insert_col(reinterpret_cast<fitsfile *>(fptr), nCols + 1, const_cast<char *>(ttype.c_str()),
1091  const_cast<char *>(tform.c_str()), &status);
1092  if (behavior & AUTO_CHECK) {
1093  LSST_FITS_CHECK_STATUS(*this, boost::format("Adding column '%s' with size %d") % ttype % size);
1094  }
1095  return nCols;
1096 }
#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.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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 1108 of file fits.cc.

1108  {
1109  long first = 0;
1110  fits_get_num_rows(reinterpret_cast<fitsfile *>(fptr), &first, &status);
1111  fits_insert_rows(reinterpret_cast<fitsfile *>(fptr), first, nRows, &status);
1112  if (behavior & AUTO_CHECK) {
1113  LSST_FITS_CHECK_STATUS(*this, boost::format("Adding %d rows to binary table") % nRows);
1114  }
1115  return first;
1116 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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 1685 of file fits.cc.

1685  {
1686  auto fits = reinterpret_cast<fitsfile *>(fptr);
1687  if (getHdu() != 0 || countHdus() == 1) {
1688  return false; // Can't possibly be the PHU leading a compressed image
1689  }
1690  // Check NAXIS = 0
1691  int naxis;
1692  fits_get_img_dim(fits, &naxis, &status);
1693  if (behavior & AUTO_CHECK) {
1694  LSST_FITS_CHECK_STATUS(*this, "Checking NAXIS of PHU");
1695  }
1696  if (naxis != 0) {
1697  return false;
1698  }
1699  // Check first extension (and move back there when we're done if we're not compressed)
1700  HduMoveGuard move(*this, 1);
1701  bool isCompressed = fits_is_compressed_image(fits, &status);
1702  if (behavior & AUTO_CHECK) {
1703  LSST_FITS_CHECK_STATUS(*this, "Checking compression");
1704  }
1705  if (isCompressed) {
1706  move.disable();
1707  }
1708  return isCompressed;
1709 }
#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:488
int countHdus()
Return the number of HDUs in the file.
Definition: fits.cc:515

◆ 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 1394 of file fits.cc.

1394  {
1395  int imageType = 0;
1396  fits_get_img_equivtype(reinterpret_cast<fitsfile *>(fptr), &imageType, &status);
1397  if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting image type");
1399  if (imageType < 0) {
1400  return false; // can't represent floating-point with integer
1401  }
1403  if (isFitsImageTypeSigned(imageType)) {
1404  return FitsBitPix<T>::CONSTANT >= imageType;
1405  } else {
1406  // need extra bits to safely convert unsigned to signed
1407  return FitsBitPix<T>::CONSTANT > imageType;
1408  }
1409  } else {
1410  if (!isFitsImageTypeSigned(imageType)) {
1411  return FitsBitPix<T>::CONSTANT >= imageType;
1412  } else if (imageType == LONGLONG_IMG) {
1413  // workaround for CFITSIO not recognizing uint64 as
1414  // unsigned
1415  return FitsBitPix<T>::CONSTANT >= imageType;
1416  } else {
1417  return false;
1418  }
1419  }
1420  }
1421  // we allow all conversions to float and double, even if they lose precision
1422  return true;
1423 }
#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 1582 of file fits.cc.

1582  {
1583  fits_close_file(reinterpret_cast<fitsfile *>(fptr), &status);
1584  fptr = nullptr;
1585 }

◆ countHdus()

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

Return the number of HDUs in the file.

Definition at line 515 of file fits.cc.

515  {
516  int n = 0;
517  fits_get_num_hdus(reinterpret_cast<fitsfile *>(fptr), &n, &status);
518  if (behavior & AUTO_CHECK) {
519  LSST_FITS_CHECK_STATUS(*this, "Getting number of HDUs in file.");
520  }
521  return n;
522 }
#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 1118 of file fits.cc.

1118  {
1119  long r = 0;
1120  fits_get_num_rows(reinterpret_cast<fitsfile *>(fptr), &r, &status);
1121  if (behavior & AUTO_CHECK) {
1122  LSST_FITS_CHECK_STATUS(*this, "Checking how many rows are in table");
1123  }
1124  return r;
1125 }
#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 1199 of file fits.cc.

1199  {
1200  long naxes = 0;
1201  fits_create_img(reinterpret_cast<fitsfile *>(fptr), 8, 0, &naxes, &status);
1202  if (behavior & AUTO_CHECK) {
1203  LSST_FITS_CHECK_STATUS(*this, "Creating empty image HDU");
1204  }
1205 }
#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 1076 of file fits.cc.

1076  {
1077  char *ttype = 0;
1078  char *tform = 0;
1079  fits_create_tbl(reinterpret_cast<fitsfile *>(fptr), BINARY_TBL, 0, 0, &ttype, &tform, 0, 0, &status);
1080  if (behavior & AUTO_CHECK) {
1081  LSST_FITS_CHECK_STATUS(*this, "Creating binary table");
1082  }
1083 }
#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 762 of file fits.cc.

762  {
763  char key[81]; // allow for terminating NUL
764  char value[81];
765  char comment[81];
766  int nKeys = 0;
767  fits_get_hdrspace(reinterpret_cast<fitsfile *>(fptr), &nKeys, 0, &status);
768  std::string keyStr;
769  std::string valueStr;
770  std::string commentStr;
771  int i = 1;
772  while (i <= nKeys) {
773  fits_read_keyn(reinterpret_cast<fitsfile *>(fptr), i, key, value, comment, &status);
774  keyStr = key;
775  valueStr = value;
776  commentStr = comment;
777  ++i;
778  while (valueStr.size() > 2 && valueStr[valueStr.size() - 2] == '&' && i <= nKeys) {
779  // we're using key to hold the entire record here; the actual key is safe in keyStr
780  fits_read_record(reinterpret_cast<fitsfile *>(fptr), i, key, &status);
781  if (strncmp(key, "CONTINUE", 8) != 0) {
782  // require both trailing '&' and CONTINUE to invoke long-string handling
783  break;
784  }
785  std::string card = key;
786  valueStr.erase(valueStr.size() - 2);
787  std::size_t firstQuote = card.find('\'');
788  if (firstQuote == std::string::npos) {
789  throw LSST_EXCEPT(
790  FitsError,
792  fptr, status,
793  boost::format("Invalid CONTINUE at header key %d: \"%s\".") % i % card));
794  }
795  std::size_t lastQuote = card.find('\'', firstQuote + 1);
796  if (lastQuote == std::string::npos) {
797  throw LSST_EXCEPT(
798  FitsError,
800  fptr, status,
801  boost::format("Invalid CONTINUE at header key %d: \"%s\".") % i % card));
802  }
803  valueStr += card.substr(firstQuote + 1, lastQuote - firstQuote);
804  std::size_t slash = card.find('/', lastQuote + 1);
805  if (slash != std::string::npos) {
806  commentStr += strip(card.substr(slash + 1));
807  }
808  ++i;
809  }
810  if (behavior & AUTO_CHECK) {
811  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading key '%s'") % keyStr);
812  }
813  functor(keyStr, valueStr, commentStr);
814  }
815 }
#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)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
T find(T... args)
T size(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
Key< U > key
Definition: Schema.cc:281
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:407
bool strip
Definition: fits.cc:883

◆ 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 479 of file fits.cc.

479  {
480  std::string fileName = "<unknown>";
481  fitsfile *fd = reinterpret_cast<fitsfile *>(fptr);
482  if (fd != 0 && fd->Fptr != 0 && fd->Fptr->filename != 0) {
483  fileName = fd->Fptr->filename;
484  }
485  return fileName;
486 }
STL class.

◆ getHdu()

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

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

Definition at line 488 of file fits.cc.

488  {
489  int n = 1;
490  fits_get_hdu_num(reinterpret_cast<fitsfile *>(fptr), &n);
491  return n - 1;
492 }

◆ getImageCompression()

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

Return the current image compression settings.

Definition at line 1454 of file fits.cc.

1454  {
1455  auto fits = reinterpret_cast<fitsfile *>(fptr);
1456  int compType = 0; // cfitsio compression type
1457  fits_get_compression_type(fits, &compType, &status);
1458  if (behavior & AUTO_CHECK) {
1459  LSST_FITS_CHECK_STATUS(*this, "Getting compression type");
1460  }
1461 
1462  ImageCompressionOptions::Tiles tiles = ndarray::allocate(MAX_COMPRESS_DIM);
1463  fits_get_tile_dim(fits, tiles.getNumElements(), tiles.getData(), &status);
1464  if (behavior & AUTO_CHECK) {
1465  LSST_FITS_CHECK_STATUS(*this, "Getting tile dimensions");
1466  }
1467 
1468  float quantizeLevel;
1469  fits_get_quantize_level(fits, &quantizeLevel, &status);
1470  if (behavior & AUTO_CHECK) {
1471  LSST_FITS_CHECK_STATUS(*this, "Getting quantizeLevel");
1472  }
1473 
1474  return ImageCompressionOptions(compressionAlgorithmFromCfitsio(compType), tiles, quantizeLevel);
1475 }
#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 1381 of file fits.cc.

1381  {
1382  int nAxis = 0;
1383  fits_get_img_dim(reinterpret_cast<fitsfile *>(fptr), &nAxis, &status);
1384  if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting NAXIS");
1385  return nAxis;
1386 }
#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 1425 of file fits.cc.

1425  {
1426  int bitpix = 0;
1427  fits_get_img_equivtype(reinterpret_cast<fitsfile *>(fptr), &bitpix, &status);
1428  if (behavior & AUTO_CHECK) LSST_FITS_CHECK_STATUS(*this, "Getting image type");
1429  // FITS' 'BITPIX' key is the number of bits in a pixel, but negative for
1430  // floats. But the above CFITSIO routine adds support for unsigned
1431  // integers by checking BZERO for an offset as well. So the 'bitpix' value
1432  // we get back from that should be the raw value for signed integers and
1433  // floats, but may be something else (still positive) for unsigned, and
1434  // hence we'll compare to some FITSIO constants to be safe looking at
1435  // integers.
1436  if (bitpix < 0) {
1437  return "float" + std::to_string(-bitpix);
1438  }
1439  switch (bitpix) {
1440  case BYTE_IMG: return "uint8";
1441  case SBYTE_IMG: return "int8";
1442  case SHORT_IMG: return "int16";
1443  case USHORT_IMG: return "uint16";
1444  case LONG_IMG: return "int32";
1445  case ULONG_IMG: return "uint32";
1446  case LONGLONG_IMG: return "int64";
1447  }
1448  throw LSST_EXCEPT(
1449  FitsError,
1450  (boost::format("Unrecognized BITPIX value: %d") % bitpix).str()
1451  );
1452 }
#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)
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
#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 1176 of file fits.cc.

1176  {
1177  int typecode = 0;
1178  long result = 0;
1179  long width = 0;
1180  fits_get_coltype(reinterpret_cast<fitsfile *>(fptr), col + 1, &typecode, &result, &width, &status);
1181  if (behavior & AUTO_CHECK) {
1182  LSST_FITS_CHECK_STATUS(*this, boost::format("Looking up array size for column %d") % col);
1183  }
1184  return result;
1185 }
int col
Definition: CR.cc:144
#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:418
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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 1187 of file fits.cc.

1187  {
1188  long result = 0;
1189  long offset = 0;
1190  fits_read_descript(reinterpret_cast<fitsfile *>(fptr), col + 1, row + 1, &result, &offset, &status);
1191  if (behavior & AUTO_CHECK) {
1192  LSST_FITS_CHECK_STATUS(*this, boost::format("Looking up array size for cell (%d, %d)") % row % col);
1193  }
1194  return result;
1195 }
int col
Definition: CR.cc:144
#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:418
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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 755 of file fits.cc.

755  {
756  readKeyImpl(*this, key.c_str(), value);
757  if (behavior & AUTO_CHECK) {
758  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading key '%s'") % key);
759  }
760 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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 1046 of file fits.cc.

1046  {
1047  MetadataIterationFunctor f;
1048  f.strip = strip;
1049  f.set = &metadata;
1050  f.list = dynamic_cast<daf::base::PropertyList *>(&metadata);
1051  forEachKey(f);
1052 }
void forEachKey(HeaderIterationFunctor &functor)
Call a polymorphic functor for every key in the header.
Definition: fits.cc:762
bool strip
Definition: fits.cc:883

◆ 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 1151 of file fits.cc.

1151  {
1152  int anynul = false;
1153  fits_read_col(reinterpret_cast<fitsfile *>(fptr), FitsTableType<T>::CONSTANT, col + 1, row + 1, 1,
1154  nElements, 0, value, &anynul, &status);
1155  if (behavior & AUTO_CHECK) {
1156  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading value at table cell (%d, %d)") % row % col);
1157  }
1158 }
int col
Definition: CR.cc:144
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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:1151

◆ 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 1160 of file fits.cc.

1160  {
1161  int anynul = false;
1162  long size = isVariableLength ? getTableArraySize(row, col) : getTableArraySize(col);
1163  // We can't directly write into a std::string until C++17.
1164  std::vector<char> buf(size + 1, 0);
1165  // cfitsio wants a char** because they imagine we might want an array of strings,
1166  // but we only want one element.
1167  char *tmp = &buf.front();
1168  fits_read_col(reinterpret_cast<fitsfile *>(fptr), TSTRING, col + 1, row + 1, 1, 1, 0, &tmp, &anynul,
1169  &status);
1170  if (behavior & AUTO_CHECK) {
1171  LSST_FITS_CHECK_STATUS(*this, boost::format("Reading value at table cell (%d, %d)") % row % col);
1172  }
1173  value = std::string(tmp);
1174 }
int col
Definition: CR.cc:144
#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:1176
STL class.
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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 494 of file fits.cc.

494  {
495  if (relative) {
496  fits_movrel_hdu(reinterpret_cast<fitsfile *>(fptr), hdu, 0, &status);
497  if (behavior & AUTO_CHECK) {
498  LSST_FITS_CHECK_STATUS(*this, boost::format("Incrementing HDU by %d") % hdu);
499  }
500  } else {
501  if (hdu != DEFAULT_HDU) {
502  fits_movabs_hdu(reinterpret_cast<fitsfile *>(fptr), hdu + 1, 0, &status);
503  }
504  if (hdu == DEFAULT_HDU && getHdu() == 0 && getImageDim() == 0) {
505  // want a silent failure here
506  int tmpStatus = status;
507  fits_movrel_hdu(reinterpret_cast<fitsfile *>(fptr), 1, 0, &tmpStatus);
508  }
509  if (behavior & AUTO_CHECK) {
510  LSST_FITS_CHECK_STATUS(*this, boost::format("Moving to HDU %d") % hdu);
511  }
512  }
513 }
int getImageDim()
Return the number of dimensions in the current HDU.
Definition: fits.cc:1381
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
int getHdu()
Return the current HDU (0-indexed; 0 is the Primary HDU).
Definition: fits.cc:488
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 1477 of file fits.cc.

1477  {
1478  auto fits = reinterpret_cast<fitsfile *>(fptr);
1479  fits_unset_compression_request(fits, &status); // wipe the slate and start over
1481  allowImageCompression ? comp.algorithm : ImageCompressionOptions::NONE;
1482  fits_set_compression_type(fits, compressionAlgorithmToCfitsio(algorithm), &status);
1483  if (behavior & AUTO_CHECK) {
1484  LSST_FITS_CHECK_STATUS(*this, "Setting compression type");
1485  }
1486 
1487  if (algorithm == ImageCompressionOptions::NONE) {
1488  // Nothing else worth doing
1489  return;
1490  }
1491 
1492  fits_set_tile_dim(fits, comp.tiles.getNumElements(), comp.tiles.getData(), &status);
1493  if (behavior & AUTO_CHECK) {
1494  LSST_FITS_CHECK_STATUS(*this, "Setting tile dimensions");
1495  }
1496 
1497  if (comp.algorithm != ImageCompressionOptions::PLIO && std::isfinite(comp.quantizeLevel)) {
1498  fits_set_quantize_level(fits, comp.quantizeLevel, &status);
1499  if (behavior & AUTO_CHECK) {
1500  LSST_FITS_CHECK_STATUS(*this, "Setting quantization level");
1501  }
1502  }
1503 }
#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 672 of file fits.cc.

672  {
673  updateKey((boost::format("%s%d") % prefix % (n + 1)).str(), value, comment);
674  if (behavior & AUTO_CHECK) {
675  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s%d': '%s'") % prefix % (n + 1) % value);
676  }
677 }
#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 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:640
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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:672
std::string prefix
Definition: SchemaMapper.cc:79
STL class.

◆ 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 688 of file fits.cc.

688  {
689  updateKey((boost::format("%s%d") % prefix % (n + 1)).str(), value);
690  if (behavior & AUTO_CHECK) {
691  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s%d': '%s'") % prefix % (n + 1) % value);
692  }
693 }
#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 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:640
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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:672
std::string prefix
Definition: SchemaMapper.cc:79
STL class.

◆ 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 640 of file fits.cc.

640  {
641  updateKeyImpl(*this, key.c_str(), value, comment.c_str());
642  if (behavior & AUTO_CHECK) {
643  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s': '%s'") % key % value);
644  }
645 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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:640
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 656 of file fits.cc.

656  {
657  updateKeyImpl(*this, key.c_str(), value, 0);
658  if (behavior & AUTO_CHECK) {
659  LSST_FITS_CHECK_STATUS(*this, boost::format("Updating key '%s': '%s'") % key % value);
660  }
661 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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:640
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 680 of file fits.cc.

680  {
681  writeKey((boost::format("%s%d") % prefix % (n + 1)).str(), value, comment);
682  if (behavior & AUTO_CHECK) {
683  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s%d': '%s'") % prefix % (n + 1) % value);
684  }
685 }
#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
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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:648

◆ 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:680
std::string prefix
Definition: SchemaMapper.cc:79
STL class.

◆ 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 696 of file fits.cc.

696  {
697  writeKey((boost::format("%s%d") % prefix % (n + 1)).str(), value);
698  if (behavior & AUTO_CHECK) {
699  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s%d': '%s'") % prefix % (n + 1) % value);
700  }
701 }
#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
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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:648

◆ 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:680
std::string prefix
Definition: SchemaMapper.cc:79
STL class.

◆ 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 1255 of file fits.cc.

1257  {
1258  auto fits = reinterpret_cast<fitsfile *>(fptr);
1259  ImageCompressionOptions const &compression =
1260  image.getBBox().getArea() > 0
1261  ? options.compression
1262  : ImageCompressionOptions(
1263  ImageCompressionOptions::NONE); // cfitsio can't compress empty images
1264  ImageCompressionContext comp(*this, compression); // RAII
1265  if (behavior & AUTO_CHECK) {
1266  LSST_FITS_CHECK_STATUS(*this, "Activating compression for write image");
1267  }
1268 
1269  ImageScale scale = options.scaling.determine(image, mask);
1270 
1271  // We need a place to put the image+header, and CFITSIO needs to know the dimenions.
1272  ndarray::Vector<long, 2> dims(image.getArray().getShape().reverse());
1273  createImageImpl(scale.bitpix == 0 ? detail::Bitpix<T>::value : scale.bitpix, 2, dims.elems);
1274 
1275  // Write the header
1278  if (header) {
1279  std::shared_ptr<daf::base::PropertySet> copy = header->deepCopy();
1280  copy->combine(wcsMetadata);
1281  header = copy;
1282  } else {
1283  header = wcsMetadata;
1284  }
1285  writeMetadata(*header);
1286 
1287  // Scale the image how we want it on disk
1288  ndarray::Array<T const, 2, 2> array = makeContiguousArray(image.getArray());
1289  auto pixels = scale.toFits(array, compression.quantizeLevel != 0, options.scaling.fuzz,
1290  options.compression.tiles, options.scaling.seed);
1291 
1292  // We only want cfitsio to do the scale and zero for unsigned 64-bit integer types. For those,
1293  // "double bzero" has sufficient precision to represent the appropriate value. We'll let
1294  // cfitsio handle it itself.
1295  // In all other cases, we will convert the image to use the appropriate scale and zero
1296  // (because we want to fuzz the numbers in the quantisation), so we don't want cfitsio
1297  // rescaling.
1299  fits_set_bscale(fits, 1.0, 0.0, &status);
1300  if (behavior & AUTO_CHECK) {
1301  LSST_FITS_CHECK_STATUS(*this, "Setting bscale,bzero");
1302  }
1303  }
1304 
1305  // Write the pixels
1306  int const fitsType = scale.bitpix == 0 ? FitsType<T>::CONSTANT : fitsTypeForBitpix(scale.bitpix);
1307  fits_write_img(fits, fitsType, 1, pixels->getNumElements(), const_cast<void *>(pixels->getData()),
1308  &status);
1309  if (behavior & AUTO_CHECK) {
1310  LSST_FITS_CHECK_STATUS(*this, "Writing image");
1311  }
1312 
1313  // Now write the headers we didn't want cfitsio to know about when we were writing the pixels
1314  // (because we don't want it using them to modify the pixels, and we don't want it overwriting
1315  // these values).
1317  std::isfinite(scale.bzero) && std::isfinite(scale.bscale) && (scale.bscale != 0.0)) {
1319  if (scale.bzero != 0.0) {
1320  fits_write_key_lng(fits, "BZERO", static_cast<long>(scale.bzero),
1321  "Scaling: MEMORY = BZERO + BSCALE * DISK", &status);
1322  }
1323  if (scale.bscale != 1.0) {
1324  fits_write_key_lng(fits, "BSCALE", static_cast<long>(scale.bscale),
1325  "Scaling: MEMORY = BZERO + BSCALE * DISK", &status);
1326  }
1327  } else {
1328  fits_write_key_dbl(fits, "BZERO", scale.bzero, 12, "Scaling: MEMORY = BZERO + BSCALE * DISK",
1329  &status);
1330  fits_write_key_dbl(fits, "BSCALE", scale.bscale, 12, "Scaling: MEMORY = BZERO + BSCALE * DISK",
1331  &status);
1332  }
1333  if (behavior & AUTO_CHECK) {
1334  LSST_FITS_CHECK_STATUS(*this, "Writing BSCALE,BZERO");
1335  }
1336  }
1337 
1338  if (scale.bitpix > 0 && !std::numeric_limits<T>::is_integer) {
1339  fits_write_key_lng(fits, "BLANK", scale.blank, "Value for undefined pixels", &status);
1340  fits_write_key_lng(fits, "ZDITHER0", options.scaling.seed, "Dithering seed", &status);
1341  fits_write_key_str(fits, "ZQUANTIZ", "SUBTRACTIVE_DITHER_1", "Dithering algorithm", &status);
1342  if (behavior & AUTO_CHECK) {
1343  LSST_FITS_CHECK_STATUS(*this, "Writing [Z]BLANK");
1344  }
1345  }
1346 
1347  // cfitsio says this is deprecated, but Pan-STARRS found that it was sometimes necessary, writing:
1348  // "This forces a re-scan of the header to ensure everything's kosher.
1349  // Without this, compressed HDUs have been written out with PCOUNT=0 and TFORM1 not correctly set."
1350  fits_set_hdustruc(fits, &status);
1351  if (behavior & AUTO_CHECK) {
1352  LSST_FITS_CHECK_STATUS(*this, "Finalizing header");
1353  }
1354 }
T copy(T... args)
void writeMetadata(daf::base::PropertySet const &metadata)
Read a FITS header into a PropertySet or PropertyList.
Definition: fits.cc:1054
#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
tuple options
Definition: lsstimport.py:47
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:463
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:176
T isfinite(T... args)
lsst::geom::Point2I getXY0() const
Return the image&#39;s origin.
Definition: ImageBase.h:341
std::string const wcsNameForXY0
Definition: ImageBase.h:71

◆ 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 648 of file fits.cc.

648  {
649  writeKeyImpl(*this, key.c_str(), value, comment.c_str());
650  if (behavior & AUTO_CHECK) {
651  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s': '%s'") % key % value);
652  }
653 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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:648

◆ 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 664 of file fits.cc.

664  {
665  writeKeyImpl(*this, key.c_str(), value, 0);
666  if (behavior & AUTO_CHECK) {
667  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing key '%s': '%s'") % key % value);
668  }
669 }
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
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:648

◆ 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 1054 of file fits.cc.

1054  {
1055  typedef std::vector<std::string> NameList;
1056  daf::base::PropertyList const *pl = dynamic_cast<daf::base::PropertyList const *>(&metadata);
1057  NameList paramNames;
1058  if (pl) {
1059  paramNames = pl->getOrderedNames();
1060  } else {
1061  paramNames = metadata.paramNames(false);
1062  }
1063  for (NameList::const_iterator i = paramNames.begin(); i != paramNames.end(); ++i) {
1064  if (!isKeyIgnored(*i, true)) {
1065  if (pl) {
1066  writeKeyFromProperty(*this, metadata, *i, pl->getComment(*i).c_str());
1067  } else {
1068  writeKeyFromProperty(*this, metadata, *i);
1069  }
1070  }
1071  }
1072 }

◆ 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 1128 of file fits.cc.

1128  {
1129  fits_write_col(reinterpret_cast<fitsfile *>(fptr), FitsTableType<T>::CONSTANT, col + 1, row + 1, 1,
1130  nElements, const_cast<T *>(value), &status);
1131  if (behavior & AUTO_CHECK) {
1132  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing %d-element array at table cell (%d, %d)") %
1133  nElements % row % col);
1134  }
1135 }
int col
Definition: CR.cc:144
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

◆ 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:1128

◆ 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 1137 of file fits.cc.

1137  {
1138  // cfitsio doesn't let us specify the size of a string, it just looks for null terminator.
1139  // Using std::string::c_str() guarantees that we have one. But we can't store arbitrary
1140  // data in a string field because cfitsio will also chop off anything after the first null
1141  // terminator.
1142  char const *tmp = value.c_str();
1143  fits_write_col(reinterpret_cast<fitsfile *>(fptr), TSTRING, col + 1, row + 1, 1, 1,
1144  const_cast<char const **>(&tmp), &status);
1145  if (behavior & AUTO_CHECK) {
1146  LSST_FITS_CHECK_STATUS(*this, boost::format("Writing value at table cell (%d, %d)") % row % col);
1147  }
1148 }
int col
Definition: CR.cc:144
#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 format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168

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: