CompressedImageHDU

Tile-compressed image HDU (ZIMAGE convention). Subclass of rustfits.ImageHDUisinstance(hdu, ImageHDU) holds.

class rustfits.CompressedImageHDU

Bases: ImageHDU

__getitem__(key, /)

Return self[key].

__len__()

Return len(self).

__setitem__(key, value, /)

Set self[key] to value.

add_checksum()

Compute and store both ZDATASUM and ZHECKSUM cards.

Same convention as add_datasum(). This is the call most users want.

add_datasum()

Compute and store the ZDATASUM checksum card.

Computed against the equivalent uncompressed image bytes, not the on-disk BINTABLE, per the FITS Tile Compression Convention. Same manual-refresh contract as ImageHDU.add_datasum() — re-run after write() / extend() / __setitem__.

bitpix

Raw FITS ZBITPIX value (the image-side bitpix the user reads into). Distinct from hdu.header["BITPIX"] (which is 8, the BINTABLE BITPIX on disk).

clear_tile_cache()

Drop every cached tile.

Keeps tile_cache_size as-is, so subsequent decodes will repopulate. Useful right after a one-shot read() to release the tile copies while keeping the cache configured for later slicing.

compression

Compression configuration of this HDU.

Returns the same Gzip1 / Gzip2 / Rice1 / Hcompress1 / Plio1 pyclass instance that would have been passed to FITS.create_image_hdu()’s compress= argument to reproduce the on-disk layout. Single source of truth for “how is this HDU compressed”:

if isinstance(hdu.compression, rustfits.Rice1):
    print(hdu.compression.blocksize)

The FITS-spec ZCMPTYPE string is available as hdu.compression.zcmptype; tile shape as hdu.compression.tile_shape. Two HDUs can be compared with hdu_a.compression == hdu_b.compression (field-wise __eq__).

Notes

For HDUs that were just created in this Python session, the returned object is the exact config passed to create_image_hdu(..., compress=...) — write-only parameters (like Gzip1(level=9)) round-trip. For reopened HDUs, the config is rebuilt from header cards; the level field comes back as None because gzip framing doesn’t preserve the level.

dtype

The numpy dtype read() would return. Sourced from ZBITPIX.

extend(data)

Append new pixels along the slow axis.

Same shape contract as ImageHDU.extend(): data inner-axis shape must match hdu.shape[1:]; the slow axis can be any size.

Unlike ImageHDU.extend(), there is no start= argument — writes to existing tile rows are __setitem__’s job (which re-encodes the affected tiles in place). extend only appends at the end of the slow axis. Partial last tiles are handled: the boundary tile is decoded, combined with the first portion of new data, and re-encoded.

A first extend on an empty HDU created with create_image_hdu(dtype, (0, ...), compress=...) fills a streaming-write compressed image (every algorithm except HCOMPRESS_1, which requires every axis >= 4 at create time).

Notes

Validate-then-mutate; mid-write I/O failures taint the file. Old boundary-tile bytes become orphans; call repack() to reclaim them.

extending()

Open a batched-extend context manager.

Inside the with block every extend() call buffers its input in RAM rather than re-encoding the trailing partial tile on every call. The buffer is concatenated and handed to the existing extend code once at __exit__ (normal or exceptional), collapsing N partial-tile re-encodes into 1.

Pattern:

with hdu.extending():
    for batch in batches:
        hdu.extend(batch)
    # __exit__ here: drains the buffer

Performance: a sub-tile-chunk extend loop costs roughly write-once total instead of N × partial_tile_cost; see the “2-D image extend” section of the user-facing performance docs for the measured numbers.

Restrictions inside the context (raise ValueError): read(), __getitem__, write(), __setitem__, repack(), add_checksum(), add_datasum(), verify_checksum(), verify_datasum(). Exit the context first. FITS.close() also raises while a context is open (the natural nested-with pattern never triggers this; it fires only for forgotten __exit__).

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].

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.

n_tiles

Number of tile chunks the image is split into on disk.

Product of ceil(ZNAXISn / ZTILEn) across all axes. Storage-layout property (kept here rather than on compression because it’s about how the BINTABLE is laid out, not the algorithm).

ndim

Number of image axes. Sourced from ZNAXIS.

read(*, scale=True, mask_blank=False)

Read the (decompressed) image into a numpy array.

Same signature and semantics as ImageHDU.read(): scale applies BSCALE/BZERO; mask_blank returns a MaskedArray on ZBLANK matches.

Notes

Tile cache: every tile decoded during the read populates the LRU cache (subject to tile_cache_size). This makes subsequent overlapping slicing reads hit warm tiles. To run cache-free, set set_tile_cache_size(0) before the read, or call clear_tile_cache() afterward.

repack()

Rebuild the tile-data heap, reclaiming orphan tiles.

extend() (when a partial last tile is re-encoded) and __setitem__ (every affected tile is re-encoded and appended to the heap) both leave the old compressed bytes as orphans referenced by no descriptor. repack walks every live descriptor, streams its referenced bytes into a compact new heap, and rewrites the descriptors to point at it. If the heap shrinks, the on-disk file shrinks too: the last HDU uses set_len, a non-last HDU shifts the trailing HDUs backward in lockstep.

Also clears the tile cache (its entries were keyed against the old heap layout).

No-op for an already-compact heap.

set_tile_cache_size(bytes)

Set the cache capacity in bytes.

Setting to 0 disables caching entirely — every decode is one-shot, useful for memory-constrained workflows. Shrinking the cap below current usage evicts LRU tiles to fit.

shape

Original image dimensions in numpy axis order (slowest first). Sourced from ZNAXISn; the user sees what read() would return, not the on-disk BINTABLE shape.

size

Total pixel count (product of all ZNAXISn).

tile_cache_size

Current cache capacity in bytes.

Default 32 MiB. Reads and slicing both consult this budget — there’s no per-call opt-out. Tune with set_tile_cache_size().

tile_cache_used

Bytes currently held in the tile cache.

Useful for monitoring memory usage and for tests that assert eviction worked.

unit

BUNIT header value, or None when unset. Informational only.

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 ZDATASUM against the equivalent uncompressed image bytes.

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

write(data, start=None)

Write the entire image (encoding tile-by-tile).

Same input contract as ImageHDU.write() — data must match the HDU shape exactly. start= is rejected because compressed writes are encode-once per tile; partial writes don’t compose with the tile-encoding model. Use __setitem__ for region updates instead.

Validate-then-mutate: every tile is encoded into RAM first; only after all encodes succeed does the file grow + descriptor table + heap get written. A dtype or shape error leaves the file untouched.

Parameters:
  • data (numpy.ndarray or numpy.ma.MaskedArray) – See ImageHDU.write() for the dtype rules (BITPIX-native, scaled, or f8 for general scaling; MaskedArray auto-fills via ZBLANK or NaN).

  • start (Any, optional) – Not supported. Passing anything other than None raises NotImplementedError.