Headers

class fitsy.Header(mapping=None)

Bases: object

Dict-like view of a FITS header.

A Header is shared with its parent HDU: copying the Python object gives another handle to the same header, so an edit through one is visible through all of them.

Headers from a read-only FitsFile raise ValueError from every mutating method: __setitem__(), __delitem__(), set(), insert(), add_commentary(), rename_keyword(), and update(). Open the file with mode='update' to allow in-memory edits.

Notes

A card’s value converts to a native Python scalar: a logical to bool, an integer to int, a real to float, a complex value to complex, and a string (including one assembled from CONTINUE cards) to str. An undefined value converts to None. Writing a value back accepts the same six Python types; any other type raises TypeError. A COMMENT, HISTORY or blank-keyword card holds no value of its own; header[key] returns a HeaderCommentary for one of these three keywords instead.

A keyword is matched case-insensitively: hdr["bitpix"] and hdr["BITPIX"] name the same card. A hyphenated keyword such as MJD-OBS also matches a card some writers store with an underscore instead (MJD_OBS).

__setitem__(), __delitem__(), set(), insert() and rename_keyword() reject a structural card: SIMPLE, BITPIX, NAXIS, EXTEND, PCOUNT, GCOUNT, XTENSION, END, GROUPS, or NAXISn. An HDU writer recomputes these from the data array or column descriptors, so a direct edit would be silently overwritten. Constructing a Header from a mapping, and update(), do not apply this check: a mapping or another Header carrying a structural keyword is accepted unchanged.

Examples

>>> with fitsy.open("image.fits") as f:
...     hdr = f[0].header
...     bitpix = hdr["BITPIX"]
...     for key in hdr:
...         print(key, hdr[key])
__contains__(key, /)

Return key in self.

__delitem__(key, /)

Delete self[key].

__getitem__(key, /)

Return self[key].

__iter__()

Implement iter(self).

__len__()

Return len(self).

__setitem__(key, value, /)

Set self[key] to value.

add_commentary(kind, text)

Append a commentary card.

Parameters:
  • kind ({'COMMENT', 'HISTORY', ''}) – Commentary kind. The empty string emits a blank-keyword commentary card.

  • text (str) – Commentary text. Long lines are split across multiple 80-byte cards on serialization.

Raises:
  • TypeError – If kind is not one of the recognized values.

  • ValueError – If the header is read-only.

Notes

text is not checked for non-ASCII bytes here. A non-ASCII byte only raises, as ValueError, when the header is later serialized with tostring(), bytes(header), or a file write.

cards(key)

Return every card matching key as a list of (value, comment) tuples, in declaration order.

Useful when a keyword appears more than once and you need programmatic access to every occurrence (the indexed accessor only returns the first). Commentary cards yield (text, None). Returns an empty list if no match is found.

comment(key)

Inline comment for the first card with this keyword.

Parameters:

key (str) – Keyword (case-insensitive match).

Returns:

str or None – The comment text, or None if no such card exists or the matching card has no inline comment.

date

Creation date of this HDU (DATE), always UTC, as an ISO-8601 string.

Returns None if the keyword is absent.

static frombytes(data, *, lenient=True)

Parse a header from raw FITS bytes – the inverse of bytes(header). Behaves like fromstring() but takes a bytes buffer (for example, header blocks read straight from a file), including its Raises conditions.

static fromstring(data, *, lenient=True)

Parse a header from a string of concatenated 80-character FITS cards – the inverse of tostring().

The text is read as raw card images with no separators. It need not be block-aligned or carry an END card: a partial final card is space-padded and an END is appended when absent, so both a full 2880-byte dump and a bare "OBJECT  = 'M31'" fragment parse.

Parameters:
  • data (str) – Header cards as ASCII text. Use frombytes() for a raw bytes buffer.

  • lenient (bool, keyword-only, optional) – Tolerate non-conforming values and structure (default True, matching fitsy.open()). Pass False to require strict Standard conformance.

Returns:

Header – A new, writable header.

Raises:

FitsError – If data does not parse as FITS header cards – for example an unrecognized value, or (only when lenient is False) a non-ASCII byte in a value field.

get(key, default=None)

Non-raising lookup (header.get(key, default=None)).

Parameters:
  • key (str) – Keyword to look up (case-insensitive).

  • default (object, optional) – Value to return if key is absent. Defaults to None.

Returns:

object – The matching value, or default if absent.

Notes

Unlike header[key], this method never returns a HeaderCommentary: "COMMENT", "HISTORY" and "" have no value card to match, so get on one of these three keywords always returns default.

insert(position, keyword, value=None, comment=None, *, after=False)

Insert a value card at a specified position.

A duplicate: if keyword already has a card, a second card with the same keyword is inserted rather than replacing it.

