FITS file object¶
- class rustfits.FITS(filename, mode='r', *, lenient=False)¶
Bases:
objectA FITS file open for reading, writing, or both.
- Parameters:
filename (str) – Path to the FITS file.
mode ({'r', 'r+', 'w+'}, optional) –
File open mode.
'r'(default) — read-only; the file must exist.'r+'— read+write; the file must exist. Used to modify or append HDUs to an existing file.'w+'— read+write; creates the file if it doesn’t exist, truncates to zero length if it does. Equivalent to fitsio’s'rw'+clobber=True.
lenient (bool, optional, keyword-only) –
If
False(default), header blocks must contain only printable ASCII bytes (0x20-0x7E); any other byte is rejected at open with a clear error. This is the right default for most workflows — if the file opened, every header byte was spec-compliant.If
True, non-printable bytes are substituted in place with_(matches astropy’s substitution rule) and parsing proceeds normally. Useful for archive files written by older non-conforming tools (IDL MWRFITS in particular emits keys with non-ASCII bytes the standard disallows). Lenient mode is READ-only — new card mutations throughheader[k] = vstill go through strict validation.
Examples
FITS is the top-level entry point of rustfits. Open an existing file or create a new one, then index or iterate to reach individual HDUs:
# Read an existing file with rustfits.FITS("data.fits") as fits: for hdu in fits: print(hdu.extname, hdu.has_data) sci = fits["SCI"] # by EXTNAME hdu2 = fits[2] # by position arr = fits[1].read() # The default mode is "r", so the above is the same # as as FITS(fname, "r") # Open for read and write. # Append a new HDU to an existing file with rustfits.FITS("data.fits", "r+") as fits: fits.create_image_hdu("f4", (100, 100), extname="MODEL") fits[-1].write(model) # Create a new file (or truncate an existing one) with rustfits.FITS("out.fits", "w+") as fits: fits.create_table_hdu(my_dtype, nrows=1000) fits[1].write(rows)
Notes
Use as a context manager (
with rustfits.FITS(...) as fits:) to guarantee the file handle is closed.len(fits)returns the HDU count; iteration yields each HDU in file order.- __getitem__(key, /)¶
Return self[key].
- __iter__()¶
Implement iter(self).
- __len__()¶
Return len(self).
- close()¶
Close the file handle.
Called automatically when the
FITSis used as a context manager (with rustfits.FITS(...) as fits:). Safe to call multiple times. After closing, attempting any read or write through the FITS object or its HDUs raisesIOError.Does NOT fsync: data is left in the OS page cache, which persists across normal program exit (matches fitsio and astropy). Power-loss or kernel-panic safety requires an explicit
sync()call beforeclose().
- closed¶
Trueonceclose()(or context-manager__exit__) has been called;Falsewhile the file is open.
- create_ascii_table_hdu(dtype, nrows=0, *, extname=None, extver=None, units=None, formats=None)¶
Create a new ASCII-table (
XTENSION='TABLE') HDU and append it to the file.Allocates the data section as ASCII spaces — call
AsciiTableHDU.write()(or the returned HDU viafits[-1]) to write row data.ASCII tables are rare in modern FITS files; most data pipelines use binary tables (
create_table_hdu()). The ASCII form is provided for compatibility with tools that emit it (e.g. legacy pipelines, hand-edited files).If the file has no HDUs yet, an empty primary image (
SIMPLE=T,NAXIS=0) is written first — ASCII tables can’t be primary HDUs per the FITS standard.- Parameters:
dtype (numpy.dtype or list of tuples) –
Structured dtype describing the table schema. Supported field dtypes (auto-mapped to TFORM):
i2/i4/i8→I20u1/u2/u4/u8→I20+TZERO=2^63(unsigned-int trick)f4→E15.7f8→D25.17S<n>/U<n>→A<n>
b1(bool) andi1are rejected — neither has a native ASCII-table TFORM letter. Subarray fields and Object (VLA) dtypes are not supported (use BINTABLE).nrows (int, optional) – Initial row count. Default
0.extname (str, optional)
extver (int, optional)
units (dict, optional) –
{column_name: unit_string}forTUNITncards.formats (dict, optional) – Per-column TFORM override, e.g.
{"FLUX": "F12.4"}. Keys are case-insensitive; unmatched keys raise. Values are FITS TFORM strings (A<w>/I<w>/F<w>.<d>/E<w>.<d>/D<w>.<d>). Override letter must be compatible with the input dtype kind.
- Raises:
ValueError – Negative
nrows; unsupported field dtype; subarray or Object field;formats=override incompatible with the input dtype.
See also
create_table_hduBinary-table counterpart (preferred).
AsciiTableHDU.writeWrite data into the created table.
- create_image_hdu(dtype, dims, *, extname=None, extver=None, compress=None, quantize=None, blank=None)¶
Create a new image HDU and append it to the file.
Allocates the data section as zeros via sparse-file extension — call
ImageHDU.write()(or use the returned HDU asfits[-1]) to actually write pixel data.The first HDU created becomes the primary HDU (
SIMPLE=T,EXTEND=T); subsequent calls produceXTENSION='IMAGE'extensions.- Parameters:
dtype (dtype-like) – Anything
numpy.dtype()accepts: a short-code string ('f8','i4','u2'), a numpy scalar type (numpy.int32,numpy.float64), a Python builtin (int,float), or anumpy.dtypeinstance. Normalized internally vianumpy.dtype(...). Both the BITPIX-native dtypes (u1/i2/i4/i8/f4/f8) and the unsigned-int trick dtypes (i1/u2/u4/u8) are accepted; the latter emit the correspondingBSCALE+BZEROcards.dims (sequence of int) – Image shape in numpy (row-major) axis order — slowest axis first. Reversed internally to produce FITS
NAXISn. Axis 0 (the slowest-varying axis) may be0to create an empty HDU that a laterImageHDU.extend()fills incrementally (parallel tocreate_table_hdu(nrows=0)+append). Every other axis must be> 0— the FITS standard forbids zero-pixel inner axes. (HCOMPRESS_1 additionally requires every axis>= 4, so the empty-axis-0 form is unavailable undercompress=Hcompress1(...).)extname (str, optional) –
EXTNAMEto assign. Defaults to no EXTNAME card.extver (int, optional) –
EXTVERto assign. Defaults to no EXTVER card.compress (Gzip1 / Gzip2 / Rice1 / Hcompress1 / Plio1, optional) – If set, create a tile-compressed image (
BINTABLE+ZIMAGEon disk, returned in Python as aCompressedImageHDU) instead of a plainIMAGEextension. All five algorithms are supported for integer dtypes; only GZIP_1 / GZIP_2 for unquantized floats; all-but-PLIO for quantized floats.quantize (Quantize, optional) – Per-tile quantization config for float-image compression:
rustfits.Quantize(level=..., method='dither1', seed=0). Required whencompress=is set and the dtype isf4/f8and you want lossy storage. Ignored for integer dtypes. Omit on float input to write losslessly (raw float bytes through GZIP).blank (int, optional) – Sentinel value for masked pixels (emits
BLANKfor uncompressed,ZBLANKfor compressed integer HDUs). Only valid for integer dtypes; float HDUs use NaN.
- Raises:
ValueError – Unsupported dtype, a non-positive inner dimension (axis 0 may be
0but must not be negative),quantize=withoutcompress=,blank=on a float dtype, or other algorithm/dtype incompatibilities (seeRice1/Hcompress1/Plio1for per-algorithm constraints).
See also
create_table_hduThe table-side counterpart.
Gzip1,Gzip2,Rice1,Hcompress1,Plio1QuantizePer-tile quantization config for float-image compression.
- create_table_hdu(dtype, nrows=0, *, extname=None, extver=None, units=None, var_dtypes=None, bit_columns=None, heap_format=None, compress=None, ztilelen=None)¶
Create a new BINTABLE extension HDU and append it to the file.
Allocates the data section as zeros — call
TableHDU.write()(or use the returned HDU asfits[-1]) to actually write row data.If the file has no HDUs yet, an empty primary image (
SIMPLE=T,NAXIS=0) is written first so the BINTABLE can land as an extension — the FITS standard forbids BINTABLE as the primary HDU.- Parameters:
dtype (numpy.dtype or list of tuples) – Structured dtype describing the table schema, or any form
numpy.dtype()accepts (e.g. a “descr” list like[('x', 'f4'), ('y', 'f4'), ('name', 'S10')]). For VLA columns, use Object dtype ('O') for the field and declare its inner type viavar_dtypes=.nrows (int, optional) – Initial row count. Default
0; subsequentTableHDU.write()requires the value to match this exactly, whileTableHDU.append()adds rows beyond it.extname (str, optional) –
EXTNAMEto assign.extver (int, optional) –
EXTVERto assign.units (dict, optional) –
{column_name: unit_string}to populateTUNITncards. Unspecified columns get no TUNIT.var_dtypes (dict, optional) – For VLA columns:
{column_name: inner_dtype_str}, whereinner_dtype_stris a numpy short-code for the per-cell element type ('f4'/'i4'/ etc.) or'S'for ASCII strings. The column itself must be declared as Object dtype ('O') indtype.bit_columns (list of str or True, optional) – Opt-in to bit-packed
Xstorage for bool columns: a list of column names (case-insensitive) restricts the opt-in to those columns;Trueis a soft global toggle for ALLb1columns. Default is one byte per bool (L).heap_format ({'P', 'Q'}, optional) – Descriptor format for VLA columns.
'P'(default) uses 8-byte descriptors with a 4 GB heap ceiling;'Q'uses 16-byte descriptors with no practical ceiling. Ignored when no VLA columns are declared.compress (str, bool, or per-algorithm config / dict, optional) –
Create a tile-compressed table (
ZTABLEon disk,CompressedTableHDUin Python) instead of a plain BINTABLE. Accepts:True— compress every column with cfitsio’s per-dtype defaults.a string alias (
'GZIP_1'/'GZIP_2'/'RICE_1') or config-class instance (Gzip1()/Gzip2()/Rice1()) — apply to every column.a dict
{column_name: algo}— per-column override; unspecified columns get the default.
ztilelen (int, optional) – Rows per tile for table compression. Defaults to cfitsio’s
max(1, min(nrows, 10_000_000 / row_width)). Requirescompress=; rejected otherwise.
- Raises:
ValueError – Negative
nrows; unsupported per-column dtype;var_dtypes=declared for a non-Object field;ztilelen=set withoutcompress=; invalidcompress=form; or an algorithm not legal for a column’s dtype (e.g.RICE_1on float).
See also
create_image_hduThe image-side counterpart.
TableHDU.writeWrite data into the created table.
TableHDU.appendAdd rows beyond
nrows.
- filename¶
Path passed to the constructor.
- static from_bytes(data, mode='r', *, lenient=False)¶
Parse a FITS file from in-memory bytes (no disk access).
- Parameters:
data (bytes) – Raw FITS bytes. Copied into a private in-memory buffer, so the returned
FITSis fully independent of the original object.mode ({'r', 'r+'}, optional) –
'r'(default) opens read-only;'r+'allows in-memory mutation of the private copy.'w+'is rejected because it would discard the bytes you just passed — useFITS("mem://", "w+")to create an empty in-memory file.lenient (bool, optional, keyword-only) – Same semantics as the
FITSconstructor: ifTrue, substitute non-printable header bytes with_instead of rejecting. DefaultFalse(strict). See theFITSdocstring for details.
- hdus¶
List of HDU objects in file order.
Equivalent to iterating the
FITSinstance, but returns a real Python list (e.g. for slicing / length queries without consuming the iterator).
- sync()¶
Force pending writes to disk (
fsync(2)).Optional durability for callers who must survive power loss or kernel panic between the last
write()and program exit. Normal program crashes (SIGSEGV,SIGKILL, uncaught exception) do NOT lose data without this call – the kernel’s page cache persists across process death. Expensive: blocks until the storage device confirms the write. Cheap to call repeatedly when there are no new dirty pages. No-op on already-closed files.
- to_bytes()¶
Return the FITS file’s current bytes as a Python
bytes.Primarily for in-memory files (
mem:///from_bytes()), where it extracts the file you built in RAM. Also works on a disk-backed file: it flushes, then reads the whole file into memory — note that the entire file lands in RAM, unlike the streaming read paths. Call it beforeclose(), which drops the buffer.
- write(data, *, extname=None, header=None)¶
Write
datato a new HDU, auto-detecting image vs table.Minimal-tier counterpart to
write_image()andwrite_table()— accepts only the universal kwargs (extname,header) and dispatches on the data type:plain (non-structured)
numpy.ndarray→write_image()structured
numpy.ndarray(dtype.fields is not None) →write_table(){name: array}dict →write_table()list-of-arrays +
names=→ rejected (callwrite_table()directly)anything else →
ValueError
Convenient for copying HDUs between files without caring about their type:
with rustfits.FITS(infile) as src: with rustfits.FITS(outfile, "w+") as dst: for hdu in src: if hdu.has_data: dst.write(hdu.read())
For knobs like
compress=,quantize=,blank=,var_dtypes=,units=, etc., use the type-specificwrite_image()/write_table()directly.- Parameters:
data (numpy.ndarray or dict) – Image: a plain ndarray. Table: a structured ndarray or a
{name: ndarray}dict.extname (str, optional) – EXTNAME to set on the new HDU.
header (FITSHeader or dict, optional) – Cards to copy into the new HDU after the write.
- Returns:
hdu – The newly created HDU, ready for further reads/writes while the FITS handle is open.
- Return type:
See also
write_imageImage-specific create+write with all knobs.
write_tableTable-specific create+write with all knobs.
- write_image(data, *, extname=None, extver=None, compress=None, quantize=None, blank=None, header=None)¶
Create an image HDU from
dataand write the pixels.One-call convenience that combines
create_image_hdu()andImageHDU.write(). The HDU’s dtype and shape are taken fromdata; everything else is forwarded tocreate_image_hdu().- Parameters:
data (array_like) – The pixel data to write. Anything
numpy.asanyarrayaccepts: an ndarray, a MaskedArray (mask is preserved through the write — seeImageHDU.write), or a nested Python sequence. Must have a supported numpy dtype (u1/i1/i2/u2/i4/u4/i8/u8/f4/f8).extname – Forwarded to
create_image_hdu(); see that method for the full kwarg semantics.extver – Forwarded to
create_image_hdu(); see that method for the full kwarg semantics.compress – Forwarded to
create_image_hdu(); see that method for the full kwarg semantics.quantize – Forwarded to
create_image_hdu(); see that method for the full kwarg semantics.blank – Forwarded to
create_image_hdu(); see that method for the full kwarg semantics.header (FITSHeader or dict, optional) – Cards to copy into the new HDU after the write. Routed through
FITSHeader.update(), which silently skips protected/structural cards when copying from another FITSHeader and raises on protected cards in a dict.
- Returns:
hdu – The newly created HDU, ready for further reads/writes while the FITS handle is open.
- Return type:
See also
create_image_hduSchema-only create (no data write).
write_tableThe table-side counterpart.
- write_table(data, *, names=None, extname=None, extver=None, units=None, var_dtypes=None, bit_columns=None, heap_format=None, compress=None, ztilelen=None, header=None)¶
Create a BINTABLE HDU from
dataand write the rows.One-call convenience that combines
create_table_hdu()andTableHDU.write(). The table schema (dtype + nrows) is derived fromdata; everything else is forwarded tocreate_table_hdu().If the file has no HDUs yet, an empty primary image is written first (the FITS standard forbids BINTABLE as the primary HDU).
- Parameters:
data (structured ndarray, dict, or list/tuple of arrays) –
The rows to write. Three accepted shapes:
structured ndarray — dtype is taken from
data.dtype, nrows fromlen(data).dict
{name: array}— dtype is composed field-by-field from each column’s ndarray dtype; all arrays must have the same length.list / tuple of arrays + names= — same as dict, with names supplied as a separate argument.
names (sequence of str, optional) – Column names for the list/tuple input form. Required when
datais a list or tuple; rejected for the other two forms (the names are already implied).extname – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.extver – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.units – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.var_dtypes – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.bit_columns – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.heap_format – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.compress – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.ztilelen – Forwarded to
create_table_hdu(); see that method for the full kwarg semantics.header (FITSHeader or dict, optional) – Cards to copy into the new HDU after the write. Same semantics as
write_image’sheader=.
- Returns:
hdu – The newly created HDU, ready for further reads/writes while the FITS handle is open.
- Return type:
See also
create_table_hduSchema-only create (no data write).
write_imageThe image-side counterpart.