esheldon / fitsio

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

AttributeError: 'FITSCard' object has no attribute '_convert_string' #250

Closed menanteau closed 5 years ago

menanteau commented 5 years ago

``

menanteau commented 5 years ago

When trying to read header from file as string I get AttributeError: 'FITSCard' object has no attribute '_convert_string'

Here is an example that reproduces the issue:


import fitsio

header_template = """
SIMPLE  =                    T /
BITPIX  =                    8 / bits per data value
NAXIS   =                    0 / number of axes
EXTEND  =                    T / Extensions are permitted
ORIGIN  = 'LSST DM Header Service'/ FITS file originator

         ---- Date, night and basic image information ----
DATE    =                      / Creation Date and Time of File
DATE-OBS=                      / Date of the observation (image acquisition)
DATE-BEG=                      / Time at the start of integration
DATE-END=                      / end date of the observation
MJD     =                      / Modified Julian Date that the file was written
MJD-OBS =                      / Modified Julian Date of observation
MJD-BEG =                      / Modified Julian Date derived from DATE-BEG
MJD-END =                      / Modified Julian Date derived from DATE-END
OBSID   =                      / ImageName from Camera StartIntergration
GROUPID =                      / imageSequenceName from StartIntergration
OBSTYPE =                      / BIAS, DARK, FLAT, OBJECT
BUNIT   = 'adu     '           / Brightness units for pixel array

         ---- Telescope info, location, observer ----
TELESCOP= 'LSST AuxTelescope'  / Telescope name
INSTRUME= 'LATISS'             / Instrument used to obtain these data
OBSERVER= 'LSST'               / Observer name(s)
OBS-LONG=           -70.749417 / [deg] Observatory east longitude
OBS-LAT =           -30.244639 / [deg] Observatory latitude
OBS-ELEV=               2663.0 / [m] Observatory elevation
OBSGEO-X=           1818938.94 / [m] X-axis Geocentric coordinate
OBSGEO-Y=          -5208470.95 / [m] Y-axis Geocentric coordinate
OBSGEO-Z=          -3195172.08 / [m] Z-axis Geocentric coordinate

        ---- Pointing info, etc. ----

DECTEL  =                      / Telescope DEC of observation
ROTPATEL=                      / Telescope Rotation
ROTCOORD= 'sky'                / Telescope Rotation Coordinates
RA      =                      / RA of Target
DEC     =                      / DEC of Target
ROTPA   =                      / Rotation angle relative to the sky (deg)
HASTART =                      / [HH:MM:SS] Telescope hour angle at start
ELSTART =                      / [deg] Telescope zenith distance at start
AZSTART =                      / [deg] Telescope azimuth angle at start
AMSTART =                      / Airmass at start
HAEND   =                      / [HH:MM:SS] Telescope hour angle at end
ELEND   =                      / [deg] Telescope zenith distance at end
AZEND   =                      / [deg] Telescope azimuth angle at end
AMEND   =                      / Airmass at end

        ---- Image-identifying used to build OBS-ID ----
TELCODE = 'AT'                 / The code for the telecope
CONTRLLR=                      / The controller (e.g. O for OCS, C for CCS)
DAYOBS  =                      / The observation day as defined by image name
SEQNUM  =                      / The sequence number from the image name
GROUPID =                      /

        ---- Information from Camera
CCD_MANU= 'ITL'                / CCD Manufacturer
CCD_TYPE= '3800C'              / CCD Model Number
CCD_SERN= '20304'              / Manufacturers? CCD Serial Number
LSST_NUM= 'ITL-3800C-098'      / LSST Assigned CCD Number
SEQCKSUM=                      / Checksum of Sequencer
SEQNAME =                      / SequenceName from Camera StartIntergration
REBNAME =                      / Name of the REB
CONTNUM =                      / CCD Controller (WREB) Serial Number
IMAGETAG=                      / DAQ Image id
TEMP_SET=                      / Temperature set point (deg C)
CCDTEMP =                      / Measured temperature (deg C)

        ---- Geometry from Camera ----
DETSIZE =                      / Size of sensor
OVERH   =                      / Over-scan pixels
OVERV   =                      / Vert-overscan pix
PREH    =                      / Pre-scan pixels

        ---- Filter/grating information ----
FILTER  =                      / Name of the filter
FILTPOS =                      / Filter position
GRATING =                      / Name of the second disperser
GRATPOS =                      / disperser position
LINSPOS =                      / Linear Stage

        ---- Exposure-related information ----
EXPTIME =                      / Exposure time in seconds
SHUTTIME=                      / Shutter exposure time in seconds
DARKTIME=                      / Dark time in seconds

        ---- Header information ----
FILENAME=                      / Original file name
HEADVER =                      / Version of header

        ---- Checksums ----
CHECKSUM=                      / checksum for the current HDU
DATASUM =                      / checksum of the data records

"""

# Make it FITSHDR object
# This is basically the fitsio.read_scamp_head() function
lines = header_template.splitlines()
hdr = fitsio.FITSHDR()
for l in lines:
    print(l)
    hdr.add_record(l)
timj commented 5 years ago

Minor comment but the docstring for add_record seems wrong:

fitsio.FITSHDR.add_record = add_record(self, record_in)
    Add a new record.  Strip quotes from around strings.

    This will over-write if the key already exists, except
    for COMMENT and HISTORY fields

    parameters
    -----------
    record:
        The record, either a dict or a header card string
        or a FITSRecord or FITSCard
    convert: bool, optional
        If True, convert strings.  E.g. '3' gets
        converted to 3 and "'hello'" gets converted
        to 'hello' and 'T'/'F' to True/False. Default
        is False.

convert is not an allowed argument (and the parameter name record != record_in).

esheldon commented 5 years ago

this seems related to your issue @timj #249 do you agree?

timj commented 5 years ago

The problem with the code above is that the first four lines are not allowed to be provided (presumably because they are added by the FITS writer). If I start adding header cards from ORIGIN onwards everything works (and the blank keyword items are handled fine).

timj commented 5 years ago

I will add that it's a very strange failure mode and it would be better if there was an explicit exception for "card not accepted" that could be caught.

esheldon commented 5 years ago

yes, it is a bug that it is trying to use _convert_string which was removed in a recent PR

esheldon commented 5 years ago

this is yet another casualty of the header processing optimizations we put in, sigh

esheldon commented 5 years ago

felipe, I've got a PR in to address this, can you try it out: #251