summaryrefslogtreecommitdiff
path: root/updatewcs/dgeo.py
diff options
context:
space:
mode:
Diffstat (limited to 'updatewcs/dgeo.py')
-rw-r--r--updatewcs/dgeo.py157
1 files changed, 97 insertions, 60 deletions
diff --git a/updatewcs/dgeo.py b/updatewcs/dgeo.py
index d15a485..70e6a98 100644
--- a/updatewcs/dgeo.py
+++ b/updatewcs/dgeo.py
@@ -1,6 +1,7 @@
import pyfits
from pytools import fileutil
-from hstwcs.mappings import dgeo_vals
+#from hstwcs.mappings import dgeo_vals
+import numpy
class DGEOCorr(object):
"""
@@ -13,7 +14,7 @@ class DGEOCorr(object):
=========
- Using extensions in the reference file create a WCSDVARR extension
and add it to the file object.
- - Add record-valued keywords which describe the looikup tables to the
+ - Add record-valued keywords which describe the lookup tables to the
science extension header
- Add a keyword 'DGEOFILE' to the science extension header, whose
value is the reference file used to create the WCSVARR extension
@@ -21,35 +22,38 @@ class DGEOCorr(object):
If WCSDVARR extensions exist, subsequent updates will overwrite them.
If not, they will be added to the file object.
+ It is assumed that the DGEO 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 correc tion in a DGEOFILE is available
+ Science file, for which a distortion correction in a DGEOFILE is available
"""
assert isinstance(fobj, pyfits.NP_pyfits.HDUList)
- #self.fobj = fobj
cls.applyDgeoCorr(fobj)
dgfile = fobj[0].header['DGEOFILE']
- new_kw = {'DGEOFIEL': dgfile}
+ new_kw = {'DGEOFILE': dgfile}
return new_kw
updateWCS = classmethod(updateWCS)
- def applyDgeoCorr(cls,fobj):
+ def applyDgeoCorr(cls, fobj):
"""
For each science extension in a pyfits file object:
- create a WCSDVARR extension
- update science header
- add/update DGEOFILE keyword
"""
-
- dgeover = 0
dgfile = fileutil.osfn(fobj[0].header['DGEOFILE'])
instrument = fobj[0].header.get('INSTRUME', None)
+ # Map WCSDVARR EXTVER numbers to extension numbers
wcsdvarr_ind = cls.getWCSIndex(fobj)
for ext in fobj:
try:
@@ -58,22 +62,31 @@ class DGEOCorr(object):
continue
if extname == 'sci':
extversion = ext.header['EXTVER']
- for ename in ['DX', 'DY']:
- dgeover +=1
-
- cls.addSciExtKw(ext.header, extver=dgeover, ename=ename)
- hdu = cls.createDgeoHDU(instrument, dgeofile=dgfile, dgeover=dgeover,ename=ename, extver=extversion)
+ header = ext.header
+ # get the data arrays from the reference file and transform them for use with SIP
+ dx,dy = cls.getData(dgfile, extversion)
+ ndx, ndy = cls.transformData(header, dx,dy)
+ # determine EXTVER for the WCSDVARR extension from the DGEO file (EXTNAME, 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],[ndx, ndy]):
+ cls.addSciExtKw(header, wdvarr_ver=ename[1], dgeo_name=ename[0])
+ hdu = cls.createDgeoHDU(header, dgeofile=dgfile, wdvarr_ver=ename[1],dgeo_name=ename[0], data=ename[2],extver=extversion)
if wcsdvarr_ind:
- fobj[wcsdvarr_ind[dgeover]] = hdu
+ fobj[wcsdvarr_ind[ename[1]]] = hdu
else:
fobj.append(hdu)
-
+
+
applyDgeoCorr = classmethod(applyDgeoCorr)
-
+
def getWCSIndex(cls, fobj):
"""
- Returns a mapping of WCSDVARR 'EXTVER' and pyfits.HDUList indeces.
-
+ If fobj has WCSDVARR extensions:
+ returns a mapping of their EXTVER kw are mapped to extension numbers
+ if fobj does not have WCSDVARR extensions:
+ an empty dictionary is returned.
"""
wcsd = {}
for e in range(len(fobj)):
@@ -88,17 +101,12 @@ class DGEOCorr(object):
getWCSIndex = classmethod(getWCSIndex)
- def addSciExtKw(cls, hdr, extver=None, ename=None):
+ def addSciExtKw(cls, hdr, wdvarr_ver=None, dgeo_name=None):
"""
- Adds kw to sci extension to define dgeo correction extensions
- kw to be added to sci ext:
- CPERRORj
- CPDISj
- DPj.EXTVER
- DPj.NAXES
- DPj.AXIS.i (i=DP1.NAXES)
+ Adds kw to sci extension to define WCSDVARR lookup table extensions
+
"""
- if ename =='DX':
+ if dgeo_name =='DX':
j=1
else:
j=2
@@ -110,10 +118,10 @@ class DGEOCorr(object):
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: extver, dpnaxes: 2,
+ 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' % (extver/2),
+ comments = {cperror: 'Maximum error of dgeo correction for axis %s' % (wdvarr_ver/2),
cpdis: 'Prior distortion funcion type',
dpext: 'Version number of WCSDVARR extension containing lookup distortion table',
dpnaxes: 'Number of independent variables in distortion function',
@@ -126,46 +134,75 @@ class DGEOCorr(object):
addSciExtKw = classmethod(addSciExtKw)
- def getDgeoData(cls, dgfile=None, ename=None, extver=1):
+ def getData(cls,dgfile, extver):
"""
- Given a dgeo file name, creates an array to be used
- as a data array in the dgeo extension.
- """
- return pyfits.getdata(dgfile, ext=(ename,extver))
-
- getDgeoData = classmethod(getDgeoData)
-
- def createDgeoHDU(cls, instrument, dgeofile=None, dgeover=1, ename=None,extver=1):
+ Get the data arrays from the reference DGEO files
+ """
+ xdata = pyfits.getdata(dgfile, ext=('DX',extver))
+ ydata = pyfits.getdata(dgfile, ext=('DY',extver))
+ return xdata, ydata
+ getData = classmethod(getData)
+
+ def transformData(cls, header, dx, dy):
+ """
+ Transform the DGEO data arrays for use with SIP
+ """
+ coeffs = cls.getCoeffs(header)
+ idcscale = header['IDCSCALE']
+ sclcoeffs = numpy.linalg.inv(coeffs)/idcscale
+ ndx, ndy = numpy.dot(sclcoeffs, [dx.ravel(), dy.ravel()])
+ ndx.shape = dx.shape
+ ndy.shape=dy.shape
+ return ndx, ndy
+ transformData = classmethod(transformData)
+
+ def getCoeffs(cls, header):
+ """
+ Return a matrix of the first order IDC coefficients.
+ """
+ try:
+ ocx10 = header['OCX10']
+ ocx11 = header['OCX11']
+ ocy10 = header['OCY10']
+ ocy11 = header['OCY11']
+ except AttributeError:
+ print 'First order IDCTAB coefficients are not available.\n'
+ print 'Cannot convert SIP to IDC coefficients.\n'
+ return None
+ return numpy.array([[ocx11, ocx10], [ocy11,ocy10]], dtype=numpy.float32)
+
+ getCoeffs = classmethod(getCoeffs)
+
+ def createDgeoHDU(cls, sciheader, dgeofile=None, wdvarr_ver=1, dgeo_name=None,data = None, extver=1):
"""
Creates an HDU to be added to the file object.
"""
- dgeokw = {'naxis1':None, 'naxis2':None, 'extver':dgeover, 'crpix1':None,
- 'crpix2':None, 'cdelt1':None, 'cdelt2':None, 'crval1':None, 'crval2':None}
- hdr = cls.createDgeoHdr(instrument, **dgeokw)
- data = cls.getDgeoData(dgfile=dgeofile, ename=ename, extver=extver)
+ hdr = cls.createDgeoHdr(sciheader, dgeofile=dgeofile, wdvarr_ver=wdvarr_ver, dgeoname=dgeo_name, extver=extver)
hdu=pyfits.ImageHDU(header=hdr, data=data)
return hdu
+
createDgeoHDU = classmethod(createDgeoHDU)
- def createDgeoHdr(cls, instr, **kw):
+ def createDgeoHdr(cls, sciheader, dgeofile, wdvarr_ver, dgeoname, extver):
"""
- Creates a header for the dgeo extension based on dgeo file
+ Creates a header for the WCSDVARR extension based on the DGEO reference file
and sci extension header.
- **kw = {'naxis1':None, 'naxis2':None, 'extver':None, 'crpix1':None,
- 'crpix2':None, 'cdelt1':None, 'cdelt2':None, 'crval1':None, 'crval2':None}
- """
- #instr = self.fobj[0].header['INSTRUME']
- instr_vals = dgeo_vals[instr]
- naxis1 = kw['naxis1'] or instr_vals['naxis1']
- naxis2 = kw['naxis2'] or instr_vals['naxis2']
- extver = kw['extver'] or instr_vals['extver']
- crpix1 = kw['crpix1'] or instr_vals['crpix1']
- crpix2 = kw['crpix2'] or instr_vals['crpix2']
- cdelt1 = kw['cdelt1'] or instr_vals['cdelt1']
- cdelt2 = kw['cdelt2'] or instr_vals['cdelt2']
- crval1 = kw['crval1'] or instr_vals['crval1']
- crval2 = kw['crval2'] or instr_vals['crval2']
-
+ """
+ dgeo_header = pyfits.getheader(dgeofile, ext=(dgeoname,extver))
+ sci_naxis1 = sciheader['NAXIS1']
+ sci_naxis2 = sciheader['NAXIS2']
+ sci_crpix1 = sciheader['CRPIX1']
+ sci_crpix2 = sciheader['CRPIX2']
+
+ naxis1 = dgeo_header['naxis1']
+ naxis2 = dgeo_header['naxis2']
+ extver = dgeo_header['extver']
+ crpix1 = naxis1/2.
+ crpix2 = naxis2/2.
+ cdelt1 = sci_naxis1/naxis1
+ cdelt2 = sci_naxis2/naxis2
+ crval1 = sci_crpix1
+ crval2 = sci_crpix2
keys = ['XTENSION','BITPIX','NAXIS','NAXIS1','NAXIS2',
'EXTNAME','EXTVER','PCOUNT','GCOUNT','CRPIX1',
'CDELT1','CRVAL1','CRPIX2','CDELT2','CRVAL2']
@@ -192,7 +229,7 @@ class DGEOCorr(object):
'NAXIS1': naxis1,
'NAXIS2': naxis2,
'EXTNAME': 'WCSDVARR',
- 'EXTVER': extver,
+ 'EXTVER': wdvarr_ver,
'PCOUNT': 0,
'GCOUNT': 1,
'CRPIX1': crpix1,