esheldon / fitsio

A python package for FITS input/output wrapping cfitsio
GNU General Public License v2.0
134 stars 58 forks source link

Error reading header by extension with duplicate EXTNAME headers #324

Open dstndstn opened 3 years ago

dstndstn commented 3 years ago

Hi Erin,

With fitsio 1.1.4 (and python 3.8.10), I'm trying to read an image header from the Canada-France-Hawaii Telescope's MegaPrime camera, and I'm getting weird behavior.

There are a couple of weird things with these images. First, each image HDU contains two EXTNAME cards, one

EXTNAME = 'COMPRESSED_IMAGE'   / name of this binary table extension

and one

EXTNAME = 'ccd00   '           / CCD number in the mosaic

And it also contains some header cards like

QID     = 55700500000000067457
QOBSEQID= 55301400000000293007
QICSEQID= 55351200000000325849
QOBITER =                    1
QOFFID  = 10000000000000000001

The weird thing is that I can create a FITS object and read its headers by index, but fitsio.read_header fails!

This works:

$ python -c "import fitsio; F = fitsio.FITS('/data/cfis-ls/images/cfis/pitcairn/2423575p.fits.fz'); hdr = F['ccd00'].read_header(); print(hdr['EXTNAME'])"
COMPRESSED_IMAGE

but this fails:

$ python -c "import fitsio; fitsio.read_header('/data/cfis-ls/images/cfis/pitcairn/2423575p.fits.fz', ext='ccd00')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/dist-packages/fitsio/fitslib.py", line 209, in read_header
    hdunum = _fits.movnam_hdu(ANY_HDU, extname, extver_num)
OSError: FITSIO status = 301: illegal HDU number

and (oddly?) if I run those in sequence, I get more log messages:

$ python -c "import fitsio; F = fitsio.FITS('/data/cfis-ls/images/cfis/pitcairn/2423575p.fits.fz'); hdr = F['ccd00'].read_header(); print(hdr['EXTNAME']); fitsio.read_header('/data/cfis-ls/images/cfis/pitcairn/2423575p.fits.fz', ext='ccd00')"
COMPRESSED_IMAGE
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.8/dist-packages/fitsio/fitslib.py", line 209, in read_header
    hdunum = _fits.movnam_hdu(ANY_HDU, extname, extver_num)
OSError: FITSIO status = 301: illegal HDU number
Range Error in ffc2jj converting string to longlong int: 55700500000000067457
Error in ffc2j evaluating string as a long integer: 55700500000000067457
Range Error in ffc2jj converting string to longlong int: 55301400000000293007
Error in ffc2j evaluating string as a long integer: 55301400000000293007
Range Error in ffc2jj converting string to longlong int: 55351200000000325849
Error in ffc2j evaluating string as a long integer: 55351200000000325849
Range Error in ffc2jj converting string to longlong int: 10000000000000000001
Error in ffc2j evaluating string as a long integer: 10000000000000000001
Error in ffc2dd converting string to double: Pan-STARRS
Error in ffc2j evaluating string as a long integer: 'Pan-STARRS'

Now, if I edit the header and change the first EXTNAME card to XXTNAME, then it works correctly!

I'm honestly not sure if this is something that fitsio should reasonably be expected to deal with, so feel free to close. For what it's worth, astropy seems to choke on it as well (even the fixed version).

demitri commented 3 years ago

I haven't looked at the internals lately, but I think the Astropy implementation of the FITS header object is a subclass of dict (or similar), which is incorrect. It's perfectly valid, as you see, for FITS headers to have duplicate keywords, unlike dictionaries. It may be something related to this?