Parameters:
  • position (int or str) – Integer index (0 = first card; an index at or past the current card count appends at the end), or the keyword of an existing card, in which case the new card is inserted before or after it depending on after.

  • keyword (str) – Card keyword. May be a HIERARCH name.

  • value (bool, int, float, complex, str, or None, optional) – Card value. None (the default) records an undefined-value card.

  • comment (str, optional) – Inline comment. Default None, which emits no comment.

  • after (bool, optional) – When position is a keyword, set after=True to insert the new card just after that card rather than before it. Default False. Ignored when position is an integer.

Raises:
  • KeyError – If position is a keyword that does not exist.

  • TypeError – If position is neither int nor str, or if value is not one of the accepted types.

  • ValueError – If the header is read-only, or if keyword names a structural card (see the class Notes for the full list).

  • FitsError – If keyword exceeds 8 characters or contains an invalid character (a HIERARCH keyword is exempt from the length limit).

items()

All (keyword, value) pairs in declaration order.

Commentary cards (COMMENT, HISTORY, blank) report None for the value.

Returns:

list of tuple

keys()

All keywords in declaration order.

Duplicates are kept, matching FITS semantics where HISTORY and COMMENT cards repeat.

mjd_avg_utc

Average/mid time of the observation as UTC MJD.

Reads MJD-AVG or DATE-AVG and converts from TIMESYS; falls back to the midpoint of mjd_begin_utc and mjd_end_utc when neither is present.

mjd_begin_utc

Start of the observation as UTC MJD.

Tries, in order: MJD-BEG; DATE-BEG; TSTART added to the reference epoch and TIMEOFFS; UTSTART combined with the date from DATE-OBS. The first three are converted from TIMESYS to UTC; UTSTART is UTC already.

mjd_end_utc

End of the observation as UTC MJD.

Tries, in order: MJD-END; DATE-END; TSTOP added to the reference epoch and TIMEOFFS; UTSTOP combined with the date from DATE-OBS. The first three are converted from TIMESYS to UTC; UTSTOP is UTC already.

mjd_obs_utc

Observation start converted to UTC MJD, regardless of TIMESYS.

Handles the full set of time scales defined in WCS Paper IV: UTC, GMT, TAI, TT/TDT/ET, GPS, TCG, TDB, and TCB. Barycentric/geocentric scales are reduced to TT via the linear relations in Sec.3.1.2 before the leap-second table is applied.

Returns:

float or None – UTC MJD of the observation start, or None if the observation time is absent or the time scale cannot be reduced to UTC (e.g. LOCAL, UT1).

mjd_ref

Reference epoch as MJD. Reads MJDREFI``+``MJDREFF -> MJDREF -> JDREFI``+``JDREFF -> JDREF -> DATEREF. Zero point for relative time values in the HDU.

obs_ecef

Observatory location as ITRS/ECEF Cartesian (x, y, z) in meters. Reads OBSGEO-X/Y/Z directly; falls back to geodetic keywords converted via WGS84.

obs_geodetic

Observatory geodetic coordinates (lat_deg, lon_deg, alt_m) on the WGS84 ellipsoid.

Tries OBSGEO-B/L/H first, then non-standard variants (SITELAT, SITELONG, SITEELEV, etc.). None if neither latitude nor longitude is present.

obs_orbit

URI, URL, or name.

Type:

Orbit ephemeris file (OBSORBIT)

read_only

True when this header was obtained from a read-only file.

In that case, mutating methods raise ValueError.

rename_keyword(oldname, newname)

Rename every value card whose keyword equals oldname to use newname.

Parameters:
  • oldname (str) – Existing keyword.

  • newname (str) – Replacement keyword. Must be a valid FITS or HIERARCH keyword.

Raises:
  • ValueError – If the header is read-only, or if oldname or newname names a structural card (see the class Notes for the full list). Checked before newname validity and before oldname is looked up.

  • FitsError – If newname exceeds 8 characters or contains an invalid character (a HIERARCH keyword is exempt from the length limit). Checked before oldname is looked up, so this can fire even when oldname does not exist.

  • KeyError – If no card with oldname exists.

set(keyword, value=None, comment=None, *, before=None, after=None)

Set a header card with optional positional placement.

If keyword already exists, its value is replaced (or kept, if value is omitted) and its comment is replaced when comment is given. Otherwise a new card is appended, unless before or after is given, in which case the new card is inserted at that position.

Parameters:
  • keyword (str) – Card keyword. May be a HIERARCH name.

  • value (bool, int, float, complex, str, or None, optional) – New value. If omitted and the card already exists, only the comment is updated and the existing value is kept. If omitted and the card does not exist, the new card is inserted with an undefined value. Default None.

  • comment (str, optional) – New comment. None leaves the existing comment intact when updating, or emits no comment when inserting. Default None.

  • before (str, optional) – Insert the new card immediately before the first card whose keyword equals this. Ignored if keyword already exists. Default None.

  • after (str, optional) – Insert the new card immediately after the first card whose keyword equals this. Ignored if keyword already exists. Mutually exclusive with before. Default None.

