Skip to content

Add support for rustfits fits backend.#177

Open
erykoff wants to merge 16 commits into
mainfrom
rustfits
Open

Add support for rustfits fits backend.#177
erykoff wants to merge 16 commits into
mainfrom
rustfits

Conversation

@erykoff

@erykoff erykoff commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

try:
cov_index_map = fits.read_ext_data('COV')
except (OSError, KeyError):
except (OSError, KeyError, ValueError):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the situation here? It is a fits file but doesn't have the 'COV' extension?

Comment thread healsparse/fits_shim.py Outdated
hdu = self.fits_object[extension]
if use_fitsio:
if use_rustfits:
return isinstance(hdu, (rustfits.CompressedImageHDU, rustfits.ImageHDU))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just check rustfits.ImageHDU

Comment thread healsparse/fits_shim.py
return {}
else:
hdr = copy.copy(metadata)
for reserved in FITS_RESERVED:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustfits will ignore protected fits header keys when you write to a header from an existing FITSHeader using the update method, but not when writing from a dict, so it is correct to skip protected keys.

rustfits provides rustfits.is_protected_key(name) for the above, which could replace your check against FITS_RESERVED.

Note, if this metadata was itself created from a rustfits FITSHeader, you can do header.to_dict(skip_protected=True) to provide the clean dict.

It probably makes sense to provide a method to clean a dict of protected keys so you don't need the loop.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the way that the tests do reading/writing, and there's no way to directly create a rustfits header in python, sometimes this code gets a rustfits header and sometimes a dict. But I will make use of the is_protected_key().

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I don't want to loop over all keys ... just the protected ones. I just don't know how to do this without a bunch more special cases.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to change what you are doing, I was just giving information, sorry to imply otherwise

Here is what rustfits does

https://github.com/esheldon/rustfits/blob/5c959d88ceaebefa3fd29cf4ee144adcd22e0757/src/header.rs#L440

Comment thread healsparse/io_map.py
except (OSError, UnicodeDecodeError, ValueError):
pass
# UnicodeDecodeError occurs when trying to read an hdf5 file as if it's FITS
# ValueError occurs from rustfits when trying to read an hdf5 file as if it's FITS

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What actual error is raised? I'm guessing it is ValueError because it tries to parse the primary header and finds the wrong values in the first bytes, but I want to see if a different error might be more appropriate to raise.

@erykoff erykoff Jul 3, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the following code snippet raises ValueError because it can't access extension 0. If the file nothing.notfits is not there then it raises an OSError (as expected). If the file isn't a fits (e.g. touch nothing.notfits) then rustfits will happily "open" the file but won't raise (ValueError) until it tries to access an extension. Should it be checking that it's a valid fits file on open?

with rustfits.FITS("nothing.notfits") as f:
    print(f[0])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rustfits.FITS should do eager header parsing on open. It is true that fitsio was lazy

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But it doesn’t parse the header on an empty file?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds like a bug, investigating

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fixed and will be in the next release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants