Namespace lsst::afw::fits

namespace fits

Functions

LSST_EXCEPTION_TYPE(FitsError, lsst::pex::exceptions::IoError, lsst::afw::fits::FitsError)

An exception thrown when problems are found when reading or writing FITS files. An exception thrown when a FITS file has the wrong type.

std::string makeErrorMessage(std::string const &fileName = "", int status = 0, std::string const &msg = "")

Return an error message reflecting FITS I/O errors.

Parameters
  • [in] fileName: FITS filename to be included in the error message.

  • [in] status: The last status value returned by the cfitsio library; if nonzero, the error message will include a description from cfitsio.

  • [in] msg: An additional custom message to include.

std::string makeErrorMessage(std::string const &fileName, int status, boost::format const &msg)
std::string makeErrorMessage(void *fptr, int status = 0, std::string const &msg = "")

Return an error message reflecting FITS I/O errors.

Parameters
  • [in] fptr: A cfitsio fitsfile pointer to be inspected for a filename. Passed as void* to avoid including fitsio.h in the header file.

  • [in] status: The last status value returned by the cfitsio library; if nonzero, the error message will include a description from cfitsio.

  • [in] msg: An additional custom message to include.

std::string makeErrorMessage(void *fptr, int status, boost::format const &msg)
std::string makeLimitedFitsHeader(lsst::daf::base::PropertySet const &metadata, std::set<std::string> const &excludeNames = {})

Format a PropertySet into an FITS header string in a simplistic fashion.

This function is designed to format data for creating a WCS. As such, it is quite limited:

  • It skips entries whose name is longer than 8 characters, since none are used for FITS-WCS

  • It skips string entries if the fully formatted string is longer than 80 characters

  • It skips entries with types it cannot handle (e.g. long, long long)

  • For entries that have array data, it only writes the final value, since that is the value that should be used by code that reads FITS headers.

  • It makes no attempt to insure that required entries, such as SIMPLE, are present.

Return

a FITS header string (exactly 80 characters per entry, no line terminators)

Parameters
  • [in] metadata: Metadata to format; if this is a PropertyList then the order of items is preserved

  • [in] excludeNames: Names of entries to exclude from the returned header string

template<typename T>
int getBitPix()

Return the cfitsio integer BITPIX code for the given data type.

template<typename T, int N, int C>
ndarray::Array<T const, N, N> const makeContiguousArray(ndarray::Array<T, N, C> const &array)

Construct a contiguous ndarray

A deep copy is only performed if the array is not already contiguous.

std::shared_ptr<daf::base::PropertyList> combineMetadata(std::shared_ptr<const daf::base::PropertyList> first, std::shared_ptr<const daf::base::PropertyList> second)

Combine two sets of metadata in a FITS-appropriate fashion

“COMMENT” and “HISTORY” entries:

  • If of type std::string then the values in second are appended to values in first

  • If not of type std::string then they are silently ignored

All other entries:

  • Values in second override values in first (regardless of type)

  • Only scalars are copied; if a vector is found, only the last value is copied

Return

The combined metadata. Item names have the following order:

  • names in first, omitting all names except “COMMENT” and “HISTORY” that appear in second

  • names in second, omitting “COMMENT” and “HISTORY” if valid versions appear in first

Parameters
  • [in] first: The first set of metadata to combine

  • [in] second: The second set of metadata to combine

std::shared_ptr<daf::base::PropertyList> readMetadata(std::string const &fileName, int hdu = DEFAULT_HDU, bool strip = false)

Read FITS header

Includes support for the INHERIT convention: if ‘INHERIT = T’ is in the header, the PHU will be read as well, and nominated HDU will override any duplicated values.

Return the metadata (header entries) from a FITS file.

Parameters
  • fileName: the file whose header will be read

  • hdu: the HDU to read (0-indexed; 0 is the Primary HDU).

  • strip: if true, common FITS keys that usually have non-metadata intepretations (e.g. NAXIS, BITPIX) will be ignored.

Parameters
  • [in] fileName: File to read.

  • [in] hdu: HDU to read, 0-indexed. The special value of afw::fits::DEFAULT_HDU will read the first non-empty HDU.

  • [in] strip: If true, ignore special header keys usually managed by cfitsio (e.g. NAXIS).

