Reading FITS files¶
- fitsy.open(path, mode='readonly', lenient=True)¶
Open a FITS file by path.
- Parameters:
path (str or os.PathLike) – Filesystem path to the FITS file.
mode ({'readonly', 'denywrite', 'update'}, optional) –
'readonly'(default) opens read-only. Every mutation – a header edit, a pixel edit,FitsFile.append(),del file[i], andFitsFile.writeto()back onto the same path – raisesValueError.FitsFile.writeto()to a different path still works, and copies the file unchanged.'denywrite'behaves exactly like'readonly'. fitsy does not take an OS-level write lock for this mode.'update'opens read/write. Header edits and image-pixel in-place edits (hdu.data[...] = x) are preserved on the nextFitsFile.flush(),FitsFile.close(), or a clean__exit__. Table column data is read-only in this release; reconstruct the table withfitsy.bintable()to change column values.'append'and'ostream'are recognized but not implemented; usefitsy.write()for output-only work.lenient (bool, optional) –
Tolerate common non-conforming headers so real-world files load. Default True. Pass
lenient=Falseto require strict FITS conformance.Stray bytes in free-text comments are always sanitized to spaces, even when
lenient=False.Leniency also accepts non-conforming values:
SIMPLE = Fprimary headers;non-ASCII bytes in string values, sanitized to spaces;
lower-case or otherwise malformed keywords;
values matching no standard type, kept verbatim as a string so the rest of the file still loads;
stray bytes after
END, a lower-caseend, and brokenCONTINUEchains.
A present
END, block alignment and the declared data size are enforced in every mode.
- Returns:
FitsFile – A read-only or read/write handle depending on
mode.- Raises:
ValueError – If
modeis not one of the recognized values.FitsError – On parse failures or I/O errors.
Examples
>>> import fitsy >>> with fitsy.open("image.fits") as f: ... img = f[0] ... print(img.axes)
- class fitsy.FitsFile¶
Bases:
objectOwning, ordered, mutable list of HDUs.
Each slot is a typed object –
ImageHdu,BinTable,AsciiTable, orRandomGroups– owning its own header and data, and it outlives the file handle.In
mode='readonly'(the default), every mutation raisesValueError: a header edit,hdu.data[...] = x,f.append(hdu),del f[i], andwriteto()back onto the source path.writeto()to a different path still works and copies the file unchanged.In
mode='update', the same edits are held in memory and reach the source file on the nextflush(),close(), or a clean__exit__. A pixel patch throughf[i].section[a:b] = arris written immediately instead, and does not wait forflush().Build a new, in-memory file with the
FitsFile()constructor (no path), thenappend()each HDU and callwriteto()to create a file from nothing.Use the
open()factory to load an existing file rather than constructing this class directly.Notes
A
RandomGroupsHDU writes back the header and the data section it was read with. The bindings expose no way to edit either, so a write reproduces the source HDU byte for byte.Examples
>>> with fitsy.open("image.fits", mode="update") as f: ... f[0].data[0, 0] = 42.0 ... # changes flushed automatically on __exit__ >>> with fitsy.open("image.fits") as f: # readonly ... f.writeto("copy.fits") # unmodified copy
- __enter__()¶
Context-manager entry.
- Returns:
FitsFile –
self.
- __exit__(exc_type=None, _exc_val=None, _exc_tb=None)¶
Context-manager exit.
On a clean exit – no exception in flight – calls
flush()and lets any error it raises propagate.On exit due to an in-flight exception, makes any already applied in-place pixel patch durable, but does not rewrite the file for a pending header or full-array edit; any error from that best-effort step is discarded.
- Returns:
bool – Always
False. An in-flight exception is never suppressed.
- __getitem__(key, /)¶
Return self[key].
- __len__()¶
Return len(self).
- add_checksums()¶
Enable
CHECKSUM/DATASUMstamping on every HDU thatwriteto()emits, and on every HDU thatflush()rewrites.When enabled, every HDU written gains freshly computed
CHECKSUMandDATASUMcards (per the FITS Checksum Proposal). An existing placeholder card in the header is overwritten in place; a missing one is inserted. The flag stays on for the lifetime of theFitsFileobject; there is no way to turn it back off or to stamp only one HDU.Notes
This does not stamp anything immediately. fitsy computes each value during a write, when the final byte layout of the HDU is known. Both
writeto()andflush()then stamp every HDU. This call marks the file as needing a rewrite, so aflush()with no other pending edit still writes the cards. To check the result, callverify_checksums()on the written file.
- append(value)¶
Append an HDU at the end.
- Parameters:
value (ImageHdu or BinTable or AsciiTable) – The new HDU. This also accepts a builder, meaning an
fitsy.ImageBuilder, afitsy.BinTableBuilderor anfitsy.AsciiTableBuilder, as returned byfitsy.image(),fitsy.bintable()orfitsy.ascii_table(). A builder is promoted to a live, independently editable HDU instance.- Raises:
ValueError – If the file was opened read-only.
TypeError – If value is not an HDU instance or a builder.
Notes
Marks the file dirty, and invalidates every cached in-place pixel-patch binding, before value is checked. A call that raises TypeError still forces the next write to be a full rewrite.
- close()¶
Flush pending edits (if any) and release the source file handle.
After
close(), the slot list and any HDU wrapper Python already holds remain usable as in-memory data, but the underlying file handle is dropped: reading a still-Pendingslot then raisesValueError.writeto()always visits every slot, so it raises the same way if any slot is stillPending. A laterflush()call raises only if it decides a rewrite is needed and aPendingslot remains; with nothing left to write, it is a successful no-op.Idempotent: calling
close()more than once is safe.- Raises:
TypeError, ValueError, FitsError – Under the same conditions as
flush(), which this method calls first.
- flush()¶
Flush pending edits to disk.
A no-op when the file was opened
mode='readonly'ormode='denywrite'.In
mode='update', a mutation that an in-place pixel patch cannot satisfy – a header edit,hdu.data = new_array,append(),del file[i], a fancy or dtype-mismatchedsection[...]write, or an edit on a tile-compressed image – rewrites the whole file through a sibling temp file and an atomic rename. A slot the caller never touched is streamed byte-for-byte from the original file, with no decode or re-encode. Readinghdu.dataalone does not by itself force a rewrite: fitsy re-reads that HDU’s data section from disk and compares it against the cached array, and rewrites only if the two differ.Mixing modes: if you issue an in-place
section[...]patch and then a non-patch mutation in the same session, the patch reaches disk first, throughpwrite, and the subsequentflush()then performs a full rewrite that includes the patched bytes, by streaming the already-patched source file. The patch is not lost.Crash safety: an in-place patch uses
pwritewith no undo journal; a process death mid-patch can leave the file with some rows updated and others not. The full-rewrite path is crash-safe, because it writes to a sibling temp file and renames atomically once the bytes are durable. The parent directory is not separatelyfsynced, so a power loss between the rename and the next directory commit can, in theory, leave the rename invisible after reboot on a non-journaling filesystem. A stale.fitsy-tmp.*sibling left by a crashed rewrite is harmless and may be deleted.- Raises:
TypeError – If a rewrite is needed and an HDU slot holds an object that is none of the four wrapper classes; see
writeto().ValueError – If a rewrite is needed and would leave zero HDUs, or if an internal lock was poisoned by an earlier panic.
FitsError – On an I/O failure, or if an HDU cannot be encoded for write.
- hdu(i)¶
Return the
i-th HDU. Equivalent tofile[i]for non-negative integeri.- Parameters:
i (int) – HDU index. Unlike
file[i], does not accept a negative index.- Returns:
ImageHdu or BinTable or AsciiTable or RandomGroups – The matching HDU.
- Raises:
IndexError – If i is at least
len(file).OverflowError – If i is negative.
- hdu_by_name(name, ver=None)¶
Return the first HDU with matching
EXTNAME.- Parameters:
- Returns:
ImageHdu or BinTable or AsciiTable or RandomGroups – The matching HDU.
- Raises:
KeyError – If no HDU matches name (and ver, when given).
Notes
Materializes each HDU, in order, until a match is found or the list is exhausted.
- insert(i, value)¶
Insert an HDU at position
i.- Parameters:
i (int) – Target position. A negative index counts from the end. Clamped into
[0, len(file)], so an out-of-range value inserts at the nearer end instead of raising.value (ImageHdu or BinTable or AsciiTable) – The new HDU. This also accepts a builder, meaning an
fitsy.ImageBuilder, afitsy.BinTableBuilderor anfitsy.AsciiTableBuilder, as returned byfitsy.image(),fitsy.bintable()orfitsy.ascii_table(). A builder is promoted to a live, independently editable HDU instance.
- Raises:
ValueError – If the file was opened read-only.
TypeError – If value is not an HDU instance or a builder.
Notes
Marks the file dirty, and invalidates every cached in-place pixel-patch binding, before value is checked. A call that raises TypeError still forces the next write to be a full rewrite.
- read_only¶
True when the file was opened read-only.
- verify_checksums()¶
Verify per-HDU
CHECKSUMandDATASUMcards.Streams the data section of each HDU directly from disk in fixed-size chunks (no full materialization) and compares against the values stored in the HDU header. HDUs that have neither card are reported with both fields
None; HDUs that only have one of the two are reported with the missing fieldNoneand the present one asTrue/False.- Returns:
list[dict] – One dict per HDU, in file order. Keys:
hdu– 0-based HDU index (int).checksum_ok–True/False/None.datasum_ok–True/False/None.
- Raises:
ValueError – If the file has no backing path – built with the
FitsFile()constructor rather thanfitsy.open()– or ifclose()was already called.FitsError – On an I/O failure, or if a header fails to parse.
Notes
Reads the header and data bytes currently on disk, in both
mode='readonly'andmode='update'. An in-memory edit that has not yet reached the file throughflush(),close(), or a clean__exit__is not reflected.
- wcs(i=0, alt=' ')¶
Resolve the WCS for the given HDU index.
- Parameters:
- Returns:
Wcs or None –
Noneif HDU i’s header carries no WCS for alt.- Raises:
IndexError – If i is at least
len(file).OverflowError – If i is negative.
ValueError – If alt is not exactly one character.
FitsError – If alt is not
' 'or one of'A'-'Z', if the header carries a malformed WCS, or if a-TABaxis cannot be resolved (see Notes).
Notes
A
-TABaxis (Paper III Sec.6) stores its coordinate array in a sibling BINTABLE. ThePSi_0/PVi_1cards name that table. This method loads the table from the file this handle was opened from. A handle built in memory (theFitsFile()constructor) has no file to search. A-TABaxis then raises here, not later at transform time. Usefitsy.Wcs(f[i].header)to inspect such a header without the lookup table.
- writeto(path, overwrite=False)¶
Write the file (with all in-memory edits) to
path.Each HDU is re-emitted from its current Python state:
ImageHdu– pixel data is encoded from the live numpy array (sohdu.data[...] = xround-trips);BITPIXandNAXIS*are recomputed from the array.BinTable,AsciiTable– data bytes are re-emitted as captured at load time (column edits do not round-trip in this release).RandomGroups– header and data section are re-emitted as captured at load time.
An HDU slot that is still
Pending(never accessed) streams through unchanged, whatever its kind.If the first HDU is not an image, an empty primary image HDU (
NAXIS = 0) is automatically prepended so the output is a valid FITS file.The on-disk source file (if any) is never modified, except when
pathresolves to the same file the handle was opened from – a self-write requires update mode and triggers an in-place rewrite (alias forflush()).- Parameters:
path (str or os.PathLike) – Destination path.
overwrite (bool, optional) – If False (default), raise
FileExistsErrorwhenpathalready exists. Set to True to replace it.
- Raises:
ValueError – If the file contains zero HDUs, or if
pathresolves to the source file and the handle is read-only.FileExistsError – If
pathexists andoverwriteis False.TypeError – If an HDU slot holds an object that is none of
ImageHdu,BinTable,AsciiTableorRandomGroups.FitsError – On I/O failure.
- class fitsy.ImageHdu(data, header=None, name=None)¶
Bases:
objectImage HDU with lazy numpy data.
Returned by
FitsFile.hdu()(orfile[i]) for an image HDU. Pixels are read on the first access tohdu.data, not before, except for a tile-compressed image, which is decoded in full as soon as the HDU is materialized. Later accesses return the same array, and in-place edits likehdu.data[0, 0] = 42are kept on the nextFitsFile.writeto().For images larger than RAM, use
section:hdu.section[a:b]reads only those bytes andhdu.section[a:b] = arrwrites only those, never materializing the whole array. A tile-compressed image gains nothing fromsection, since its array is already resident by the timehdu.sectioncan be used.Examples
>>> with fitsy.open("image.fits") as f: ... img = f[0] ... print(img.bitpix, img.axes, img.data.shape)
- axes¶
[NAXIS1, NAXIS2, ...].When the pixel data has been materialized, the axes are reported from the live numpy array shape (reversed, since numpy is row-major while FITS lists fastest-varying first). Otherwise the axes recorded at HDU-open time are returned – this is the lazy path that does not trigger a data read.
- Type:
Image axes in NAXIS order
- bitpix¶
FITS
BITPIXvalue (e.g.-32forf32).
- data¶
Pixel data as a numpy array.
Materializes the array on first access by reading the data section from disk, byteswapping into native order, and applying
BSCALE/BZERO/BLANKscaling. Subsequent accesses return the same array, and in-place mutation (hdu.data[...] = x) is preserved by the nextFitsFile.writeto(), and, inmode='update', byFitsFile.flush().For images that do not fit in RAM, prefer
section–hdu.section[a:b]reads only the requested bytes without materializing the full array.- Returns:
numpy.ndarray or None –
Nonewhen the HDU has no data section (NAXIS == 0). Otherwise, the dtype depends onBZERO,BSCALEandBLANK, not onBITPIXalone:If
BZEROis 0,BSCALEis 1 andBLANKis absent, the raw pixels are returned. The dtype followsBITPIX.If
BSCALEis 1 andBZEROis the standard integer offset, the matching unsigned dtype is returned.BITPIX8 withBZERO-128 returnsint8.For all other scaling,
BSCALE,BZEROandBLANKare applied, and the result is floats. A pixel whose stored value matchesBLANK– or that was alreadynanin a floating-point image – becomesnan.BITPIX8, 16 and -32 givefloat32. All other values givefloat64.
An array obtained from a read-only
FitsFilehas itsWRITEABLEflag cleared; assigning into it raisesValueError.- Raises:
FitsError – If the pixel bytes cannot be read from the source file.
Notes
A tile-compressed image is decoded in full when the HDU is materialized, not on this first
.dataaccess; by the time Python code can reachhdu.data, the array already exists.Reading
.datainmode='update'does not, by itself, force the file to be rewritten. The nextFitsFile.flush()compares this array’s bytes against the file and rewrites only if they differ.
- data_matches_source()¶
Whether the cached pixel array still matches the bytes on disk.
Returns false when that cannot be established (no read source), so the caller falls back to rewriting.
A scaled HDU is compared in physical units, because that is what the cache holds. Comparing it against the stored integers would never match, and merely reading data would then rewrite the file in a different BITPIX.
- section¶
Slicing accessor that mirrors
numpy.ndarrayindexing.hdu.section[a:b, c:d]reads only the requested region from disk – no full-image materialization.In
mode='update',hdu.section[a:b] = arrwrites only the touched bytes back via positionalpwrite, again without materializing the full image. This is the supported way to read or patch sub-regions of an image bigger than available RAM.In-place writes require contiguous slicing (
start:stopwith step 1). Fancy indexing and negative steps raise aValueError– assign throughhdu.data[...]to trigger a full-file rewrite instead.A scaled HDU (
BSCALE,BZEROorBLANK) is written in the same physical unitsdatareports. fitsy inverts the scaling and leaves the storedBITPIXalone.If
hdu.datahas already been accessed (and is therefore resident in memory), reads and writes go through the in-memory array for consistency with subsequenthdu.dataaccesses.- Returns:
_ImageSection – Slicing proxy. Use
section[i, j, k]exactly likedata[i, j, k].
- wcs(alt=' ')¶
Resolve the WCS for this HDU.
- Parameters:
alt (str, optional) – Single ASCII character.
' '(default) selects the primary description;'A'through'Z'select alternate descriptions.- Returns:
Wcs or None –
Noneif the header carries no WCS foralt.- Raises:
FitsError – If alt is not
' 'or one of'A'-'Z', if the header carries a malformed WCS, or if a-TABaxis cannot be resolved (see Notes).
Notes
A
-TABaxis (Paper III Sec.6) stores its coordinate array in a sibling BINTABLE. ThePSi_0/PVi_1cards name that table. An HDU fromfitsy.open()keeps a handle to its file. This method resolves the lookup through that handle, exactly asfitsy.FitsFile.wcs()does. An HDU built in memory has no file to search. A-TABaxis then raises here, not later at transform time. Usefitsy.Wcs(hdu.header)to inspect such a header without the lookup table.
- class fitsy.BinTable¶
Bases:
objectBinary table HDU (
BINTABLE).Returned by
FitsFile.hdu()(orfile[i]) when the HDU kind isBINTABLE. Columns are decoded eagerly. A column with a repeat count of 1 and a plain integer or realTFORMcode returns a 1-Dnumpy.ndarray; every other column – logical, string, a repeat count above 1, or a bit, complex or variable-length code – returns a Pythonlist, one entry per row. Seecolumn()for the full mapping fromTFORMcode to Python type.Examples
>>> with fitsy.open("catalog.fits") as f: ... tbl = f[1] ... ra = tbl["RA"] # numpy array ... name = tbl["NAME"] # list[str]
- __getitem__(key, /)¶
Return self[key].
- column(name)¶
Column accessor; equivalent to
table[name].- Parameters:
name (str) – Column name (
TTYPEn), case-sensitive.- Returns:
numpy.ndarray, numpy.ma.MaskedArray, or list – The decoded column, keyed by
TFORMcode (Standard Table 18):B,I,J,K, repeat 1, with noTSCALn/TZEROn, orBunder the FITS signed-byte convention (TSCALn = 1,TZEROn = -128):numpy.ndarrayofint64, ornumpy.ma.MaskedArrayofint64if a cell’s stored value matchesTNULLn.EorD, repeat 1:numpy.ndarrayoffloat64.Eis widened from its 32-bit storage.TNULLnhas no effect on these two codes.B,I,J,K, repeat 1, with any otherTSCALn/TZEROn:numpy.ndarrayoffloat64, scaled asTZEROn + TSCALn * stored. A cell whose stored value matchesTNULLnbecomesnan.A, repeat 1, noTDIMn:listofstr, right-trimmed of trailing spaces and NUL bytes.L, repeat 1:listofboolorNone(Nonemarks an undefined logical, stored as a NUL byte).Every other case – a repeat count above 1 (a fixed-size vector cell, or
AwithTDIMn),X,C,M,P/Q, orI/J/Kunder the FITS unsigned-integer convention (TSCALn = 1,TZEROn = 2**(8n-1)): alist, one entry per row:A numeric vector cell is a numpy array, reshaped to
TDIMnin C order (fastest-varying last, the reverse of theTDIMnorder) when present.An
Xcell is aboolnumpy array, unpacked most-significant bit first.A
C/Mcell is alistof(re, im)float tuples, one per repeat element. fitsy does not build a Pythoncomplexvalue.A
P/Qcell is a numpy array decoded from the heap, in the descriptor’s inner type, with that type’s own null and scaling rule.An
Acell withTDIMnis a numpy array ofstr.
- Raises:
KeyError – If name names no column.
Notes
fitsy decides a column’s representation from its first row. If a later row disagrees, the whole column falls back to the per-row
listform. An empty table (n_rowsis 0) always returns an emptylistfor every column.The returned array, when one is returned, is read-only. fitsy freezes only that outer array. A numpy array held inside a returned
liststays writable, but fitsy rebuilds the column on every call, so such an edit reaches neither the file nor the next call.
- column_names¶
List of column names in declaration order.
- data¶
Pre-decoded columns assembled into one numpy structured array, one record per row.
- Returns:
numpy.recarray – Every column, in declaration order. A column
column()returns as a numpy array keeps that array’s dtype here. A columncolumn()returns as alistis encoded asobjectdtype instead, one row’s list entry per cell. The array is read-only.- Raises:
Exception – The numpy exception, unchanged, if a numpy call fails while fitsy assembles the array.
Notes
This array is rebuilt on every access. An edit never reaches the file, or even the next call to
data; the array is frozen read-only so an edit raises instead of silently vanishing.A masked
int64column, or anLcolumn holdingNone, loses that null marker here: the masked or undefined cell reads back as0orFalse.
- header¶
The HDU header.
- n_rows¶
Number of rows in the table.
- row(r)¶
Build a row dict for row index r.
- Parameters:
r (int) – Row index. Must satisfy
0 <= r < n_rows. Unliketable[r], this method does not accept a negative index.- Returns:
dict – One entry per column, keyed by column name, holding that row’s value in the same form
column()would give for the whole column.- Raises:
IndexError – If r is outside
-n_rowston_rows - 1.
Notes
A negative r counts back from the last row, as
table[r]does.table[r]and this method accept the same indices.
- class fitsy.AsciiTable¶
Bases:
objectASCII
TABLEHDU.Returned by
FitsFile.hdu()(orfile[i]) when the HDU kind isTABLE. A numeric column (TFORMcodeI,F,EorD) decodes to anumpy.ndarrayoffloat64, withnanfor a cell matchingTNULLn. A character column (A) decodes to alistofstr. Seecolumn()for the full decoding rule.- __getitem__(key, /)¶
Return self[key].
- column(name)¶
Column accessor; equivalent to
table[name].- Parameters:
name (str) – Column name (
TTYPEn), case-sensitive.- Returns:
numpy.ndarray or list of str –
I,F,EandD(Standard Table 15) all return a 1-Dnumpy.ndarrayoffloat64, scaled byTSCALn/TZEROnwhen either is set. A blank field parses as0before scaling, so it becomesTZEROnonce scaled. A field matchingTNULLnbecomesnan.Areturns alistofstr, one per row, padded to the field width; fitsy does not trim it.- Raises:
KeyError – If name names no column.
Notes
The returned array, when one is returned, is read-only.
- column_names¶
List of column names in declaration order.
- data¶
Every column assembled into one numpy structured array, one record per row.
- Returns:
numpy.recarray – Every column, in declaration order, with the same dtype
column()gives it. The array is read-only.
Notes
This array is rebuilt on every access. An edit never reaches the file, or even the next call to
data; the array is frozen read-only so an edit raises instead of silently vanishing.
- header¶
The HDU header.
- n_rows¶
Number of rows in the table.
- row(r)¶
Build a row dict for row index r.
- Parameters:
r (int) – Row index. Must satisfy
0 <= r < n_rows. Unliketable[r], this method does not accept a negative index.- Returns:
dict – One entry per column, keyed by column name, holding that row’s value in the same form
column()would give for the whole column.- Raises:
IndexError – If r is outside
-n_rowston_rows - 1.
Notes
A negative r counts back from the last row, as
table[r]does.table[r]and this method accept the same indices.
- class fitsy.RandomGroups¶
Bases:
objectRandom-groups primary HDU (legacy format; see Standard Sec.6).
Read-only Python view: groups are decoded on demand through
group(). Indexing the file to reach this HDU (for example,file[0]) materializes it in memory.This class exposes no way to edit the header or the groups.
FitsFile.writeto()andFitsFile.flush()write back the header and the data section the HDU was read with, so the written HDU matches the source byte for byte.- bitpix¶
BITPIX value.
- data_per_group¶
Number of data values per group (prod(NAXIS2..NAXISn)).
- group(i)¶
Decode one group as
(parameters, data)numpy arrays.- Parameters:
i (int) – Group index, 0-based. Does not accept a negative index.
- Returns:
tuple of numpy.ndarray –
(parameters, data). Both arrays share the HDU’sBITPIXdtype and are read-only.parametershas lengthn_params;datahas lengthdata_per_group. NeitherBSCALE/BZEROnorPSCALn/PZEROnis applied – both arrays hold the stored, unscaled values.- Raises:
IndexError – If i is not less than
n_groups.OverflowError – If i is negative.
- header¶
HDU header.
- n_groups¶
Number of groups (GCOUNT).
- n_params¶
Number of parameters per group (PCOUNT).
Convenience functions¶
- fitsy.getdata(path, ext=None, *, header=False)¶
Read one HDU’s data, and optionally its header, from path.
- Parameters:
path (str or os.PathLike) – File to read.
ext (int or str, optional) – HDU index or
EXTNAME. Default is HDU 0. When ext is omitted and HDU 0 carries no data, fitsy reads HDU 1 instead.header (bool, keyword-only, optional) – Default
False. WhenTrue, return(data, header)instead of onlydata.
- Returns:
numpy.ndarray or tuple – Pixel data for an image HDU. A read-only structured array, one record per row, for a binary or ASCII table HDU. When header is
True, returns(data, header)instead, paired with theHeaderof the HDU the data came from.- Raises:
FitsError – If path cannot be opened or parsed as FITS.
IndexError – If ext is an out-of-range integer. Also raised if the selected HDU has no data, and, when ext was omitted, HDU 1 has no data either.
KeyError – If ext is a string that names no HDU.
TypeError – If ext is neither an int, a str, nor omitted.
Notes
A random-groups primary HDU (
GROUPS = T) has neither a data array nor a dict form. Reading one with ext omitted raisesAttributeErrorinstead of the exceptions above.
- fitsy.getheader(path, ext=None)¶
Read one HDU’s header from path.
- Parameters:
path (str or os.PathLike) – File to read.
ext (int or str, optional) – HDU index or
EXTNAME. Default is HDU 0.
- Returns:
Header – Header of the selected HDU.
- Raises:
FitsError – If path cannot be opened or parsed as FITS.
IndexError – If ext is an out-of-range integer.
KeyError – If ext is a string that names no HDU.
TypeError – If ext is neither an int, a str, nor omitted.
- fitsy.getval(path, key, ext=None)¶
Read one header keyword from path.
- Parameters:
path (str or os.PathLike) – File to read.
key (str) – Header keyword to read.
ext (int or str, optional) – HDU index or
EXTNAME. Default is HDU 0.
- Returns:
bool, int, float, complex, str, or None – Value of the card. A
HeaderCommentaryobject for aCOMMENT,HISTORY, or blank keyword.- Raises:
FitsError – If path cannot be opened or parsed as FITS.
IndexError – If ext is an out-of-range integer.
KeyError – If ext is a string that names no HDU, or if key is absent from the selected header.
TypeError – If ext is neither an int, a str, nor omitted.
- fitsy.info(path)¶
Return a brief HDU summary table for path.
- Parameters:
path (str or os.PathLike) – File to read.
- Returns:
list of tuple – One
(index, name, ver, kind, dims_or_n_rows)tuple per HDU, in file order.index– 0-based HDU position (int).name–EXTNAME, or an empty string if absent (str).ver–EXTVER, or1if absent (int).kind– wrapper class name:"ImageHdu","BinTable","AsciiTable", or"RandomGroups"."Unknown"in the unexpected case where fitsy cannot read the HDU’s Python type name.dims_or_n_rows– axis lengths (listofint) for an image HDU, row count (int) for a table HDU, orNonefor a random-groups HDU.
- Raises:
FitsError – If path cannot be opened or parsed as FITS.
Comparing files¶
- fitsy.diff(a, b, *, rtol=0.0, atol=0.0, max_diffs=10, ignore_keywords=None)¶
Compare two FITS files and return the differences.
- Parameters:
a (str or os.PathLike) – Paths to the two files to compare.
b (str or os.PathLike) – Paths to the two files to compare.
rtol (float, optional) – Relative tolerance for floating-point comparisons. Default
0.0(exact equality).atol (float, optional) – Absolute tolerance for floating-point comparisons. Default
0.0.max_diffs (int, optional) – Maximum number of data differences recorded per HDU. Default 10. Counting continues past this limit. The true count appears in the text report. Header differences are never truncated.
ignore_keywords (sequence of str, optional) – Header keywords to ignore, case-insensitive. Default
["CHECKSUM", "DATASUM", "DATE"].
- Returns:
FitsDiff – The comparison result. Call
str(diff)to get the text report.FitsDiff.identicalis True when the files match.- Raises:
FitsError – If either file cannot be opened or parsed as FITS.
Notes
fitsy combines the two tolerances as
|a - b| <= atol + rtol * |b|. Both default to0.0, which requires exact equality. A relative tolerance alone cannot reconcile values that straddle zero. Two values that are both NaN compare equal at any tolerance.The tolerances apply to every floating-point value fitsy compares: header card values, image pixels, and table cells. fitsy compares image pixels in physical units, with
BZEROandBSCALEapplied andBLANKas NaN. It reports an image difference by pixel number and a table difference asCOLUMN[row].A random-groups HDU, or an HDU of an extension type fitsy does not recognize, has no decoded form. fitsy compares its raw bytes instead. That comparison does not use
rtoloratol.When the two HDUs at one index have different types, fitsy reports the type difference and compares neither the headers nor the data of that HDU.
- class fitsy.FitsDiff¶
Bases:
objectResult of comparing two FITS files. See
diff().- __bool__()¶
True if self else False
- __str__()¶
Return str(self).
- diff_hdu_count¶
Number of compared HDUs with a reported difference.
- diff_hdu_indices()¶
Return the index of every compared HDU with a difference.
- Returns:
list of int – Indices in ascending order. An index counts from the primary HDU, which is index
0.
- hdu_counts¶
HDU counts of the two files, as
(n_a, n_b). When the counts differ, only the shared prefix of HDUs is compared.
- identical¶
True when both files have the same number of HDUs and no compared HDU has a reported difference. Differences are judged with the tolerances and ignored keywords passed to
diff().
- report()¶
Render the differences as text.
- Returns:
str – A multi-line report. The report names each HDU with a difference, then lists the header differences and the data differences of that HDU.
str(diff)returns the same text.