Known limitations ================= rustfits aims for parity with astropy and fitsio on the modern FITS feature set, but a handful of edge cases aren't yet implemented (or are deliberately out of scope). This page lists them and shows the workaround where one exists. Each item is tagged: * **(not yet)** — on the roadmap; will land when prioritized or when a user prompts for it. File an issue if you hit one. * **(by design)** — deliberately not supported; the workaround is the recommended path. Tables ------ * **TNULL masking on VLA columns** *(not yet)* — ``mask_null=True`` works for fixed B/I/J/K columns but raises on VLA columns with a TNULL card in the header. Read with ``mask_null=False`` and apply the mask yourself for now. * **Variable-length columns with TDIMn** *(not yet)* — TDIMn on a P/Q column would reshape each heap cell to the declared dims, useful for VLA-of-images, but with a quirk: the spec only allows ONE variable axis per cell, so fully variable ``(n, m)`` shapes aren't expressible in FITS without padding. * **``TDISPn`` on write** *(by design)* — the display-format hint isn't emitted by rustfits's writers. Add it by hand via ``header["TDISP1"] = ...`` if you need it; it's informational per the spec. Images ------ The image surface (read, slice, write, ``extend``, ``__setitem__``, BLANK / MaskedArray, BSCALE/BZERO, unsigned-int trick) is feature-complete for both uncompressed and tile-compressed HDUs. One narrow gap: * **Per-tile ZBLANK column** *(not yet)* — header-level ZBLANK on compressed integer images is supported. The convention also allows a per-tile *column*-form ZBLANK; rustfits doesn't read it. Rare in practice — cfitsio typically emits the header form even for DITHER_2. General ------- * **Multithreaded throughput (GIL release)** *(not yet)* — rustfits releases the GIL only during remote (``http`` / ``ftp``) downloads. The heavy CPU paths — tile decode/encode, large chunked I/O, checksum — currently hold it, so several Python threads calling into rustfits serialize on those. Single-threaded use is unaffected (the common case). Releasing the GIL around the pure-Rust decode/encode spans is a targeted future change, gated on a real multithreaded workload — file an issue if you have one. * **Random groups** (``GROUPS=T``, ``PTYPEn``) *(by design)* — legacy format; vanishingly rare in new files. Not on the roadmap. Cross-tool interop caveats -------------------------- These aren't rustfits limitations per se — they're points where the FITS ecosystem disagrees and rustfits picks one side. * **astropy ``1PX(N)`` parser** — astropy 7.2.0 rejects bit- packed VLA columns (``1PX``/``1QX``) with ``VerifyError`` during column setup. rustfits writes spec-conforming ``1PX(maxbits)`` headers, but astropy can't currently read them; fitsio (built on cfitsio) reads them fine. See the pinning test ``test_astropy_pxqx_documented_limitation``. * **astropy ``CompImageHDU`` verify_checksum** — astropy's ``verify_checksum`` for compressed HDUs has its own internal bug (TypeError on ``_compute_checksum(None)``) that triggers on its own writes too. rustfits's self-verify is correct; we don't cross-verify ZHECKSUM against astropy. * **i8 (``TLONGLONG``) RICE compression** — cfitsio's encoder doesn't support 64-bit RICE; fitsio refuses the write. rustfits rejects ``compress=Rice1()`` + i8 dtype upfront and points at ``compress=Gzip2(...)`` instead. Files we wrote with i64 RICE would be unreadable everywhere except rustfits.