summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/__init__.py47
-rw-r--r--lib/utils.py83
-rw-r--r--updatewcs/__init__.py45
-rw-r--r--updatewcs/corrections.py167
-rw-r--r--updatewcs/makewcs.py189
-rw-r--r--wcsutil/__init__.py115
-rw-r--r--wcsutil/instruments.py2
7 files changed, 299 insertions, 349 deletions
diff --git a/lib/__init__.py b/lib/__init__.py
index 08e421b..c9dca75 100644
--- a/lib/__init__.py
+++ b/lib/__init__.py
@@ -1,47 +1,8 @@
-import wcsutil
-from wcsutil import HSTWCS
-from pytools import fileutil, parseinput
-import pyfits
-
-#to avoid relative imports
+#import all needed modules here to avoid relative imports
import mappings
-from mappings import basic_wcs
+import utils
import distortion
import pywcs
-def restoreWCS(fnames):
- """
- Given a list of fits file names restore the original basic WCS kw
- and write out the files. This overwrites the original files.
- """
- files = parseinput.parseinput(fnames)[0]
- for f in files:
- isfits, ftype = fileutil.isFits(f)
- if not isfits or (isfits and ftype == 'waiver'):
- print "RestoreWCS works only on multiextension fits files."
- return
- else:
- fobj = pyfits.open(f, mode='update')
- hdr0 = fobj[0].header
- for ext in fobj:
- try:
- extname = ext.header['EXTNAME'].lower()
- except KeyError:
- continue
- if extname in ['sci', 'err', 'sdq']:
- hdr = ext.header
- owcs = HSTWCS(hdr0, hdr)
- #Changed restore to update the attributes ???
- # this may need to be changed
- backup = owcs.restore()
- if not backup:
- print '\No archived keywords found.\n'
- continue
- else:
- for kw in basic_wcs:
- nkw = ('O'+kw)[:7]
- if backup.has_key(kw):
- hdr.update(kw, hdr[nkw])
- fobj.close()
-
-
+
+ \ No newline at end of file
diff --git a/lib/utils.py b/lib/utils.py
new file mode 100644
index 0000000..bec12f7
--- /dev/null
+++ b/lib/utils.py
@@ -0,0 +1,83 @@
+from pytools import parseinput, fileutil
+import pyfits
+from mappings import basic_wcs
+
+def restoreWCS(fnames):
+ """
+ Given a list of fits file names restore the original basic WCS kw
+ and write out the files. This overwrites the original files.
+
+ Affected keywords:
+ 'CD1_1', 'CD1_2', 'CD2_1', 'CD2_2', 'CRVAL1','CRVAL2','CTYPE1', 'CTYPE2',
+ 'CRPIX1', 'CRPIX2', 'CTYPE1', 'CTYPE2', 'ORIENTAT'
+ """
+ files = parseinput.parseinput(fnames)[0]
+ for f in files:
+ isfits, ftype = fileutil.isFits(f)
+ if not isfits or (isfits and ftype == 'waiver'):
+ print "RestoreWCS works only with true fits files."
+ return
+ else:
+ fobj = pyfits.open(f, mode='update')
+ for ext in fobj:
+ try:
+ extname = ext.header['EXTNAME'].lower()
+ except KeyError:
+ continue
+ if extname in ['sci', 'err', 'sdq']:
+ hdr = ext.header
+ backup = get_archive(hdr)
+ if not backup:
+ #print 'No archived keywords found.\n'
+ continue
+ else:
+ for kw in basic_wcs:
+ nkw = ('O'+kw)[:7]
+ if backup.has_key(kw):
+ hdr.update(kw, hdr[nkw])
+ fobj.close()
+
+def get_archive(header):
+ """
+ Returns a dictionary with the archived basic WCS keywords.
+ """
+
+ backup = {}
+ for k in basic_wcs:
+ try:
+ nkw = ('O'+k)[:7]
+ backup[k] = header[nkw]
+ except KeyError:
+ pass
+ return backup
+
+def write_archive(header):
+ """
+ Archives original WCS kw before recalculating them.
+ """
+ backup_kw = get_archive(header)
+ if backup_kw != {}:
+ print "Archive already exists\n."
+ return
+ else:
+ cmt = 'archived value'
+ for kw in basic_wcs:
+ nkw = 'O'+kw
+ header.update(nkw[:7], header[kw], comment=cmt)
+
+
+def diff_angles(a,b):
+ """
+ Perform angle subtraction a-b taking into account
+ small-angle differences across 360degree line.
+ """
+
+ diff = a - b
+
+ if diff > 180.0:
+ diff -= 360.0
+
+ if diff < -180.0:
+ diff += 360.0
+
+ return diff \ No newline at end of file
diff --git a/updatewcs/__init__.py b/updatewcs/__init__.py
index db89d13..107a9f5 100644
--- a/updatewcs/__init__.py
+++ b/updatewcs/__init__.py
@@ -4,12 +4,13 @@ import pyfits
from hstwcs.wcsutil import HSTWCS
from hstwcs.mappings import allowed_corrections
#from .. mappings import allowed_corrections
+from hstwcs import utils
import corrections, makewcs
import dgeo
import time
from pytools import parseinput, fileutil
-#NB! the order of corrections matters
+#Note: The order of corrections is important
__docformat__ = 'restructuredtext'
@@ -52,19 +53,30 @@ def updatewcs(input, vacorr=True, tddcorr=True, checkfiles=True):
print 'No valid input, quitting ...\n'
return
for f in files:
- instr = pyfits.getval(f, 'INSTRUME')
+ instrument = pyfits.getval(f, 'INSTRUME')
+ if instrument == 'ACS' and pyfits.getval(f, 'DETECTOR')== 'WFC':
+ try:
+ tdc = pyfits.getval(f, 'TDDCORR')
+ if tdc == 'PERFORM':
+ tddcorr = True
+ else:
+ tddcorr = False
+ except KeyError:
+ tddcorr = True
try:
- acorr = setCorrections(instr,vacorr=vacorr, tddcorr=tddcorr)
+ #define which corrections will be performed
+ acorr = setCorrections(instrument,vacorr=vacorr, tddcorr=tddcorr)
except KeyError:
print 'Unsupported instrument %s ' %instr
print 'Removing %s from list of processed files\n' % f
files.remove(f)
continue
-
+ #restore the original WCS keywords
+ utils.restoreWCS(f)
makecorr(f, acorr)
return files
-def makecorr(fname, acorr):
+def makecorr(fname, allowed_corr):
"""
Purpose
=======
@@ -78,23 +90,26 @@ def makecorr(fname, acorr):
"""
f = pyfits.open(fname, mode='update')
+ #Determine the reference chip and make a copy of its restored header.
nrefchip, nrefext = getNrefchip(f)
primhdr = f[0].header
-
+ ref_hdr = f[nrefext].header.copy()
+ utils.write_archive(ref_hdr)
for extn in f:
- refwcs = HSTWCS(primhdr, f[nrefext].header)
- refwcs.archive_kw()
- refwcs.readModel()
+ # Perhaps all ext headers should be corrected (to be consistent)
if extn.header.has_key('extname') and extn.header['extname'].lower() == 'sci':
+ refwcs = HSTWCS(primhdr, ref_hdr, fobj=f)
+ refwcs.readModel(ref_hdr)
hdr = extn.header
- owcs = HSTWCS(primhdr, hdr)
- owcs.archive_kw()
- owcs.readModel()
- for c in acorr:
- owcs.__setattr__('DO'+c, 'PERFORM')
+ owcs = HSTWCS(primhdr, hdr, fobj=f)
+ utils.write_archive(hdr)
+ owcs.readModel(hdr)
+ for c in allowed_corr:
corr_klass = corrections.__getattribute__(c)
- corr_klass(owcs, refwcs)
+ kw2update = corr_klass.updateWCS(owcs, refwcs)
+ for kw in kw2update:
+ hdr.update(kw, kw2update[kw])
diff --git a/updatewcs/corrections.py b/updatewcs/corrections.py
index e94be64..ac49833 100644
--- a/updatewcs/corrections.py
+++ b/updatewcs/corrections.py
@@ -2,51 +2,44 @@ import datetime
import numpy
from numpy import linalg
from pytools import fileutil
+from hstwcs.utils import diff_angles
+import makewcs, dgeo
-from makewcs import MakeWCS
-from dgeo import DGEO
+MakeWCS = makewcs.MakeWCS
+DGEO = dgeo.DGEO
class TDDCorr(object):
"""
Purpose
=======
Apply time dependent distortion correction to SIP coefficients and basic
- WCS keywords. Atthi stime it is applicable only to ACS/WFC data.
+ WCS keywords. It is applicable only to ACS/WFC data.
Ref: Jay Anderson, ACS ISR 2007-08, Variation of the Distortion
Solution of the WFC
+ :Parameters:
+ `owcs`: HSTWCS object
+ An extension HSTWCS object to be modified
+ `refwcs`: HSTWCS object
+ A reference HSTWCS object
"""
- def __init__(self, owcs=None, refwcs=None):
- """
- :Parameters:
- `owcs`: HSTWCS object
- An extension HSTWCS object to be modified
- `refwcs`: HSTWCS object
- A reference HSTWCS object
- """
- self.wcsobj = owcs
- if self.wcsobj.DOTDDCorr == 'PERFORM':
- self.updateWCS()
- self.wcsobj.DOTDDCorr = 'COMPLETE'
- else:
- pass
-
- def updateWCS(self):
+
+ def updateWCS(cls, wcs, refwcs):
"""
- Calculates alpha and beta for ACS/WFC data.
- Writes 2 new kw to the extension header: TDDALPHA and TDDBETA
+ - sets TDDCORR to COMPLETE
"""
- if self.wcsobj.instrument == 'ACS' and self.wcsobj.detector == 'WFC':
- newkw = ['TDDALPHA', 'TDDBETA']
- self.set_alpha_beta()
- self.applyTDD()
- self.updatehdr(newkeywords=newkw)
-
- else:
- pass
+
+ alpha, beta = cls.set_alpha_beta(wcs)
+ cls.apply_tdd2idc(wcs, alpha, beta)
+ newkw = {'TDDALPHA': alpha, 'TDDBETA':beta, 'TDDCORR': 'COMPLETE'}
+
+ return newkw
+ updateWCS = classmethod(updateWCS)
- def applyTDD(self):
+ def apply_tdd2idc(cls,wcs, alpha, beta):
"""
Applies TDD to the idctab coefficients of a ACS/WFC observation.
This should be always the first correction.
@@ -56,36 +49,36 @@ class TDDCorr(object):
idcrad = fileutil.DEGTORAD(idctheta)
mrotp = fileutil.buildRotMatrix(idctheta)
mrotn = fileutil.buildRotMatrix(-idctheta)
- abmat = numpy.array([[self.TDDBETA,self.TDDALPHA],[self.TDDALPHA,self.TDDBETA]])
- tdd_mat = numpy.array([[1+(self.TDDBETA/2048.), self.TDDALPHA/2048.],[self.TDDALPHA/2048.,1-(self.TDDBETA/2048.)]],numpy.float64)
+ abmat = numpy.array([[beta,alpha],[alpha,beta]])
+ tdd_mat = numpy.array([[1+(beta/2048.), alpha/2048.],[alpha/2048.,1-(beta/2048.)]],numpy.float64)
abmat1 = numpy.dot(tdd_mat, mrotn)
abmat2 = numpy.dot(mrotp,abmat1)
- xshape, yshape = self.wcsobj.idcmodel.cx.shape, self.wcsobj.idcmodel.cy.shape
- icxy = numpy.dot(abmat2,[self.wcsobj.idcmodel.cx.ravel(),self.wcsobj.idcmodel.cy.ravel()])
- self.wcsobj.idcmodel.cx = icxy[0]
- self.wcsobj.idcmodel.cy = icxy[1]
- self.wcsobj.idcmodel.cx.shape = xshape
- self.wcsobj.idcmodel.cy.shape = yshape
+ xshape, yshape = wcs.idcmodel.cx.shape, wcs.idcmodel.cy.shape
+ icxy = numpy.dot(abmat2,[wcs.idcmodel.cx.ravel(),wcs.idcmodel.cy.ravel()])
+ wcs.idcmodel.cx = icxy[0]
+ wcs.idcmodel.cy = icxy[1]
+ wcs.idcmodel.cx.shape = xshape
+ wcs.idcmodel.cy.shape = yshape
+ wcs.set()
+
+ apply_tdd2idc = classmethod(apply_tdd2idc)
- def set_alpha_beta(self):
+ def set_alpha_beta(cls, wcs):
"""
Compute the time dependent distortion skew terms
default date of 2004.5 = 2004-7-1
"""
dday = 2004.5
- year,month,day = self.wcsobj.date_obs.split('-')
+ year,month,day = wcs.date_obs.split('-')
rdate = datetime.datetime(int(year),int(month),int(day))
rday = float(rdate.strftime("%j"))/365.25 + rdate.year
alpha = 0.095 + 0.090*(rday-dday)/2.5
beta = -0.029 - 0.030*(rday-dday)/2.5
- self.TDDALPHA = alpha
- self.TDDBETA = beta
-
- def updatehdr(self, newkeywords=None):
-
- for kw in newkeywords:
- self.wcsobj.hdr.update(kw, self.__getattribute__(kw))
+ return alpha, beta
+
+ set_alpha_beta = classmethod(set_alpha_beta)
+
class VACorr(object):
"""
@@ -93,60 +86,44 @@ class VACorr(object):
=======
Apply velocity aberation correction to WCS keywords.
Modifies the CD matrix and CRVAL1/2
+
"""
- def __init__(self, owcs=None, refwcs=None):
- self.wcsobj = owcs
- self.refwcs = refwcs
- if self.wcsobj.DOVACorr == 'PERFORM':
- self.updateWCS()
- self.wcsobj.DOVACorr == 'COMPLETE'
- else:
- pass
-
- def updateWCS(self):
- if self.wcsobj.vafactor != 1:
- self.wcsobj.cd = self.wcsobj.cd * self.wcsobj.vafactor
+
+ def updateWCS(cls, wcs, refwcs):
+ if wcs.vafactor != 1:
+ wcs.cd = wcs.cd * wcs.vafactor
+ crval1 = wcs.crval[0]
+ crval2 = wcs.crval[1]
+ wcs.crval[0] = wcs.crval[0] + wcs.vafactor*diff_angles(wcs.crval[0], crval1)
+ wcs.crval[1] = wcs.crval[1] + wcs.vafactor*diff_angles(wcs.crval[1], crval2)
- #self.wcsobj.crval[0] = self.wcsobj.ra_targ + self.wcsobj.vafactor*(self.wcsobj.crval[0] - self.wcsobj.ra_targ)
- #self.wcsobj.crval[1] = self.wcsobj.dec_targ + self.wcsobj.vafactor*(self.wcsobj.crval[1] - self.wcsobj.dec_targ)
- ref_backup = self.refwcs.restore()
- crval1 = ref_backup['CRVAL1']
- crval2 = ref_backup['CRVAL2']
- self.wcsobj.crval[0] = crval1 + self.wcsobj.vafactor*diff_angles(self.wcsobj.crval[0], crval1)
- self.wcsobj.crval[1] = crval2 + self.wcsobj.vafactor*diff_angles(self.wcsobj.crval[1], crval2)
-
- kw2update={'CD1_1': self.wcsobj.cd[0,0], 'CD1_2':self.wcsobj.cd[0,1],
- 'CD2_1':self.wcsobj.cd[1,0], 'CD2_2':self.wcsobj.cd[1,1],
- 'CRVAL1':self.wcsobj.crval[0], 'CRVAL2':self.wcsobj.crval[1]}
- self.updatehdr(newkeywords=kw2update)
+ kw2update={'CD1_1': wcs.cd[0,0], 'CD1_2':wcs.cd[0,1],
+ 'CD2_1':wcs.cd[1,0], 'CD2_2':wcs.cd[1,1],
+ 'CRVAL1':wcs.crval[0], 'CRVAL2':wcs.crval[1]}
+ wcs.set()
else:
pass
-
- def updatehdr(self, newkeywords=None):
- for kw in newkeywords:
- self.wcsobj.hdr.update(kw, newkeywords[kw])
+ return kw2update
+
+ updateWCS = classmethod(updateWCS)
+
class CompSIP(object):
"""
Purpose
=======
Compute SIP coefficients from idc table coefficients.
-
"""
- def __init__(self, owcs, refwcs):
- self.wcsobj = owcs
- self.updateWCS()
- self.DOCOMPSIP = 'COMPLETE'
-
- def updateWCS(self):
+
+ def updateWCS(cls, wcs, refwcs):
kw2update = {}
- order = self.wcsobj.idcmodel.norder
+ order = wcs.idcmodel.norder
kw2update['A_ORDER'] = order
kw2update['B_ORDER'] = order
- pscale = self.wcsobj.idcmodel.refpix['PSCALE']
+ pscale = wcs.idcmodel.refpix['PSCALE']
- cx = self.wcsobj.idcmodel.cx
- cy = self.wcsobj.idcmodel.cy
+ cx = wcs.idcmodel.cx
+ cy = wcs.idcmodel.cy
matr = numpy.array([[cx[1,1],cx[1,0]], [cy[1,1],cy[1,0]]], dtype=numpy.float)
imatr = linalg.inv(matr)
@@ -163,26 +140,8 @@ class CompSIP(object):
Bkey="B_%d_%d" % (m,n-m)
kw2update[Akey] = sipval[0,0]
kw2update[Bkey] = sipval[1,0]
- self.updatehdr(newkw=kw2update)
-
- def updatehdr(self, newkw=None):
- if not newkw: return
- for kw in newkw.keys():
- self.wcsobj.hdr.update(kw, newkw[kw])
-
-
-def diff_angles(a,b):
- """
- Perform angle subtraction a-b taking into account
- small-angle differences across 360degree line.
- """
+ return kw2update
- diff = a - b
+ updateWCS = classmethod(updateWCS)
- if diff > 180.0:
- diff -= 360.0
- if diff < -180.0:
- diff += 360.0
-
- return diff
diff --git a/updatewcs/makewcs.py b/updatewcs/makewcs.py
index 451da13..ddb4d06 100644
--- a/updatewcs/makewcs.py
+++ b/updatewcs/makewcs.py
@@ -3,6 +3,7 @@ from hstwcs.mappings import DEGTORAD, RADTODEG
import numpy
from numpy import math
from math import sin, sqrt, pow, cos, asin, atan2,pi
+from hstwcs import utils
class MakeWCS(object):
"""
@@ -17,74 +18,73 @@ class MakeWCS(object):
- update extension header
"""
-
- def __init__(self, owcs, refwcs):
- self.wcsobj = owcs
- self.refwcs = refwcs
- self.updateWCS()
- self.DOMakeWCS = 'COMPLETE'
-
- def updateWCS(self):
+
+ def updateWCS(cls, wcs, refwcs):
"""
recomputes the basic WCS kw
"""
- backup_wcs = self.wcsobj.restore()
- ltvoff, offshift = self.getOffsets(backup_wcs)
+ ltvoff, offshift = cls.getOffsets(wcs)
- self.uprefwcs(ltvoff, offshift)
- self.upextwcs(ltvoff, offshift)
- self.updatehdr()
-
- def upextwcs(self, loff, offsh):
+ cls.uprefwcs(wcs, refwcs, ltvoff, offshift)
+ cls.upextwcs(wcs, refwcs, ltvoff, offshift)
+
+ kw2update = {'CD1_1': wcs.cd[0,0],
+ 'CD1_2': wcs.cd[0,1],
+ 'CD2_1': wcs.cd[1,0],
+ 'CD2_2': wcs.cd[1,1],
+ 'CRVAL1': wcs.crval[0],
+ 'CRVAL2': wcs.crval[1],
+ 'CRPIX1': wcs.crpix[0],
+ 'CRPIX2': wcs.crpix[1],
+ }
+ return kw2update
+
+ updateWCS = classmethod(updateWCS)
+
+ def upextwcs(self, wcs, refwcs, loff, offsh):
"""
updates an extension wcs
"""
ltvoffx, ltvoffy = loff[0], loff[1]
offshiftx, offshifty = offsh[0], offsh[1]
- backup_wcs = self.wcsobj.restore()
- ltv1 = self.wcsobj.ltv1
- ltv2 = self.wcsobj.ltv2
-
-
+ ltv1 = wcs.ltv1
+ ltv2 = wcs.ltv2
if ltv1 != 0. or ltv2 != 0.:
- offsetx = backup_wcs['CRPIX1'] - ltv1 - self.wcsobj.idcmodel.refpix['XREF']
- offsety = backup_wcs['CRPIX2'] - ltv2 - self.wcsobj.idcmodel.refpix['YREF']
- fx,fy = self.wcsobj.idcmodel.shift(self.wcsobj.idcmodel.cx,self.wcsobj.idcmodel.cy,offsetx,offsety)
+ offsetx = backup_wcs['CRPIX1'] - ltv1 - wcs.idcmodel.refpix['XREF']
+ offsety = backup_wcs['CRPIX2'] - ltv2 - wcs.idcmodel.refpix['YREF']
+ fx,fy = wcs.idcmodel.shift(wcs.idcmodel.cx,wcs.idcmodel.cy,offsetx,offsety)
else:
- fx, fy = self.wcsobj.idcmodel.cx, self.wcsobj.idcmodel.cy
+ fx, fy = wcs.idcmodel.cx, wcs.idcmodel.cy
- ridcmodel = self.refwcs.idcmodel
- v2 = self.wcsobj.idcmodel.refpix['V2REF']
- v3 = self.wcsobj.idcmodel.refpix['V3REF']
- v2ref = self.refwcs.idcmodel.refpix['V2REF']
+ ridcmodel = refwcs.idcmodel
+ v2 = wcs.idcmodel.refpix['V2REF']
+ v3 = wcs.idcmodel.refpix['V3REF']
+ v2ref = refwcs.idcmodel.refpix['V2REF']
- v3ref = self.refwcs.idcmodel.refpix['V3REF']
- R_scale = self.refwcs.idcmodel.refpix['PSCALE']/3600.0
+ v3ref = refwcs.idcmodel.refpix['V3REF']
+ R_scale = refwcs.idcmodel.refpix['PSCALE']/3600.0
off = sqrt((v2-v2ref)**2 + (v3-v3ref)**2)/(R_scale*3600.0)
-
- # Here we must include the PARITY
if v3 == v3ref:
theta=0.0
else:
- theta = atan2(self.wcsobj.parity[0][0]*(v2-v2ref),self.wcsobj.parity[1][1]*(v3-v3ref))
+ theta = atan2(wcs.parity[0][0]*(v2-v2ref), wcs.parity[1][1]*(v3-v3ref))
- if self.refwcs.idcmodel.refpix['THETA']: theta += self.refwcs.idcmodel.refpix['THETA']*pi/180.0
+ if refwcs.idcmodel.refpix['THETA']: theta += refwcs.idcmodel.refpix['THETA']*pi/180.0
dX=(off*sin(theta)) + offshiftx
dY=(off*cos(theta)) + offshifty
px = numpy.array([[dX,dY]])
- newcrval = self.refwcs.pixel2world_fits(px)[0]
- newcrpix = numpy.array([self.wcsobj.idcmodel.refpix['XREF'] + ltvoffx,
- self.wcsobj.idcmodel.refpix['YREF'] + ltvoffy])
-
- self.wcsobj.crval = newcrval
- self.wcsobj.crpix = newcrpix
+ newcrval = refwcs.pixel2world_fits(px)[0]
+ newcrpix = numpy.array([wcs.idcmodel.refpix['XREF'] + ltvoffx,
+ wcs.idcmodel.refpix['YREF'] + ltvoffy])
+ wcs.crval = newcrval
+ wcs.crpix = newcrpix
# Account for subarray offset
# Angle of chip relative to chip
- if self.wcsobj.idcmodel.refpix['THETA']:
- dtheta = self.wcsobj.idcmodel.refpix['THETA'] - self.refwcs.idcmodel.refpix['THETA']
+ if wcs.idcmodel.refpix['THETA']:
+ dtheta = wcs.idcmodel.refpix['THETA'] - refwcs.idcmodel.refpix['THETA']
else:
dtheta = 0.0
@@ -96,8 +96,7 @@ class MakeWCS(object):
delYX=fy[1,1]/R_scale/3600.
delXY=fx[1,0]/R_scale/3600.
delYY=fy[1,0]/R_scale/3600.
-
-
+
# Convert to radians
rr=dtheta*pi/180.0
@@ -110,93 +109,74 @@ class MakeWCS(object):
px = numpy.array([[dX+dXX,dY+dYX]])
# Transform to sky coordinates
-
- wc = self.refwcs.pixel2world_fits(px)
+ wc = refwcs.pixel2world_fits(px)
a = wc[0,0]
b = wc[0,1]
px = numpy.array([[dX+dXY,dY+dYY]])
- wc = self.refwcs.pixel2world_fits(px)
+ wc = refwcs.pixel2world_fits(px)
c = wc[0,0]
d = wc[0,1]
-
+
# Calculate the new CDs and convert to degrees
- cd11 = diff_angles(a,newcrval[0])*cos(newcrval[1]*pi/180.0)
- cd12 = diff_angles(c,newcrval[0])*cos(newcrval[1]*pi/180.0)
- cd21 = diff_angles(b,newcrval[1])
- cd22 = diff_angles(d,newcrval[1])
-
+ cd11 = utils.diff_angles(a,newcrval[0])*cos(newcrval[1]*pi/180.0)
+ cd12 = utils.diff_angles(c,newcrval[0])*cos(newcrval[1]*pi/180.0)
+ cd21 = utils.diff_angles(b,newcrval[1])
+ cd22 = utils.diff_angles(d,newcrval[1])
cd = numpy.array([[cd11, cd12], [cd21, cd22]])
- self.wcsobj.cd = cd
+ wcs.cd = cd
+
+ upextwcs = classmethod(upextwcs)
- def uprefwcs(self, loff, offsh):
+ def uprefwcs(self, wcs, refwcs, loff, offsh):
"""
Updates the reference chip
"""
ltvoffx, ltvoffy = loff[0], loff[1]
offshift = offsh
- backup_refwcs = self.refwcs.restore()
- dec = backup_refwcs['CRVAL2']
-
+ dec = refwcs.crval[1]
# Get an approximate reference position on the sky
- rref = numpy.array([[self.refwcs.idcmodel.refpix['XREF']+ltvoffx,
- self.refwcs.idcmodel.refpix['YREF']+ltvoffy]])
-
-
- crval = self.refwcs.pixel2world_fits(rref)
+ rref = numpy.array([[refwcs.idcmodel.refpix['XREF']+ltvoffx,
+ refwcs.idcmodel.refpix['YREF']+ltvoffy]])
+ crval = refwcs.pixel2world_fits(rref)
# Convert the PA_V3 orientation to the orientation at the aperture
# This is for the reference chip only - we use this for the
# reference tangent plane definition
# It has the same orientation as the reference chip
- pv = troll(self.wcsobj.pav3,dec,self.refwcs.idcmodel.refpix['V2REF'],
- self.refwcs.idcmodel.refpix['V3REF'])
+ pv = troll(wcs.pav3,dec,refwcs.idcmodel.refpix['V2REF'],
+ refwcs.idcmodel.refpix['V3REF'])
# Add the chip rotation angle
- if self.refwcs.idcmodel.refpix['THETA']:
- pv += self.refwcs.idcmodel.refpix['THETA']
+ if refwcs.idcmodel.refpix['THETA']:
+ pv += refwcs.idcmodel.refpix['THETA']
# Set values for the rest of the reference WCS
- self.refwcs.crval = crval[0]
- self.refwcs.crpix = numpy.array([0.0,0.0])+offsh
- parity = self.refwcs.parity
- R_scale = self.refwcs.idcmodel.refpix['PSCALE']/3600.0
+ refwcs.crval = crval[0]
+ refwcs.crpix = numpy.array([0.0,0.0])+offsh
+ parity = refwcs.parity
+ R_scale = refwcs.idcmodel.refpix['PSCALE']/3600.0
cd11 = parity[0][0] * cos(pv*pi/180.0)*R_scale
cd12 = parity[0][0] * -sin(pv*pi/180.0)*R_scale
cd21 = parity[1][1] * sin(pv*pi/180.0)*R_scale
cd22 = parity[1][1] * cos(pv*pi/180.0)*R_scale
rcd = numpy.array([[cd11, cd12], [cd21, cd22]])
- self.refwcs.cd = rcd
- self.refwcs.set()
-
-
+ refwcs.cd = rcd
+ refwcs.set()
- def updatehdr(self):
- """
- Keywords to update:
- CD1_1, CD1_2, CD2_1, CD2_2, CRPIX1, CRPIX2, CRVAL1, CRVAL2
- """
-
- self.wcsobj.hdr.update('CD1_1', self.wcsobj.cd[0,0])
- self.wcsobj.hdr.update('CD1_2', self.wcsobj.cd[0,1])
- self.wcsobj.hdr.update('CD2_1', self.wcsobj.cd[1,0])
- self.wcsobj.hdr.update('CD2_2', self.wcsobj.cd[1,1])
- self.wcsobj.hdr.update('CRVAL1', self.wcsobj.crval[0])
- self.wcsobj.hdr.update('CRVAL2', self.wcsobj.crval[1])
- self.wcsobj.hdr.update('CRPIX1', self.wcsobj.crpix[0])
- self.wcsobj.hdr.update('CRPIX2', self.wcsobj.crpix[1])
- self.wcsobj.hdr.update('ORIENTAT', self.wcsobj.orientat)
+ uprefwcs = classmethod(uprefwcs)
- def getOffsets(self, backup_wcs):
- ltv1 = self.wcsobj.ltv1
- ltv2 = self.wcsobj.ltv2
+
+ def getOffsets(cls, wcs):
+ ltv1 = wcs.ltv1
+ ltv2 = wcs.ltv2
- offsetx = backup_wcs['CRPIX1'] - ltv1 - self.wcsobj.idcmodel.refpix['XREF']
- offsety = backup_wcs['CRPIX2'] - ltv2 - self.wcsobj.idcmodel.refpix['YREF']
+ offsetx = wcs.crpix[0] - ltv1 - wcs.idcmodel.refpix['XREF']
+ offsety = wcs.crpix[1] - ltv2 - wcs.idcmodel.refpix['YREF']
- shiftx = self.wcsobj.idcmodel.refpix['XREF'] + ltv1
- shifty = self.wcsobj.idcmodel.refpix['YREF'] + ltv2
+ shiftx = wcs.idcmodel.refpix['XREF'] + ltv1
+ shifty = wcs.idcmodel.refpix['YREF'] + ltv2
if ltv1 != 0. or ltv2 != 0.:
ltvoffx = ltv1 + offsetx
ltvoffy = ltv2 + offsety
@@ -212,21 +192,8 @@ class MakeWCS(object):
offshift = numpy.array([offshiftx, offshifty])
return ltvoff, offshift
-def diff_angles(a,b):
- """
- Perform angle subtraction a-b taking into account
- small-angle differences across 360degree line.
- """
-
- diff = a - b
-
- if diff > 180.0:
- diff -= 360.0
-
- if diff < -180.0:
- diff += 360.0
+ getOffsets = classmethod(getOffsets)
- return diff
def troll(roll, dec, v2, v3):
""" Computes the roll angle at the target position based on:
diff --git a/wcsutil/__init__.py b/wcsutil/__init__.py
index 46ad42e..9482a48 100644
--- a/wcsutil/__init__.py
+++ b/wcsutil/__init__.py
@@ -16,34 +16,34 @@ class HSTWCS(SIP):
"""
Purpose
=======
- Create a wcs object based on the instrument.
+ Create a WCS object based on the instrument.
It has all basic WCS kw as attribbutes (set by pywcs).
It also uses the primary and extension header to define
instrument specific attributes needed by the correction classes.
"""
- def __init__(self, hdr0, hdr):
+ def __init__(self, hdr0, ehdr, fobj=None):
"""
:Parameters:
`hdr0`: Pyfits Header
primary header
- `hdr`: Pyfits Header
+ `ehdr`: Pyfits Header
extension header
+ `fobj`: PyFITS HDUList object or None
+ pyfits file object
"""
- self.hdr = hdr
- self.hdr0 = hdr0
- SIP.__init__(self, self.hdr)
+ SIP.__init__(self, ehdr, fobj=fobj)
self.setHDR0kw(hdr0)
- self.detector = self.setDetector()
+ self.detector = self.setDetector(hdr0)
self.inst_kw = ins_spec_kw
- self.setInstrSpecKw()
+ self.setInstrSpecKw(hdr0, ehdr)
self.pscale = self.setPscale()
self.orientat = self.setOrient()
def setHDR0kw(self, primhdr):
- #sets attributes from kw defined in the primary header
+ # Set attributes from kw defined in the primary header.
self.instrument = primhdr.get('INSTRUME', None)
self.offtab = primhdr.get('OFFTAB', None)
self.idctab = primhdr.get('IDCTAB', None)
@@ -53,34 +53,35 @@ class HSTWCS(SIP):
self.dec_targ = primhdr.get('DEC_TARG', None)
- def setDetector(self):
- #sets detector attribute for instuments which have more than one detector
+ def setDetector(self, header):
+ # Set detector attribute for instuments which have more than one detector
if self.instrument in ['ACS', 'WFC3']:
- return self.hdr0.get('DETECTOR', None)
-
-
- def setInstrSpecKw(self):
- #Based on the instrument kw creates an instalnce of an instrument WCS class
- #and sets attributes from instrument specific kw
+ return header.get('DETECTOR', None)
+ else:
+ return None
+
+ def setInstrSpecKw(self, prim_hdr, ext_hdr):
+ # Based on the instrument kw creates an instalnce of an instrument WCS class
+ # and sets attributes from instrument specific kw
if self.instrument in inst_mappings.keys():
inst_kl = inst_mappings[self.instrument]
inst_kl = instruments.__dict__[inst_kl]
- insobj = inst_kl(self.hdr0, self.hdr)
+ insobj = inst_kl(prim_hdr, ext_hdr)
for key in self.inst_kw:
self.__setattr__(key, insobj.__getattribute__(key))
else:
raise KeyError, "Unsupported instrument - %s" %self.instrument
def setPscale(self):
- #Calculates the plate scale from the cd matrix
- #this may not be needed now and shoufl probably be done after all
+ # Calculates the plate scale from the cd matrix
+ # this may not be needed now and shoufl probably be done after all
# corrections
cd11 = self.cd[0][0]
cd21 = self.cd[1][0]
return N.sqrt(N.power(cd11,2)+N.power(cd21,2)) * 3600.
def setOrient(self):
- #same as setPscale
+ # Recompute ORIENTAT
cd12 = self.cd[0][1]
cd22 = self.cd[1][1]
return RADTODEG(N.arctan2(cd12,cd22))
@@ -91,7 +92,7 @@ class HSTWCS(SIP):
def verifyKw(self):
"""verify that all required kw have meaningful values"""
- def readModel(self):
+ def readModel(self, header):
"""
Purpose
=======
@@ -106,61 +107,27 @@ class HSTWCS(SIP):
offtab=self.offtab, binned=self.binned)
- self.updatehdr()
+ self.updatehdr(header)
- def updatehdr(self, newkeywords=None):
+ def updatehdr(self, ext_hdr, newkeywords=None):
#kw2add : OCX10, OCX11, OCY10, OCY11
# record the model in the header for use by pydrizzle
- self.hdr.update('OCX10', self.idcmodel.cx[1,0])
- self.hdr.update('OCX11', self.idcmodel.cx[1,1])
- self.hdr.update('OCY10', self.idcmodel.cy[1,0])
- self.hdr.update('OCY11', self.idcmodel.cy[1,1])
- self.hdr.update('IDCSCALE', self.idcmodel.refpix['PSCALE'])
- self.hdr.update('IDCTHETA', self.idcmodel.refpix['THETA'])
- self.hdr.update('IDCXREF', self.idcmodel.refpix['XREF'])
- self.hdr.update('IDCYREF', self.idcmodel.refpix['YREF'])
- self.hdr.update('IDCV2REF', self.idcmodel.refpix['V2REF'])
- self.hdr.update('IDCV3REF', self.idcmodel.refpix['V3REF'])
- self.hdr.update('IDCXSIZE', self.idcmodel.refpix['XSIZE'])
- self.hdr.update('IDCYSIZE', self.idcmodel.refpix['YSIZE'])
- self.hdr.update('IDCXDELT', self.idcmodel.refpix['XDELTA'])
- self.hdr.update('IDCYDELT', self.idcmodel.refpix['YDELTA'])
- self.hdr.update('CENTERED', self.idcmodel.refpix['centered'])
+ ext_hdr.update('OCX10', self.idcmodel.cx[1,0])
+ ext_hdr.update('OCX11', self.idcmodel.cx[1,1])
+ ext_hdr.update('OCY10', self.idcmodel.cy[1,0])
+ ext_hdr.update('OCY11', self.idcmodel.cy[1,1])
+ ext_hdr.update('IDCSCALE', self.idcmodel.refpix['PSCALE'])
+ ext_hdr.update('IDCTHETA', self.idcmodel.refpix['THETA'])
+ ext_hdr.update('IDCXREF', self.idcmodel.refpix['XREF'])
+ ext_hdr.update('IDCYREF', self.idcmodel.refpix['YREF'])
+ ext_hdr.update('IDCV2REF', self.idcmodel.refpix['V2REF'])
+ ext_hdr.update('IDCV3REF', self.idcmodel.refpix['V3REF'])
+ ext_hdr.update('IDCXSIZE', self.idcmodel.refpix['XSIZE'])
+ ext_hdr.update('IDCYSIZE', self.idcmodel.refpix['YSIZE'])
+ ext_hdr.update('IDCXDELT', self.idcmodel.refpix['XDELTA'])
+ ext_hdr.update('IDCYDELT', self.idcmodel.refpix['YDELTA'])
+ ext_hdr.update('CENTERED', self.idcmodel.refpix['centered'])
- def restore(self):
- """
- restores basic wcs keywords from archive
- this should be modified to always return a populated
- dictionary, although the values may be None.
- """
-
- backup = {}
- for k in basic_wcs:
- try:
- nkw = ('O'+k)[:7]
- #backup[k] = self.hdr.__getitem__('O'+k)
- backup[k] = self.hdr[nkw]
- #self.__setattr__(k, self.hdr.__getitem__('O'+k))
- self.__setattr__(k, self.hdr[nkw])
- except KeyError:
- print 'Keyword %s not found' % k
-
- return backup
-
- def archive_kw(self):
- """
- archive original WCS kw before recalculating them.
- """
- backup_kw = self.restore()
- if backup_kw != {}:
- return
- else:
- # keep the archived kw 8 characters long
- cmt = 'archived value'
- for kw in basic_wcs:
- nkw = 'O'+kw
- self.hdr.update(nkw[:7], self.hdr[kw], comment=cmt)
-
-
+ \ No newline at end of file
diff --git a/wcsutil/instruments.py b/wcsutil/instruments.py
index 2790d8a..a80ec31 100644
--- a/wcsutil/instruments.py
+++ b/wcsutil/instruments.py
@@ -71,13 +71,11 @@ class ACSWCS(InstrWCS):
InstrWCS.__init__(self,hdr0, hdr)
self.set_ins_spec_kw()
-
def set_parity(self):
parity = {'WFC':[[1.0,0.0],[0.0,-1.0]],
'HRC':[[-1.0,0.0],[0.0,1.0]],
'SBC':[[-1.0,0.0],[0.0,1.0]]}
detector = self.primhdr.get('detector', None)
- print 'detector', detector
self.parity = parity[detector]