summaryrefslogtreecommitdiff
path: root/updatewcs/dgeo.py
diff options
context:
space:
mode:
Diffstat (limited to 'updatewcs/dgeo.py')
-rw-r--r--updatewcs/dgeo.py311
1 files changed, 0 insertions, 311 deletions
diff --git a/updatewcs/dgeo.py b/updatewcs/dgeo.py
deleted file mode 100644
index 44d495e..0000000
--- a/updatewcs/dgeo.py
+++ /dev/null
@@ -1,311 +0,0 @@
-from __future__ import division # confidence high
-
-import pyfits
-from pytools import fileutil
-import utils
-import numpy as np
-
-class DGEOCorr(object):
- """
- Defines a Lookup table prior distortion correction as per WCS paper IV.
- It uses a reference file defined by the NPOLFILE (suffix 'NPL') keyword
- in the primary header.
-
- Notes
- -----
- - Using extensions in the reference file create a WCSDVARR extensions
- and add them to the science file.
- - Add record-valued keywords to the science extension header to describe
- the lookup tables.
- - Add a keyword 'NPOLEXT' to the science extension header to store
- the name of the reference file used to create the WCSDVARR extensions.
-
- If WCSDVARR extensions exist and `NPOLFILE` is different from `NPOLEXT`,
- a subsequent update will overwrite the existing extensions.
- If WCSDVARR extensions were not found in the science file, they will be added.
-
- It is assumed that the NPL reference files were created to work with IDC tables
- but will be applied with SIP coefficients. A transformation is applied to correct
- for the fact that the lookup tables will be applied before the first order coefficients
- which are in the CD matrix when the SIP convention is used.
- """
-
- def updateWCS(cls, fobj):
- """
- Parameters
- ----------
- fobj: pyfits object
- Science file, for which a distortion correction in a NPOLFILE is available
-
- """
- assert isinstance(fobj, pyfits.HDUList)
- cls.applyNPOLCorr(fobj)
- nplfile = fobj[0].header['NPOLFILE']
-
- new_kw = {'NPOLEXT': nplfile}
- return new_kw
-
- updateWCS = classmethod(updateWCS)
-
- def applyNPOLCorr(cls, fobj):
- """
- For each science extension in a pyfits file object:
- - create a WCSDVARR extension
- - update science header
- - add/update DGEOEXT keyword
- """
- nplfile = fileutil.osfn(fobj[0].header['NPOLFILE'])
- # Map WCSDVARR EXTVER numbers to extension numbers
- wcsdvarr_ind = cls.getWCSIndex(fobj)
- for ext in fobj:
- try:
- extname = ext.header['EXTNAME'].lower()
- except KeyError:
- continue
- if extname == 'sci':
- extversion = ext.header['EXTVER']
- ccdchip = cls.get_ccdchip(fobj, extname='SCI', extver=extversion)
- binned = utils.getBinning(fobj, extversion)
- header = ext.header
- # get the data arrays from the reference file and transform them for use with SIP
- dx,dy = cls.getData(nplfile, ccdchip)
- idccoeffs = cls.getIDCCoeffs(header)
-
- if idccoeffs != None:
- dx, dy = cls.transformData(dx,dy, idccoeffs)
-
- # Determine EXTVER for the WCSDVARR extension from the NPL file (EXTNAME, EXTVER) kw.
- # This is used to populate DPj.EXTVER kw
- wcsdvarr_x_version = 2 * extversion -1
- wcsdvarr_y_version = 2 * extversion
-
- for ename in zip(['DX', 'DY'], [wcsdvarr_x_version,wcsdvarr_y_version],[dx, dy]):
- cls.addSciExtKw(header, wdvarr_ver=ename[1], npol_extname=ename[0])
- hdu = cls.createNpolHDU(header, npolfile=nplfile, \
- wdvarr_ver=ename[1], npl_extname=ename[0], data=ename[2],ccdchip=ccdchip, binned=binned)
- if wcsdvarr_ind:
- fobj[wcsdvarr_ind[ename[1]]] = hdu
- else:
- fobj.append(hdu)
-
-
- applyNPOLCorr = classmethod(applyNPOLCorr)
-
- def getWCSIndex(cls, fobj):
-
- """
- If fobj has WCSDVARR extensions:
- returns a mapping of their EXTVER kw to file object extension numbers
- if fobj does not have WCSDVARR extensions:
- an empty dictionary is returned
- """
- wcsd = {}
- for e in range(len(fobj)):
- try:
- ename = fobj[e].header['EXTNAME']
- except KeyError:
- continue
- if ename == 'WCSDVARR':
- wcsd[fobj[e].header['EXTVER']] = e
-
- return wcsd
-
- getWCSIndex = classmethod(getWCSIndex)
-
- def addSciExtKw(cls, hdr, wdvarr_ver=None, npol_extname=None):
- """
- Adds kw to sci extension to define WCSDVARR lookup table extensions
-
- """
- if npol_extname =='DX':
- j=1
- else:
- j=2
-
- cperror = 'CPERROR%s' %j
- cpdis = 'CPDIS%s' %j
- dpext = 'DP%s.' %j + 'EXTVER'
- dpnaxes = 'DP%s.' %j +'NAXES'
- dpaxis1 = 'DP%s.' %j+'AXIS.1'
- dpaxis2 = 'DP%s.' %j+'AXIS.2'
- keys = [cperror, cpdis, dpext, dpnaxes, dpaxis1, dpaxis2]
- values = {cperror: 0.0, cpdis: 'Lookup', dpext: wdvarr_ver, dpnaxes: 2,
- dpaxis1: 1, dpaxis2: 2}
-
- comments = {cperror: 'Maximum error of dgeo correction for axis %s' % j,
- cpdis: 'Prior distortion funcion type',
- dpext: 'Version number of WCSDVARR extension containing lookup distortion table',
- dpnaxes: 'Number of independent variables in distortion function',
- dpaxis1: 'Axis number of the jth independent variable in a distortion function',
- dpaxis2: 'Axis number of the jth independent variable in a distortion function'
- }
-
- for key in keys:
- hdr.update(key=key, value=values[key], comment=comments[key], before='HISTORY')
-
- addSciExtKw = classmethod(addSciExtKw)
-
- def getData(cls,nplfile, ccdchip):
- """
- Get the data arrays from the reference DGEO files
- Make sure 'CCDCHIP' in the dgeo file matches "CCDCHIP' in the science file.
- """
- npl = pyfits.open(nplfile)
- for ext in npl:
- nplextname = ext.header.get('EXTNAME',"")
- nplccdchip = ext.header.get('CCDCHIP',1)
- if nplextname == 'DX' and nplccdchip == ccdchip:
- xdata = ext.data.copy()
- continue
- elif nplextname == 'DY' and nplccdchip == ccdchip:
- ydata = ext.data.copy()
- continue
- else:
- continue
- npl.close()
- return xdata, ydata
- getData = classmethod(getData)
-
- def transformData(cls, dx, dy, coeffs):
- """
- Transform the DGEO data arrays for use with SIP
- """
- ndx, ndy = np.dot(coeffs, [dx.ravel(), dy.ravel()])
- ndx.shape = dx.shape
- ndy.shape=dy.shape
- return ndx, ndy
-
- transformData = classmethod(transformData)
-
- def getIDCCoeffs(cls, header):
- """
- Return a matrix of the scaled first order IDC coefficients.
- """
- try:
- ocx10 = header['OCX10']
- ocx11 = header['OCX11']
- ocy10 = header['OCY10']
- ocy11 = header['OCY11']
- coeffs = np.array([[ocx11, ocx10], [ocy11,ocy10]], dtype=np.float32)
- except KeyError:
- print 'First order IDCTAB coefficients are not available.\n'
- print 'Cannot convert SIP to IDC coefficients.\n'
- return None
- try:
- idcscale = header['IDCSCALE']
- except KeyError:
- idcscale = 1
-
- return np.linalg.inv(coeffs/idcscale)
-
- getIDCCoeffs = classmethod(getIDCCoeffs)
-
- def createNpolHDU(cls, sciheader, npolfile=None, wdvarr_ver=1, npl_extname=None,data = None, ccdchip=1, binned=1):
- """
- Creates an HDU to be added to the file object.
- """
- hdr = cls.createNpolHdr(sciheader, npolfile=npolfile, wdvarr_ver=wdvarr_ver, npl_extname=npl_extname, ccdchip=ccdchip, binned=binned)
- hdu=pyfits.ImageHDU(header=hdr, data=data)
- return hdu
-
- createNpolHDU = classmethod(createNpolHDU)
-
- def createNpolHdr(cls, sciheader, npolfile, wdvarr_ver, npl_extname, ccdchip, binned):
- """
- Creates a header for the WCSDVARR extension based on the DGEO reference file
- and sci extension header. The goal is to always work in image coordinates
- (also for subarrays and binned images. The WCS for the WCSDVARR extension
- i ssuch that a full size dgeo table is created and then shifted or scaled
- if the science image is a subarray or binned image.
- """
- npl = pyfits.open(npolfile)
- for ext in npl:
- #for i in range(len(dgf)):
- try:
- nplextname = ext.header['EXTNAME']
- nplextver = ext.header['EXTVER']
- except KeyError:
- continue
- #dgccdchip = ext.header.get('CCDCHIP', 0)
- nplccdchip = cls.get_ccdchip(npl, extname=nplextname, extver=nplextver)
- if nplextname == npl_extname and nplccdchip == ccdchip:
- npol_header = ext.header
- break
- else:
- continue
- npl.close()
-
- naxis = pyfits.getval(npolfile, ext=1, key='NAXIS')
- ccdchip = nplextname #dgeo_header['CCDCHIP']
-
- kw = { 'NAXIS': 'Size of the axis',
- 'CDELT': 'Coordinate increment along axis',
- 'CRPIX': 'Coordinate system reference pixel',
- 'CRVAL': 'Coordinate system value at reference pixel',
- }
-
- kw_comm1 = {}
- kw_val1 = {}
- for key in kw.keys():
- for i in range(1, naxis+1):
- si = str(i)
- kw_comm1[key+si] = kw[key]
-
- for i in range(1, naxis+1):
- si = str(i)
- kw_val1['NAXIS'+si] = npol_header.get('NAXIS'+si)
- kw_val1['CDELT'+si] = npol_header.get('CDELT'+si, 1.0)
- kw_val1['CRPIX'+si] = npol_header.get('CRPIX'+si, 0.0)
- kw_val1['CRVAL'+si] = npol_header.get('CRVAL'+si, 0.0)
-
- kw_comm0 = {'XTENSION': 'Image extension',
- 'BITPIX': 'IEEE floating point',
- 'NAXIS': 'Number of axes',
- 'EXTNAME': 'WCS distortion array',
- 'EXTVER': 'Distortion array version number',
- 'PCOUNT': 'Special data area of size 0',
- 'GCOUNT': 'One data group',
- }
-
- kw_val0 = { 'XTENSION': 'IMAGE',
- 'BITPIX': -32,
- 'NAXIS': naxis,
- 'EXTNAME': 'WCSDVARR',
- 'EXTVER': wdvarr_ver,
- 'PCOUNT': 0,
- 'GCOUNT': 1,
- 'CCDCHIP': ccdchip,
- }
-
- cdl = pyfits.CardList()
- for key in kw_comm0.keys():
- cdl.append(pyfits.Card(key=key, value=kw_val0[key], comment=kw_comm0[key]))
- for key in kw_comm1.keys():
- cdl.append(pyfits.Card(key=key, value=kw_val1[key], comment=kw_comm1[key]))
-
-
- hdr = pyfits.Header(cards=cdl)
-
- return hdr
-
- createNpolHdr = classmethod(createNpolHdr)
-
- def get_ccdchip(cls, fobj, extname, extver):
- """
- Given a science file or dgeo file determine CCDCHIP
- """
- ccdchip = 1
- if fobj[0].header['INSTRUME'] == 'ACS' and fobj[0].header['DETECTOR'] == 'WFC':
- ccdchip = fobj[extname, extver].header['CCDCHIP']
- elif fobj[0].header['INSTRUME'] == 'WFC3' and fobj[0].header['DETECTOR'] == 'UVIS':
- ccdchip = fobj[extname, extver].header['CCDCHIP']
- elif fobj[0].header['INSTRUME'] == 'WFPC2':
- ccdchip = fobj[extname, extver].header['DETECTOR']
- elif fobj[0].header['INSTRUME'] == 'STIS':
- ccdchip = fobj[extname, extver].header['DETECTOR']
- elif fobj[0].header['INSTRUME'] == 'NICMOS':
- ccdchip = fobj[extname, extver].header['CAMERA']
- return ccdchip
-
- get_ccdchip = classmethod(get_ccdchip)
- \ No newline at end of file