Raises:
  • ValueError – If both before and after are supplied, if the header is read-only, or if keyword names a structural card (see the class Notes for the full list).

  • KeyError – If the named before/after card does not exist.

  • TypeError – If value is not one of the accepted types.

  • FitsError – If keyword exceeds 8 characters or contains an invalid character (a HIERARCH keyword is exempt from the length limit).

time_elapsed

Wall-clock elapsed time in seconds (TELAPSE), including dead time. None if absent or TIMEUNIT is unrecognized.

time_exposure

Effective exposure time in seconds, excluding dead time.

This reads XPOSURE, scaled by TIMEUNIT or by a per-card [unit] annotation when one is present. It falls back to EXPTIME, which predates the standard and is always in seconds, when XPOSURE is absent.

Returns:

float or None – The exposure time in seconds. None when neither keyword is present, and when XPOSURE is present but its unit is not a recognized time unit.

time_sys

Active time scale (TIMESYS), trimmed and upper-cased.

Returns "UTC" when the keyword is absent, per the FITS standard default. The value is read back verbatim, so a header with an unrecognized or malformed TIMESYS still returns that text; this getter does not validate it against the WCS Paper IV Table 1 time scales that mjd_obs_utc and its siblings understand.

time_unit

Time unit for numeric time values (TIMEUNIT), lower-cased.

Returns "s" when the keyword is absent (FITS standard default).

to_dict()

Plain dict view of the header.

Inline comments are dropped. A commentary card (COMMENT, HISTORY, blank-keyword) carries no value and is omitted entirely, not even as a None entry. A duplicated value keyword is deduplicated to its last-seen value. Convenience for ad-hoc work; round-trip fidelity requires items().

tostring()

Serialize the header as a single string of 80-character FITS cards (no separators, terminated by END and padded to a 2880-byte block). The text round-trips through fromstring().

Returns:

str – The serialized header text.

Raises:

ValueError – If a card cannot be serialized: a non-finite (NaN or infinite) real value, or a string or commentary card holding a byte outside printable ASCII. These are accepted without checking by __setitem__(), set(), insert() and add_commentary(), and rejected only here.

unit_for(key)

Unit string for a keyword’s [unit] comment annotation.

Parameters:

key (str) – Keyword to look up (case-insensitive).

Returns:

str or None – The unit text, or None if the keyword is absent or its comment carries no [unit] annotation.

update(other)

Merge another header (or a str-keyed mapping) into this one.

For each (key, value) in other, an existing keyword’s value is overwritten in place and a new keyword is appended. A mapping value may be a bare scalar or a (value, comment) tuple, as for __setitem__(). Unlike __setitem__(), a structural keyword (see the class Notes) is copied unchecked rather than rejected.

Commentary cards (COMMENT, HISTORY, blank-keyword) are not copied; use add_commentary() if you want to transfer them explicitly.

Parameters:

other (Header or Mapping[str, Any]) – The values to merge in. Header instances copy their value cards; mappings are iterated in declaration order.

Raises:
  • ValueError – If the header is read-only.

  • TypeError – If other is neither a Header nor an object with an .items() method, or if one of its values is not a bool, int, float, complex, str or None.

  • FitsError – If a keyword copied from other exceeds 8 characters or contains an invalid character.

Notes

A mapping key is folded to upper case, as header[key] = value folds its key.

validate(fix=False, warn=True)

Check the header for deprecated, non-standard, or missing keywords.

Parameters:
  • fix (bool, optional) – When True, every suggested fix is applied to the returned header copy. Defaults to False.

  • warn (bool, optional) – When True (the default), each issue is emitted as a Python warnings warning prefixed with [warning] or [error]. Set to False to suppress all output.

Returns:

Header – A new independent snapshot of this header (fixed when fix=True, otherwise an unmodified clone).

value_in_si(key)

Value of key converted to the canonical unit for its physical dimension: meters for length, seconds for time, degrees for angle, and so on.

Reads the source unit from the keyword’s [unit] comment annotation and applies the conversion factor.

Parameters:

key (str) – Keyword to look up (case-insensitive).

Returns:

float or None – The converted value, or None if the keyword is absent, non-numeric, carries no [unit] annotation, or the annotation is not a recognized unit.

class fitsy.HeaderCommentary

Bases: object

List-like view of every commentary card body that shares a keyword (COMMENT, HISTORY, blank-keyword). Returned by header[key] for one of those three keywords.

  • len(view) – number of cards

  • view[i] – text body of the i-th card

  • str(view) / repr(view) – newline-joined bodies

  • iterable

__getitem__(key, /)

Return self[key].

__iter__()

Implement iter(self).

__len__()

Return len(self).