Writing FITS files

fitsy.image(data, header=None, primary=True)

Build an image HDU from an array.

Parameters:
  • data (array-like) – Image pixels. A numpy array of dtype bool, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32 or float64, or anything numpy.asarray() accepts (nested lists, tuples, objects implementing __array__). The returned HDU’s NAXIS list is the reverse of data.shape, because numpy lists axes slowest-first and FITS lists them fastest-first.

  • header (Header or mapping, optional) – Extra header cards to merge in. A Header or a dict. Values may be scalars or (value, comment) tuples. Default None, which adds no extra cards.

  • primary (bool, optional) – Default True. Builds the header with SIMPLE = T. Set to False to build an image extension header instead (XTENSION = 'IMAGE' with PCOUNT and GCOUNT).

Returns:

ImageBuilder – Pass to write().

Raises:

TypeError – If data is neither an array of one of the dtypes above nor something numpy.asarray() accepts.

Notes

int8, uint16, uint32 and uint64 have no direct FITS type. fitsy stores each one under the FITS unsigned-integer convention, which a conforming reader decodes back to the original values. A bool array is stored as BITPIX = 8.

A float array holds physical values, so a BZERO, BSCALE or BLANK card in header is dropped. Those cards describe integer storage that the array no longer has, and keeping one would scale the values a second time when the file is read back. An integer array keeps the card that header supplies, in place of the card fitsy would compute.

Pass primary=False to every image() call after the first item passed to write(). write() raises fitsy.FitsError if a later HDU still declares SIMPLE, or if the first HDU does not.

A COMMENT, HISTORY or blank-keyword card in header carries into the built HDU, after the value cards.

fitsy.compressed_image(data, header=None, *, tile_shape=None, extname=None)

Tile-compress a numpy array into a BINTABLE HDU (ZIMAGE).

The result is a tile-compressed image extension: a BINTABLE with ZIMAGE = T whose rows each hold one compressed tile. fitsy.open() reads it back as an image.

Parameters:
  • data (array-like) – Image pixels. A numpy array of dtype bool, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32 or float64, or anything numpy.asarray() accepts.

  • header (Header or mapping, optional) – Extra cards merged into the synthesized image header before compression. A Header or a dict. Default None, which adds no extra cards.

  • tile_shape (sequence of int, optional) – Tile shape in FITS axis order (tile_shape[0] is the NAXIS1 direction). Length must equal data.ndim. Default None, which tiles as (NAXIS1, 1, 1, ...) – one row per tile (Pence & Seaman 2010 Sec.3).

  • extname (str, optional) – EXTNAME keyword on the resulting BINTABLE. Default "COMPRESSED_IMAGE".

Returns:

BinTableBuilder – Pass to write().

Raises:
  • TypeError – If data is neither an array of one of the dtypes above nor something numpy.asarray() accepts.

  • FitsError – If data has no axes (a 0-D array). Also raised if tile_shape is given and its length does not equal data.ndim, or if one of its entries is 0.

Notes

This function emits ZCMPTYPE = 'GZIP_1' compressed tiles. GZIP_1 is lossless for every dtype listed above.

fitsy computes the structural cards of the compressed HDU itself. It therefore ignores a structural card, such as BITPIX, and a reserved Z card, such as ZBITPIX, in header. Set EXTNAME through extname. Every other card carries into the compressed HDU and survives decompression, including a COMMENT, HISTORY or blank-keyword card, which lands after the value cards.

fitsy.bintable(columns, units=None, extname=None)

Build a BINTABLE HDU from a column dictionary.

Parameters:
  • columns (dict[str, sequence]) –

    One entry per column. All columns must share the same row count. Supported value kinds:

    • a numpy bool, uint8, int16, int32, int64, float32 or float64 array (1-D, or 2-D for a fixed-repeat column)

    • list[str] -> nA (right-padded to the longest string)

    • list[complex] -> M (C128)

    • list[list[float]] -> 1PD variable-length column (heap-stored, f64 element type). This applies to any nested numeric list, ragged or not. Pass a 2-D numpy array to get a fixed-repeat column instead.

    • a flat sequence of numbers ([1, 2, 3], a tuple, a range), converted with numpy.asarray() and encoded as the dtype numpy infers

  • units (dict[str, str], optional) – Per-column TUNITn strings. Default None, which adds no TUNITn cards. A key that names no column in columns is ignored.

  • extname (str, optional) – EXTNAME keyword for this extension. Default None, which adds no EXTNAME card.

Returns:

BinTableBuilder – Pass to write().

Raises:

ValueError – If a column’s values do not match one of the kinds listed above, or if the columns disagree on row count.

Notes

A numpy array of int8, uint16, uint32 or uint64 is not one of the supported kinds; convert it first, for example with arr.astype(numpy.int32).

fitsy.ascii_table(columns, formats=None, tnulls=None, units=None, extname=None)

Build an ASCII TABLE HDU from a column dictionary.

Parameters:
  • columns (dict[str, sequence]) –

    One entry per column. All columns must share the same row count. Supported value kinds:

    • list[str] -> A{maxlen}

    • list[int], list[Optional[int]], or a numpy integer array -> I{w} by default. A None cell needs a matching entry in tnulls.

    • list[float] or a numpy float array -> E{w}.{d} by default

  • formats (dict[str, str], optional) – Per-column override for the auto-chosen TFORM code, such as {"flux": "F10.3"}. The format kind must match the column’s value kind: I for an integer column, F/E/ D for a float column, A for a string column. Default None, which auto-chooses every column’s format.

  • tnulls (dict[str, str], optional) – TNULL sentinel string for a numeric column that holds an undefined cell (None for an integer column, nan for a float column). Default None, which sets no TNULL.

  • units (dict[str, str], optional) – Per-column TUNIT strings. Default None, which adds no TUNIT cards.

  • extname (str, optional) – EXTNAME keyword. Default None, which adds no EXTNAME card.

