astropy / ccdproc

Astropy affiliated package for reducing optical/IR CCD data
https://ccdproc.readthedocs.io
BSD 3-Clause "New" or "Revised" License
89 stars 86 forks source link

ImagerFileCollection.ccds() extension override #817

Open AnthonyHorton opened 6 months ago

AnthonyHorton commented 6 months ago

When using ImageFileCollection.ccds() to generate CCDData objects from the files in an ImageFileCollection it is not possible to change which FITS extension the CCDData objects will be generated for. It is only possible to generate CCDData objects for the extension that was selected when the ImageFileCollection was created. This is a problem when working with some multi-extension FITS files, such as those from some ESO instruments.

Here's the hdulist.info() from an example FITS file from the ESPRESSO instrument:

Filename: ESPRESSO/bias_20231203/ESPRE.2023-12-03T12:49:30.096.fits.bz2
No.    Name      Ver    Type      Cards   Dimensions   Format
  0  PRIMARY       1 PrimaryHDU    1440   (0, 0)      
  1  CCD290blue    1 ImageHDU       720   (9920, 9296)   int16 (rescales to uint16)   
  2  CCD290red     1 ImageHDU       720   (9920, 9296)   int16 (rescales to uint16)  

The primary only contains a header, no data, and there are two image data extensions corresponding to the blue and red arms of the spectograph. The primary header contains most of the information you would want to use for selecting/filtering files (e.g. image type, target object, etc.) so you need to create the ImageFileCollection with ext=0, but having selected the FITS files that you want to process you can't tell ImageFileCollection.ccds() to use the data extensions instead. ImageFileCollection.ccds() doesn't have an ext argument, and if you try to specify it using the ccd_kwargs argument instead you get a TypeError due to multiple keyword values.

Example:

 # Use keyword in primary header to select bias frames
ifc = ccdproc.ImageFileCollection(data_path, keywords="*", ext=0)
bias_ifc = ifc.filter(**{'eso dpr type':'bias'})  

# Now try to get CCDDatas for blue channel data in extension 1 for combining.
# This raises TypeError:
blue_combiner = ccdproc.Combiner(bias_ifc_dec.ccds(ext='CCD290blue'))
# This raises TypeError too: 
blue_combiner = ccdproc.Combiner(bias_ifc_dec.ccds(ccd_kwargs={'hdu':'CCD290blue'}))

Of course it's possible to work around this by writing your own CCDData generator and feeding the ImageFileCollection.files into it, but it would be more convenient if ImageFileCollection.ccds() had an optional ext argument that allowed you to override the value that gets passes to the astropy.nddata.ccddata.fits_ccddata_reader() hdu parameter.

AnthonyHorton commented 6 months ago

FWIW I'm quite likely to have a go at implementing this myself, if the change is likely to be accepted.

mwcraig commented 6 months ago

@AnthonyHorton -- this sounds like an excellent addition. I'd be happy to promptly review/merge/release!