AsciiTableHDU

ASCII table HDU (XTENSION='TABLE'). Sibling of rustfits.TableHDU (NOT a subclass — the on-disk layout differs enough that a unified inheritance would put if ascii branches throughout BINTABLE methods). Subclass of rustfits.HDU.

The read / write / edit surface matches rustfits.TableHDU one-for-one (minus VLA / X / subarray / complex / compression, which the FITS spec doesn’t allow for ASCII tables). See the Tables tutorial for the surface tour and the ASCII-specific gotchas.

class rustfits.AsciiTableHDU

Bases: HDU

An ASCII-table extension HDU (XTENSION='TABLE').

ASCII tables store row data as fixed-width text, distinct from binary tables (TableHDU). Returned by indexing a FITS object at a position containing a TABLE HDU.

Reads return a numpy structured array whose dtype reflects the per-column TFORMn mapping:

  • Aw (text) → U<w> (numpy unicode string)

  • Iw (integer) → i8

  • Fw.d / Ew.d (single-precision float) → f4 when d <= 7; f8 when d > 7 (cfitsio’s E26.17 default for f8 input is correctly read as f8)

  • Dw.d (double-precision float) → f8

Default scale=True applies TSCAL / TZERO: the unsigned-int trick on I columns (with TZERO=2**63) promotes to u8, and other non-trivial scaling produces f8. Pass scale=False for raw stored values. Default mask_null=False returns a plain ndarray; pass True for a numpy.ma.MaskedArray with cells matching TNULLn masked.

Indexing supports the same forms as TableHDU:

arr = hdu[5] # one row as a np.void record arr = hdu[10:20] # 10 rows as a structured ndarray arr = hdu[[1, 3, 5]] # fancy row select col = hdu[“RA”] # SingleColumnSubset (deferred read) sub = hdu[[“RA”, “DEC”]] # ColumnSubset (deferred read)

ASCII tables are rare in modern FITS files; most data pipelines use binary tables instead. Both round-trip bit-exactly with astropy and fitsio.

__getitem__(key, /)

Return self[key].

__len__()

Return len(self).

__setitem__(key, value, /)

Set self[key] to value.

add_checksum()

Compute and store both DATASUM and CHECKSUM cards.

Same semantics as TableHDU.add_checksum(). This is the call most users want — writes both cards atomically.

add_datasum()

Compute and store the DATASUM checksum card.

Same semantics as TableHDU.add_datasum(): manual refresh, no auto-update on mutation. Call after write() / append() / __setitem__.

append(data, *, names=None)

Append rows to the end of the table.

Grows NAXIS2 and the data section. For non-last HDUs, the file tail shifts forward and later-HDU offsets are bumped in lockstep; previously-issued handles remain valid.

Parameters:
  • data (numpy.ndarray, dict, or list/tuple of ndarrays) – Same three input forms as write(). Length defines the number of new rows.

  • names (list of str, optional) – Required for the list/tuple form; ignored otherwise.

Notes

Validate-then-mutate: dtype / shape errors are raised before any file bytes are touched. Mid-write I/O failures taint the file.

appending()

No-op batched-append context manager.

ASCII-table appends go straight to disk (no partial-trailing- tile re-encode tax to amortize), so this context does nothing on enter or exit — it exists for API symmetry with CompressedTableHDU.appending(), where the context does meaningful work. Generic code that iterates HDUs of mixed types can use the pattern uniformly:

for hdu in fits:
    with hdu.appending():
        for batch in batches:
            hdu.append(batch)
colnames

Column names in on-disk order, as a tuple.

delete_column(key)

Delete a column from the table.

Parameters:

key (str or int) – Column name (case-insensitive) or 0-based integer index (negative wraps).

Notes

Every column after the deleted slot has its TBCOLn byte-position reduced by the deleted column’s width. The data section shrinks accordingly; for non-last HDUs the file tail is shifted backward and previously-issued HDU handles transparently see the new offsets.

Mid-write I/O failures taint the file (close + reopen to recover).

dtype

The numpy structured dtype the table reads into.

extend(data, *, names=None)

Alias for append().

Mirrors TableHDU.extend() so generic code that iterates HDUs and calls .extend(...) keeps working.

extending()

Alias for appending(). Mirrors TableHDU.extending() so generic code that iterates HDUs of any type can use with hdu.extending(): uniformly.

extname

EXTNAME header value, or None when the keyword is absent.

EXTNAME is the user-visible name of the HDU (e.g. 'SCI', 'CATALOG'). Combined with extver it’s the standard way to identify HDUs without relying on position-by-index.

extver

EXTVER header value, defaulting to 1 when absent.

Per the FITS standard, multiple HDUs may share an EXTNAME and are distinguished by EXTVER. Returns 1 rather than None for the absent case so callers can compare/select without handling Optional[int].

formats

Per-column FITS format strings, as a dict.

Reconstructs the on-disk TFORMn for every column in the same shape create_ascii_table_hdu() accepts via its formats= kwarg. Round-trips:

with rustfits.FITS("dest.fits", "w+") as f:
    f.create_ascii_table_hdu(
        src_hdu.dtype,
        formats=src_hdu.formats,
        nrows=src_hdu.nrows,
    )

Format shapes: A<w> and I<w> for string / integer columns; F<w>.<d>, E<w>.<d>, D<w>.<d> for the fixed / single-exponent / double-exponent floats.

has_data

True iff this HDU has a non-empty data section.

Works uniformly across image and table HDUs: the test is NAXIS > 0 AND every NAXISn > 0. For images that means “at least one pixel”; for tables it means “at least one row of at least one column”.

Useful for picking the first HDU worth reading in a file (primary HDUs are often empty stubs):

