Skip to content

Working with headers

Every HDU carries its header as a FitsHeader. The class exposes typed accessors and iteration over the raw cards.

const naxis = hdu.header.getNumber("NAXIS"); // number | undefined
const obs = hdu.header.getString("OBSERVER"); // string | undefined
const simple = hdu.header.getBoolean("SIMPLE"); // boolean | undefined
const raw = hdu.header.get("BSCALE"); // HeaderValue

HeaderValue is string | number | bigint | boolean | FitsComplex | undefined. The typed accessors narrow the result and return undefined when the keyword is missing or holds the wrong type.

Axis lengths are NAXIS1, NAXIS2, …. Table columns are TFORM1, TFORM2, …. The header treats those as ordinary keywords. Build the name with template literals.

const naxis = hdu.header.getNumber("NAXIS") ?? 0;
const dims: number[] = [];
for (let i = 1; i <= naxis; i++) {
dims.push(hdu.header.getNumber(`NAXIS${i}`) ?? 0);
}

Long string values that span multiple cards via the CONTINUE convention are assembled into a single string by the parser. Long keywords using the HIERARCH convention (including the ESO dialect) are matched on the full keyword text.

const longName = hdu.header.getString("ESO INS PIPE DETECT");
const longText = hdu.header.getString("FILENAME"); // CONTINUE-assembled

Lookups use the bare hierarchical name. The HIERARCH prefix marks the convention on the card and is not part of the stored keyword.

for (const c of hdu.header.comments) console.log("COMMENT:", c);
for (const h of hdu.header.history) console.log("HISTORY:", h);

Each list contains the text bodies of the corresponding cards in file order.

A header may legitimately repeat a keyword. get returns the first match. getAll returns every value in card order.

const firstHistory = hdu.header.get("HISTORY");
const allHistory = hdu.header.getAll("HISTORY");

openFits handles whole files. When you already hold header bytes without a file around them, parseHeader parses a FitsHeader straight from a buffer. It walks the 2880-byte blocks until the END card and resolves CONTINUE long strings. Nothing past the header is touched.

import { parseHeader } from "@fits-js/core";
const { header, byteLength, warnings, endFound } = parseHeader(bytes);
header.getNumber("NAXIS"); // 2
// the data unit begins at byteLength

byteLength is always a multiple of 2880 and marks where the data unit (or the next HDU) starts. endFound is false when the supplied bytes ran out before an END card appeared. Like openFits, the parser is lenient by default and reports recovered violations on warnings. Pass { strict: true } to throw instead.