Returns:

AsciiTableBuilder – Pass to write().

Raises:
  • TypeError – If a column’s values do not match list[str], list[Optional[int]], or list[float], or if formats gives a format kind that does not match the column’s value kind.

  • ValueError – If a string cell holds a byte outside ASCII 32-126 (Standard Sec.7.2.5).

  • FitsError – If formats holds a string that is not a valid TFORM code, if the columns disagree on row count, if a rendered cell or a TNULL sentinel does not fit the column’s field width, or if a numeric column holds an undefined cell with no matching entry in tnulls.

fitsy.write(path, hdus, overwrite=False, *, checksums=False)

Write a sequence of HDU builders to disk.

Parameters:
  • path (str or os.PathLike) – Destination path.

  • hdus (list) – Builders returned by image(), bintable(), ascii_table() or compressed_image(). When the first item is an image builder, it becomes the primary HDU, and it must have been built with primary=True. When the first item is any other builder, fitsy writes an empty primary HDU before it. A table-only file thus needs no placeholder image.

  • overwrite (bool, optional) – Default False, which raises fitsy.FitsError instead of truncating an existing file at path. True truncates and overwrites it.

  • checksums (bool, optional) – Default False. True computes and stamps CHECKSUM and DATASUM cards on every emitted HDU (FITS Checksum Proposal).

Raises:
  • ValueError – If hdus is empty.

  • TypeError – If an item of hdus is not an ImageBuilder, BinTableBuilder or AsciiTableBuilder.

  • FitsError – If path cannot be opened for writing, for example because it already exists and overwrite is False. Also raised if an HDU built with the wrong primary value reaches the writer – a non-first image HDU built with primary=True, or a first image HDU built with primary=False.

Notes

When checksums is False, fitsy writes a CHECKSUM or DATASUM card already present in a builder’s header verbatim, unchanged.

Examples

>>> import numpy as np, fitsy
>>> fitsy.write("out.fits", [
...     fitsy.image(np.zeros((10, 10), dtype=np.float32)),
... ])
fitsy.append(path, data, header=None)

Append one image HDU to an existing FITS file.

Writes the new HDU directly after the last existing HDU. fitsy rewrites no existing HDU.

Parameters:
  • path (str or os.PathLike) – FITS file to append to. The file must already exist and must parse as FITS.

  • data (array-like) – Image pixels for the new HDU. A numpy array of dtype bool, int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32 or float64, or anything numpy.asarray() accepts.

  • header (Header or mapping, optional) – Extra header cards for the new HDU. Default None.

Raises:
  • FitsError – If path cannot be opened for append, or the write fails.

  • TypeError – If data is not an image array or array-like, or its dtype is not one fitsy supports.

Notes

fitsy writes the new HDU as an extension, with XTENSION = 'IMAGE'. fitsy parses the whole file first, to check it and to find the offset of the append. Any bytes after the last HDU are overwritten.

fitsy builds the new HDU with fitsy.image(). See that function for the dtype rule, and for the BZERO and BSCALE cards it adds for an unsigned dtype.

fitsy.setval(path, key, value=None, *, ext=None, comment=None)

Set one header keyword in path. Rewrites the file.

Parameters:
  • path (str or os.PathLike) – File to edit.

  • key (str) – Header keyword to set.

  • value (bool, int, float, complex, str, or None, optional) – New card value. Default None, which writes a card with an undefined value.

  • ext (int or str, keyword-only, optional) – HDU index or EXTNAME. Default is HDU 0.

  • comment (str, keyword-only, optional) – New card comment. Default None, which leaves an existing card’s comment unchanged.

Raises:
  • FitsError – If path cannot be opened or parsed as FITS, if key is not a valid FITS keyword, or if the rewrite fails.

  • IndexError – If ext is an out-of-range integer.

  • KeyError – If ext is a string that names no HDU.

  • TypeError – If ext is neither an int, a str, nor omitted. Also raised if value is a type fitsy cannot store in a header card.

  • ValueError – If key names a structural card managed by the writer, such as BITPIX or NAXIS.

fitsy.delval(path, key, *, ext=None)

Remove one header keyword from path. Rewrites the file.

Parameters:
  • path (str or os.PathLike) – File to edit.

  • key (str) – Header keyword to remove.

  • ext (int or str, keyword-only, optional) – HDU index or EXTNAME. Default is HDU 0.

Raises:
  • FitsError – If path cannot be opened or parsed as FITS, or if the rewrite fails.

  • IndexError – If ext is an out-of-range integer.

  • KeyError – If ext is a string that names no HDU, or if key is absent from the selected header. Call getval(), or test key in header on an open file, to guard an optional card.

  • TypeError – If ext is neither an int, a str, nor omitted.

  • ValueError – If key names a structural card managed by the writer, such as BITPIX or NAXIS.

class fitsy.ImageBuilder

Bases: object

Opaque image HDU spec produced by image().

Pass to write() as part of a list of builders.

class fitsy.BinTableBuilder

Bases: object

Opaque BINTABLE HDU spec produced by bintable().

class fitsy.AsciiTableBuilder

Bases: object

Opaque ASCII TABLE HDU spec produced by ascii_table().