hdu = next(h for h in fits if h.has_data)
arr = hdu.read()

Edge case: a VLA table with NAXIS2=0 but PCOUNT>0 (heap-only) returns False — no main rows means there’s nothing to interpret the heap through, which is the right answer for the “is this HDU worth reading?” question.

header

The HDU’s FITSHeader.

Returns a live view of this HDU’s header cards. Mutations via the header object (__setitem__, __delitem__, update, add_comment, add_history, add_blank) write through to disk immediately, following the disk-write-before-commit ordering documented on FITSHeader.

Reads are cheap; mutations may grow the reserved header blocks in place if the new card list exceeds the current allotment.

index

The HDU’s 0-based position in its file.

Stable for the lifetime of the FITS object — even when an earlier HDU grows and shifts this HDU’s bytes forward, the index is unchanged because the HDU is still at the same position in the file’s HDU list.

insert_column(name, data, *, position=None, after=None, before=None, unit=None, format=None)

Insert a new column into the table at the given position.

Parameters:
  • name (str) – Column name (case-insensitive on subsequent lookup).

  • data (numpy.ndarray) – 1-D ndarray of length NAXIS2. Supported dtype kinds: i? (any signed-int width) → I20; u?I20 + TZERO=2**63 (unsigned-int trick); f4E15.7; f8D25.17; S<w> / U<w>A<w>. Object-dtype (VLA) is rejected — ASCII tables have no heap.

  • position (int, optional) – 0-based slot for the new column (0..=ncols). Default appends at the end. At most one of position / after / before may be set.

  • after (str or int, optional) – Insert just after this column (name case-insensitive, or 0-based integer index with negative wrap-around).

  • before (str or int, optional) – Insert just before this column.

  • unit (str, optional) – TUNITn informational unit string.

  • format (str, optional) – Override the auto-picked TFORM string (e.g. "I10", "F12.4", "E15.7", "D25.17", "A20"). Letter must be compatible with the input dtype kind.

Notes

Validate-then-mutate: the input is fully validated before any file or header bytes are touched. Mid-write I/O failures taint the file (close + reopen to recover).

For non-last HDUs the file tail shifts forward to make room for the wider rows; previously-issued HDU handles transparently see the new offsets via the shared layout.

Every column at or after the new column’s position has its TBCOLn byte-position bumped by the new column’s width.

iter(*, chunksize=None, columns=None, scale=True)

Iterate over table rows or row-chunks.

hdu.iter() is equivalent to for row in hdu — one row per iteration as a numpy scalar record. Passing chunksize switches to yielding structured arrays instead.

Parameters:
  • chunksize (int, optional) – None (default) yields one row per iteration as a numpy scalar record. A positive integer yields a structured ndarray of up to chunksize rows per iteration.

  • columns (list of str, optional) – Restrict iteration to these columns (case-insensitive), forwarded to read().

  • scale (bool, default True) – Apply scaling, forwarded to read().

ncols

Number of columns in the table (TFIELDS).

nrows

Number of rows in the table (NAXIS2).

read(*, rows=None, columns=None, scale=True, mask_null=False)

Read rows from the table into a numpy structured array.

Parameters:
  • rows (slice, int, or iterable of int, optional) – Rows to read. None (default) reads every row in file order. A slice or iterable selects a subset; negative indices supported. Iterables are deduped with first-occurrence-wins ordering.

  • columns (list of str, optional) – Column names to read (case-insensitive against the table’s column names). None (default) reads every column in file order. A list selects + reorders.

  • scale (bool, optional) – If True (default), apply TSCAL / TZERO scaling. See the class docstring for per-letter rules.

  • mask_null (bool, optional) – If True, return a numpy.ma.MaskedArray with cells masked where the trimmed field text equals the trimmed TNULLn string. Compare is on stored text (pre-scaling). Columns without TNULLn stay unmasked.

Returns:

Structured array of shape (n_selected,) with one field per selected column.

Return type:

numpy.ndarray or numpy.ma.MaskedArray

read_column(name, *, rows=None, as_bytes=False, scale=True, mask_null=False)

Read one column into a plain (non-structured) ndarray.

Parameters:
  • name (str) – Column name (case-insensitive).

  • rows (slice, int, or iterable of int, optional) – Row subset to read. None (default) reads every row.

  • as_bytes (bool, optional) – For A columns only. If True, return raw on-disk bytes in an S<width> ndarray (no trim, no ASCII validation) — escape hatch for non-ASCII content the default U decode would reject.

  • scale (bool, optional) – Apply TSCAL / TZERO scaling. Default True.

  • mask_null (bool, optional) – Return a numpy.ma.MaskedArray with cells matching TNULLn masked. Default False.

units

Per-column units (TUNITn), as a dict.

verify_checksum()

Verify the stored CHECKSUM over the full HDU.

Returns True / False / None (None means the card is absent).

verify_datasum()

Verify the stored DATASUM against the current data.

Returns True / False / None (None means the card is absent).

write(data, *, names=None)

Bulk-write data into the table’s data section.

Overwrites all NAXIS2 rows in the table; for appending new rows instead use append(). Accepts three input forms (matching TableHDU.write()):

  • Structured ndarray — field names must match the HDU’s columns (case-insensitive); extras / missing rejected. len(data) must equal NAXIS2.

  • Dict {name: ndarray} — one entry per HDU column; extras / missing rejected.

  • List or tuple of ndarrays with names=[...] — parallel sequences; same per-column model as dict.

Parameters:
  • data (numpy.ndarray, dict, or list/tuple of ndarrays)

  • names (list of str, optional) – Required only when data is a list/tuple.

Notes

Validate-then-mutate: dtype / length errors are raised before any file bytes are touched. Mid-write I/O failures taint the file (close + reopen to recover).