std::shared_ptr<daf::base::PropertyList> readMetadata(fits::MemFileManager &manager, int hdu = DEFAULT_HDU, bool strip = false)

Read FITS header

Includes support for the INHERIT convention: if ‘INHERIT = T’ is in the header, the PHU will be read as well, and nominated HDU will override any duplicated values.

Parameters
  • manager: the in-memory file whose header will be read

  • hdu: the HDU to read (0-indexed; 0 is the Primary HDU).

  • strip: if true, common FITS keys that usually have non-metadata intepretations (e.g. NAXIS, BITPIX) will be ignored.

std::shared_ptr<daf::base::PropertyList> readMetadata(fits::Fits &fitsfile, bool strip = false)

Read FITS header

Includes support for the INHERIT convention: if ‘INHERIT = T’ is in the header, the PHU will be read as well, and nominated HDU will override any duplicated values.

Parameters
  • fitsfile: the file and HDU to be read

  • strip: if true, common FITS keys that usually have non-metadata intepretations (e.g. NAXIS, BITPIX) will be ignored.

void setAllowImageCompression(bool allow)
bool getAllowImageCompression()
ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromString(std::string const &name)

Interpret compression algorithm expressed in string.

std::string compressionAlgorithmToString(ImageCompressionOptions::CompressionAlgorithm algorithm)

Provide string version of compression algorithm.

ImageCompressionOptions::CompressionAlgorithm compressionAlgorithmFromCfitsio(int cfitsio)

Convert compression algorithm from cfitsio to ImageCompressionOptions::CompressionAlgorithm.

int compressionAlgorithmToCfitsio(ImageCompressionOptions::CompressionAlgorithm algorithm)

Convert ImageCompressionOptions::CompressionAlgorithm to cfitsio.

ImageScalingOptions::ScalingAlgorithm scalingAlgorithmFromString(std::string const &name)

Interpret scaling algorithm expressed in string.

std::string scalingAlgorithmToString(ImageScalingOptions::ScalingAlgorithm algorithm)

Provide string version of compression algorithm.

Variables

const int DEFAULT_HDU = INT_MIN

Specify that the default HDU should be read.

This special HDU number indicates that the first extension should be used if the primary HDU is empty (i.e., has NAXIS=0) and the Primary HDU is the current.

class Fits
#include <fits.h>

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.

class HduMoveGuard
#include <fits.h>

RAII scoped guard for moving the HDU in a Fits object.

This class attempts to ensure that the HDU state of a Fits object is restored when the guard class goes out of scope, even in the presence of exceptions. (In practice, resetting the HDU can only fail if the Fits object has become sufficiently corrupted that it’s no longer usable at all).

class HeaderIterationFunctor
#include <fits.h>

Base class for polymorphic functors used to iterator over FITS key headers.

Subclass this, and then pass an instance to Fits::forEachKey to iterate over all the keys in a header.

struct ImageCompressionOptions
#include <fitsCompression.h>

Options for tile compression of image pixels

Tile compression is a feature provided by cfitsio, where contiguous parts of the image (“tiles”, e.g., rows, multiple rows, blocks or the entire image) are compressed separately. The aim of this struct is to hold the parameters used to configure the compression.

Floating-point images can be losslessly compressed (quantizeLevel=0.0) using (only) the GZIP or GZIP_SHUFFLE compression algorithms, but the compression factor so achieved is modest (e.g., ~ 10% compression). Better compression factors can be achieved if floating-point images are first quantised into integer images. This can be done by cfitsio (through the quantizeLevel parameter) or through use of the ImageScalingOptions.

The Compression is specified by:

  • the compression algorithm

  • the tile size

  • the quantization level (for quantization applied by cfitsio; for floating-point images)

Due to bugs, cfitsio may require setting the quantizeLevel to a value other than zero when compressing integer data, but in this case it should have no effect.

struct ImageScale
#include <fitsCompression.h>

Scale to apply to image

Images are scaled to the type implied by the provided BITPIX using the provided scale and zero-point:

value in memory = BZERO + BSCALE * value in FITS

In addition to scaling, a random field of values distributed [0,1) may be added before quantisation (“fuzz”); this preserves the expectation value of the floating-point image, while increasing the variance by 1/12.

class ImageScalingOptions
#include <fitsCompression.h>

Options for scaling image pixels

Scaling (quantisation) of floating-point images is important in order to achieve respectable compression factors. Unfortunately, scaling a floating-point image means losing some information, in two ways: values are quantised so values in between the quanta will be rounded up or down; and values outside the range of supported values in the integer image will be clipped. This implementation is based on the successful implementation used by Pan-STARRS.

cfitsio provides a facility for scaling image pixels on write (see ImageCompressionOptions.quantizeLevel), but that facility is limited (it provides a single scaling option, and doesn’t use our masks when collecting statistics). This scaling facility provides multiple scaling options, and could be extended to support more in the future (e.g., logarithmic or asinh scaling).

Scaling is specified by:

  • the scaling algorithm: the algorithm used to determining the scales (and therefore the dynamic range).

  • the bits per pixel: 8,16,32,64,-32,-64 (negative means floating-point but you probably don’t want to use those here); larger values give more dynamic range, produce larger images (which effect may be negated by compression).

  • fuzz: whether to add a random field of values distributed [0,1) before quantisation; this preserves the expectation value of the floating-point image, while increasing the variance by 1/12.

  • seed: seed for the random number generator used by the fuzz.

  • maskPlanes: a list of mask planes to be ignored when doing statistics.

  • quantizeLevel: for the STDEV_* algorithms, specifies the ratio of the quantum size to the image standard deviation.

  • quantizePad: for the STDEV_POSITIVE and STDEV_NEGATIVE algorithms, specifies how many standard deviations to allow on the short side.

  • bscale, bzero: for the MANUAL algorithm, specifies the BSCALE and BZERO to use.

Scaling algorithms are:

  • NONE: no scaling or quantisation at all. The image goes out the way it came in.

  • RANGE: scale based on the dynamic range in the image. This preserves dynamic range at the cost of sensitivity to low-level fluctuations.

  • STDEV_POSITIVE: the scale is set to sample the standard deviation of the image (bscale = stdev/quantizeLevel) and the dynamic range extends principally positive (allowing only quantizePad standard deviations negative).

  • STDEV_NEGATIVE: similar to STDEV_POSITIVE, but the dynamic range extends principally negative.

  • STDEV_BOTH: the scale is set similar to STDEV_POSITIVE, but the dynamic range is shared between the positive and negative sides.

  • MANUAL: the scale is set manually. We do what we’re told, no more, no less.

Perhaps this one class could/should have been polymorphic, with different subclasses for different algorithms? But I went with a C-like approach keying off the enum, probably because I was influenced by Pan-STARRS’ C code.

struct ImageWriteOptions
#include <fits.h>

Options for writing an image to FITS

An image being written to FITS may be scaled (quantised) and/or compressed. This struct is a container for options controlling each of those separately.

class MemFileManager
#include <fits.h>

Lifetime-management for memory that goes into FITS memory files.

namespace detail

Functions

template<typename T>
std::shared_ptr<PixelArrayBase> makePixelArray(int bitpix, ndarray::Array<T, 1, 1> const &array)

Create a PixelArray suitable for an image with the nominated BITPIX

Return

A new PixelArray.

Parameters
  • [in] bitpix: Bits per pixel (0,8,16,32,64,-32,-64) for output.

  • [in] array: Array with pixel values to convert.

template<typename T>
struct Bitpix
#include <fitsCompression.h>

FITS BITPIX header value by C++ type.

template<typename T>
class PixelArray : public lsst::afw::fits::detail::PixelArrayBase
#include <fitsCompression.h>

Typed array of pixel values.

class PixelArrayBase
#include <fitsCompression.h>

Abstract base class for an array of pixel values

For writing pixels out with the C-based cfitsio API, it’s helpful to have a type-agnostic holder of the pixel values (because although we can template on the array type, the output type can be configured at run-time, which means we can’t use ndarray::Array as the carrier). This is essentially a C++-ish void* array.

Subclassed by lsst::afw::fits::detail::PixelArray< T >