diff options
-rw-r--r-- | updatewcs/__init__.py | 104 | ||||
-rw-r--r-- | wcsutil/hstwcs.py | 14 | ||||
-rw-r--r-- | wcsutil/mosaic.py | 40 | ||||
-rw-r--r-- | wcsutil/wcscorr.py | 165 |
4 files changed, 196 insertions, 127 deletions
diff --git a/updatewcs/__init__.py b/updatewcs/__init__.py index 08a0a46..10bba90 100644 --- a/updatewcs/__init__.py +++ b/updatewcs/__init__.py @@ -24,24 +24,24 @@ atexit.register(logging.shutdown) __docformat__ = 'restructuredtext' -def updatewcs(input, vacorr=True, tddcorr=True, npolcorr=True, d2imcorr=True, +def updatewcs(input, vacorr=True, tddcorr=True, npolcorr=True, d2imcorr=True, checkfiles=True, wcskey=" ", wcsname=" ", clobber=False, verbose=False): """ Updates HST science files with the best available calibration information. - This allows users to retrieve from the archive self contained science files + This allows users to retrieve from the archive self contained science files which do not require additional reference files. - - Basic WCS keywords are updated in the process and new keywords (following WCS + + Basic WCS keywords are updated in the process and new keywords (following WCS Paper IV and the SIP convention) as well as new extensions are added to the science files. - - + + Example ------- >>>from stwcs import updatewcs >>>updatewcs.updatewcs(filename) - - Dependencies + + Dependencies ------------ `pytools` `pyfits` @@ -54,7 +54,7 @@ def updatewcs(input, vacorr=True, tddcorr=True, npolcorr=True, d2imcorr=True, vacorr: boolean If True, vecocity aberration correction will be applied tddcorr: boolean - If True, time dependent distortion correction will be applied + If True, time dependent distortion correction will be applied npolcorr: boolean If True, a Lookup table distortion will be applied d2imcorr: boolean @@ -69,7 +69,7 @@ def updatewcs(input, vacorr=True, tddcorr=True, npolcorr=True, d2imcorr=True, A-Z - use this key to archive the WCS wcsname: a string The name under which the primary WCS is archived after it is updated. - If an empty string (default), the name of the idctable is used as + If an empty string (default), the name of the idctable is used as a base. clobber: boolean a flag for reusing the wcskey when archiving the primary WCS @@ -79,11 +79,11 @@ def updatewcs(input, vacorr=True, tddcorr=True, npolcorr=True, d2imcorr=True, else: logger.setLevel(verbose) args = "vacorr=%s, tddcorr=%s, npolcorr=%s, d2imcorr=%s, checkfiles=%s, \ - wcskey=%s, wcsname=%s, clobber=%s" % (str(vacorr), str(tddcorr), str(npolcorr), - str(d2imcorr), str(checkfiles), str(wcskey), + wcskey=%s, wcsname=%s, clobber=%s" % (str(vacorr), str(tddcorr), str(npolcorr), + str(d2imcorr), str(checkfiles), str(wcskey), str(wcsname), str(clobber)) logger.info('\n\tStarting UPDATEWCS: %s', time.asctime()) - + files = parseinput.parseinput(input)[0] logger.info("\n\tInput files: %s, " % [i for i in files]) logger.info("\n\tInput arguments: %s" %args) @@ -91,7 +91,7 @@ def updatewcs(input, vacorr=True, tddcorr=True, npolcorr=True, d2imcorr=True, files = checkFiles(files) if not files: print 'No valid input, quitting ...\n' - return + return for f in files: acorr = apply_corrections.setCorrections(f, vacorr=vacorr, \ @@ -99,7 +99,7 @@ def updatewcs(input, vacorr=True, tddcorr=True, npolcorr=True, d2imcorr=True, if 'MakeWCS' in acorr and newIDCTAB(f): logger.warning("\n\tNew IDCTAB file detected. All current WCSs will be deleted") cleanWCS(f) - + #restore the original WCS keywords makecorr(f, acorr, wkey=wcskey, wname=wcsname, clobber=False) return files @@ -109,7 +109,7 @@ def makecorr(fname, allowed_corr, wkey=" ", wname=" ", clobber=False): Purpose ======= Applies corrections to the WCS of a single file - + :Parameters: `fname`: string file name @@ -121,7 +121,7 @@ def makecorr(fname, allowed_corr, wkey=" ", wname=" ", clobber=False): A-Z - use this key to archive the WCS `wname`: a string The name under which the primary WCS is archived after it is updated. - If an empty string (default), the name of the idctable is used as + If an empty string (default), the name of the idctable is used as a base. `clobber`: boolean a flag for reusing the wcskey when archiving the primary WCS @@ -134,19 +134,19 @@ def makecorr(fname, allowed_corr, wkey=" ", wname=" ", clobber=False): wcsutil.restoreWCS(f, nrefext, wcskey='O', clobber=True) rwcs = HSTWCS(fobj=f, ext=nrefext) rwcs.readModel(update=True,header=f[nrefext].header) - + wcsutil.archiveWCS(f, nrefext, 'O', wcsname='OPUS', clobber=True) - + if 'DET2IMCorr' in allowed_corr: det2im.DET2IMCorr.updateWCS(f) - + # get a wcskey and wcsname from the first extension header idcname = fileutil.osfn(rwcs.idctab) key, name = getKeyName(f[1].header, wkey, wname, idcname) - + for i in range(len(f))[1:]: extn = f[i] - + if extn.header.has_key('extname'): extname = extn.header['extname'].lower() if extname == 'sci': @@ -163,7 +163,7 @@ def makecorr(fname, allowed_corr, wkey=" ", wname=" ", clobber=False): kw2update = corr_klass.updateWCS(ext_wcs, ref_wcs) for kw in kw2update: hdr.update(kw, kw2update[kw]) - #if wkey is None, do not archive the primary WCS + #if wkey is None, do not archive the primary WCS if key is not None: wcsutil.archiveWCS(f, ext=i, wcskey=key, wcsname=name, clobber=True) elif extname in ['err', 'dq', 'sdq', 'samp', 'time']: @@ -174,7 +174,7 @@ def makecorr(fname, allowed_corr, wkey=" ", wname=" ", clobber=False): copyWCS(w, extn.header, key, name) else: continue - + if 'NPOLCorr' in allowed_corr: kw2update = npol.NPOLCorr.updateWCS(f) for kw in kw2update: @@ -207,13 +207,13 @@ def getKeyName(hdr, wkey, wname, idcname): def copyWCS(w, hdr, wkey, wname): """ - This is a convenience function to copy a WCS object - to a header as a primary WCS. It is used only to copy the + This is a convenience function to copy a WCS object + to a header as a primary WCS. It is used only to copy the WCS of the 'SCI' extension to the headers of 'ERR', 'DQ', 'SDQ', 'TIME' or 'SAMP' extensions. """ hwcs = w.to_header() - + if w.wcs.has_cd(): wcsutil.pc2cd(hwcs) for k in hwcs.keys(): @@ -221,19 +221,19 @@ def copyWCS(w, hdr, wkey, wname): hdr.update(key=key, value=hwcs[k]) norient = np.rad2deg(np.arctan2(hwcs['CD1_2'],hwcs['CD2_2'])) okey = 'ORIENT%s' % wkey - hdr.update(key=okey, value=norient) + hdr.update(key=okey, value=norient) def getNrefchip(fobj): """ Finds which FITS extension holds the reference chip. - - The reference chip has EXTNAME='SCI', can be in any extension and - is instrument specific. This functions provides mappings between + + The reference chip has EXTNAME='SCI', can be in any extension and + is instrument specific. This functions provides mappings between sci extensions, chips and fits extensions. In the case of a subarray when the reference chip is missing, the first 'SCI' extension is the reference chip. - + Parameters ---------- fobj: pyfits HDUList object @@ -241,19 +241,19 @@ def getNrefchip(fobj): nrefext = 1 nrefchip = 1 instrument = fobj[0].header['INSTRUME'] - + if instrument == 'WFPC2': chipkw = 'DETECTOR' - extvers = [("SCI",img.header['EXTVER']) for img in + extvers = [("SCI",img.header['EXTVER']) for img in fobj[1:] if img.header['EXTNAME'].lower()=='sci'] - detectors = [img.header[chipkw] for img in fobj[1:] if + detectors = [img.header[chipkw] for img in fobj[1:] if img.header['EXTNAME'].lower()=='sci'] - fitsext = [i for i in range(len(fobj))[1:] if + fitsext = [i for i in range(len(fobj))[1:] if fobj[i].header['EXTNAME'].lower()=='sci'] det2ext=dict(map(None, detectors,extvers)) ext2det=dict(map(None, extvers, detectors)) ext2fitsext=dict(map(None, extvers, fitsext)) - + if 3 not in detectors: nrefchip = ext2det.pop(extvers[0]) nrefext = ext2fitsext.pop(extvers[0]) @@ -261,20 +261,20 @@ def getNrefchip(fobj): nrefchip = 3 extname = det2ext.pop(nrefchip) nrefext = ext2fitsext.pop(extname) - + elif (instrument == 'ACS' and fobj[0].header['DETECTOR'] == 'WFC') or \ (instrument == 'WFC3' and fobj[0].header['DETECTOR'] == 'UVIS'): chipkw = 'CCDCHIP' - extvers = [("SCI",img.header['EXTVER']) for img in + extvers = [("SCI",img.header['EXTVER']) for img in fobj[1:] if img.header['EXTNAME'].lower()=='sci'] - detectors = [img.header[chipkw] for img in fobj[1:] if + detectors = [img.header[chipkw] for img in fobj[1:] if img.header['EXTNAME'].lower()=='sci'] - fitsext = [i for i in range(len(fobj))[1:] if + fitsext = [i for i in range(len(fobj))[1:] if fobj[i].header['EXTNAME'].lower()=='sci'] det2ext=dict(map(None, detectors,extvers)) ext2det=dict(map(None, extvers, detectors)) ext2fitsext=dict(map(None, extvers, fitsext)) - + if 2 not in detectors: nrefchip = ext2det.pop(extvers[0]) nrefext = ext2fitsext.pop(extvers[0]) @@ -288,7 +288,7 @@ def getNrefchip(fobj): if extname != None and extname.lower == 'sci': nrefext = i break - + return nrefchip, nrefext def checkFiles(input): @@ -312,7 +312,7 @@ def checkFiles(input): continue # Check for existence of waiver FITS input, and quit if found. # Or should we print a warning and continue but not use that file - if imgfits: + if imgfits: if imgtype == 'waiver': newfilename = waiver2mef(file, convert_dq=True) if newfilename == None: @@ -323,9 +323,9 @@ def checkFiles(input): else: newfiles.append(file) - # If a GEIS image is provided as input, create a new MEF file with + # If a GEIS image is provided as input, create a new MEF file with # a name generated using 'buildFITSName()' - # Convert the corresponding data quality file if present + # Convert the corresponding data quality file if present if not imgfits: newfilename = geis2mef(file, convert_dq=True) if newfilename == None: @@ -337,7 +337,7 @@ def checkFiles(input): logger.warning('\n\tThe following files will be removed from the list of files to be processed %s' % removed_files) #for f in removed_files: # print f - + newfiles = checkFiles(newfiles)[0] logger.info("\n\tThese files passed the input check and will be processed: %s" % newfiles) return newfiles @@ -354,7 +354,7 @@ def newIDCTAB(fname): return False else: return True - + def cleanWCS(fname): # A new IDCTAB means all previously computed WCS's are invalid # We are deleting all of them except the original OPUS WCS.nvalidates all WCS's. @@ -363,16 +363,16 @@ def cleanWCS(fname): fext = range(len(f)) for key in keys: wcsutil.deleteWCS(fname, ext=fext,wcskey=key) - + def getCorrections(instrument): """ Print corrections available for an instrument - + :Parameters: `instrument`: string, one of 'WFPC2', 'NICMOS', 'STIS', 'ACS', 'WFC3' """ acorr = apply_corrections.allowed_corrections[instrument] - + print "The following corrections will be performed for instrument %s\n" % instrument for c in acorr: print c,': ' , apply_corrections.cnames[c] -
\ No newline at end of file + diff --git a/wcsutil/hstwcs.py b/wcsutil/hstwcs.py index d16e174..26dad5d 100644 --- a/wcsutil/hstwcs.py +++ b/wcsutil/hstwcs.py @@ -50,22 +50,24 @@ class HSTWCS(WCS): self.minerr = minerr self.wcskey = wcskey - if fobj != None: - filename, hdr0, ehdr, phdu = getinput.parseSingleInput(f=fobj, ext=ext) + if fobj is not None: + filename, hdr0, ehdr, phdu = getinput.parseSingleInput(f=fobj, + ext=ext) self.filename = filename instrument_name = hdr0.get('INSTRUME', 'DEFAULT') if instrument_name in ['IRAF/ARTDATA','',' ','N/A']: self.instrument = 'DEFAULT' else: self.instrument = instrument_name - WCS.__init__(self, ehdr, fobj=phdu, minerr=self.minerr, key=self.wcskey) + WCS.__init__(self, ehdr, fobj=phdu, minerr=self.minerr, + key=self.wcskey) # If input was a pyfits HDUList object, it's the user's # responsibility to close it, otherwise, it's closed here. if not isinstance(fobj, pyfits.HDUList): phdu.close() self.setInstrSpecKw(hdr0, ehdr) self.readIDCCoeffs(ehdr) - extname = ehdr.get('EXTNAME', "") + extname = ehdr.get('EXTNAME', '') extnum = ehdr.get('EXTVER', None) self.extname = (extname, extnum) else: @@ -262,7 +264,7 @@ class HSTWCS(WCS): if idc2hdr: for card in self._idc2hdr(): - h.update(card.key,value=card.value,comment=card.comment) + h.update(card.key,value=card.value,comment=card.comment) try: del h.ascard['RESTFRQ'] del h.ascard['RESTWAV'] @@ -273,7 +275,7 @@ class HSTWCS(WCS): h.update(card.key,value=card.value,comment=card.comment) for card in self._sip2hdr('b'): h.update(card.key,value=card.value,comment=card.comment) - + try: ap = self.sip.ap except AssertionError: diff --git a/wcsutil/mosaic.py b/wcsutil/mosaic.py index c46b898..d4ee660 100644 --- a/wcsutil/mosaic.py +++ b/wcsutil/mosaic.py @@ -12,16 +12,16 @@ from stwcs.wcsutil import altwcs def vmosaic(fnames, outwcs=None, ref_wcs=None, ext=None, extname=None, undistort=True, wkey='V', wname='VirtualMosaic', plot=False, clobber=False): """ Create a virtual mosaic using the WCS of the input images. - + Parameters ---------- - fnames: a string or a list + fnames: a string or a list a string or a list of filenames, or a list of wcsutil.HSTWCS objects outwcs: an HSTWCS object if given, represents the output tangent plane if None, the output WCS is calculated from the input observations. ref_wcs: an HSTWCS object - if output wcs is not given, this will be used as a reference for the + if output wcs is not given, this will be used as a reference for the calculation of the output WCS. If ref_wcs is None and outwcs is None, then the first observation in th einput list is used as reference. ext: an int, a tuple or a list @@ -34,21 +34,21 @@ def vmosaic(fnames, outwcs=None, ref_wcs=None, ext=None, extname=None, undistort undistort (or not) the output WCS wkey: string default: 'V' - one character A-Z to be used to record the virtual mosaic WCS as + one character A-Z to be used to record the virtual mosaic WCS as an alternate WCS in the headers of the input files. wname: string default: 'VirtualMosaic - a string to be used as a WCSNAME value for the alternate WCS representign + a string to be used as a WCSNAME value for the alternate WCS representign the virtual mosaic plot: boolean if True and matplotlib is installed will make a plot of the tangent plane and the location of the input observations. clobber: boolean - This covers the case when an alternate WCS with the requested key + This covers the case when an alternate WCS with the requested key already exists in the header of the input files. if clobber is True, it will be overwritten if False, it will compute the new one but will not write it to the headers. - + Notes ----- The algorithm is: @@ -57,7 +57,7 @@ def vmosaic(fnames, outwcs=None, ref_wcs=None, ext=None, extname=None, undistort This represents the virtual mosaic WCS. 2. For each input observation/chip, an HSTWCS object is created and its footprint on the sky is calculated (using only the four corners). - 3. For each input observation the footprint is projected on the output + 3. For each input observation the footprint is projected on the output tangent plane and the virtual WCS is recorded in the header. """ wcsobjects = readWCS(fnames, ext, extname) @@ -65,12 +65,12 @@ def vmosaic(fnames, outwcs=None, ref_wcs=None, ext=None, extname=None, undistort outwcs = outwcs.deepcopy() else: if ref_wcs != None: - outwcs = utils.output_wcs(wcsobjects, ref_wcs=ref_wcs, undistort=undistort) + outwcs = utils.output_wcs(wcsobjects, ref_wcs=ref_wcs, undistort=undistort) else: outwcs = utils.output_wcs(wcsobjects, undistort=undistort) if plot: - outc=np.array([[0.,0], [outwcs.naxis1,0], - [outwcs.naxis1, outwcs.naxis2], + outc=np.array([[0.,0], [outwcs.naxis1,0], + [outwcs.naxis1, outwcs.naxis2], [0,outwcs.naxis2], [0,0]]) plt.plot(outc[:,0], outc[:,1]) for wobj in wcsobjects: @@ -93,7 +93,7 @@ def updatehdr(fname, wcsobj, wkey, wcsname, ext=1, clobber=False): else: altwcs.deleteWCS(fname, ext=ext, wcskey='V') f = pyfits.open(fname, mode='update') - + hwcs = wcs2header(wcsobj) wcsnamekey = 'WCSNAME' + wkey f[ext].header.update(key=wcsnamekey, value=wcsname) @@ -101,11 +101,11 @@ def updatehdr(fname, wcsobj, wkey, wcsname, ext=1, clobber=False): f[ext].header.update(key=k[:7]+wkey, value=hwcs[k]) f.close() - + def wcs2header(wcsobj): - + h = wcsobj.to_header() - + if wcsobj.wcs.has_cd(): altwcs.pc2cd(h) h.update('CTYPE1', 'RA---TAN') @@ -113,7 +113,7 @@ def wcs2header(wcsobj): norient = np.rad2deg(np.arctan2(h['CD1_2'],h['CD2_2'])) #okey = 'ORIENT%s' % wkey okey = 'ORIENT' - h.update(key=okey, value=norient) + h.update(key=okey, value=norient) return h def readWCS(input, exts=None, extname=None): @@ -133,7 +133,7 @@ def readWCS(input, exts=None, extname=None): filelist = input[:] wcso = [] fomited = [] - # figure out which FITS extension(s) to use + # figure out which FITS extension(s) to use if exts == None and extname == None: #Assume it's simple FITS and the data is in the primary HDU for f in filelist: @@ -168,8 +168,8 @@ def readWCS(input, exts=None, extname=None): for f in fomited: print f return wcso - - + + def validateExt(ext): if not isinstance(ext, int) and not isinstance(ext, tuple) \ and not isinstance(ext, list): @@ -180,4 +180,4 @@ def validateExt(ext): return True -
\ No newline at end of file + diff --git a/wcsutil/wcscorr.py b/wcsutil/wcscorr.py index 9b4a39e..5a592c3 100644 --- a/wcsutil/wcscorr.py +++ b/wcsutil/wcscorr.py @@ -64,6 +64,7 @@ def init_wcscorr(input, force=False): if wcs1.idcscale is None: idc2header = False wcs_keywords = wcs1.wcs2header(idc2hdr=idc2header).keys() + # Now copy original OPUS values into table for extver in xrange(1, numsci + 1): rowind = find_wcscorr_row(wcsext.data, @@ -110,6 +111,8 @@ def init_wcscorr(input, force=False): used_wcskeys.remove('O') # Now copy remaining alternate WCSs into table + # TODO: Much of this appears to be redundant with update_wcscorr; consider + # merging them... for uwkey in used_wcskeys: if wkey == ' ': break @@ -122,7 +125,7 @@ def init_wcscorr(input, force=False): idctab = fileutil.osfn(fimg[0].header['idctab']) idcname = os.path.split(idctab)[-1] idcname = idcname[:idcname.find('_')] - wcsid = 'IDC_' + idcname + '_' + fileutil.getDate() + wcsid = 'IDC_' + idcname else: wcsid = wcshdr['WCSNAME' + uwkey] @@ -158,14 +161,17 @@ def init_wcscorr(input, force=False): if need_to_close: fimg.close() + def find_wcscorr_row(wcstab, selections): - """ Return an array of indices from the table (NOT HDU) 'wcstab' that matches the - selections specified by the user. + """ + Return an array of indices from the table (NOT HDU) 'wcstab' that matches the + selections specified by the user. - The row selection criteria must be specified as a dictionary with - column name as key and value(s) representing the valid desired row values. - For example, {'wcs_id':'OPUS','extver':2}. + The row selection criteria must be specified as a dictionary with + column name as key and value(s) representing the valid desired row values. + For example, {'wcs_id':'OPUS','extver':2}. """ + mask = None for i in selections: bmask = (wcstab.field(i) == selections[i]) @@ -176,6 +182,7 @@ def find_wcscorr_row(wcstab, selections): del bmask return mask + def archive_wcs_file(image, wcs_id=None): """ Update WCSCORR table with rows for each SCI extension to record the @@ -188,74 +195,133 @@ def archive_wcs_file(image, wcs_id=None): else: fimg = image close_image = False - numsci = fileutil.countExtn(fimg) - for extn in range(1, numsci+1): - update_wcscorr(fimg, fimg['sci',extn].header, selections=wcs_id) + + update_wcscorr(fimg, wcs_id=wcs_id) + if close_image: fimg.close() -def update_wcscorr(fimg, hdr, selections=None): + +def update_wcscorr(dest, source=None, extname='SCI', wcs_id=None): """ - Update WCSCORR table with a new row for this extension header. It + Update WCSCORR table with a new row or rows for this extension header. It copies the current set of WCS keywords as a new row of the table based on keyed WCSs as per Paper I Multiple WCS standard). + + Parameters + ---------- + dest : HDUList + The HDU list whose WCSCORR table should be appended to (the WCSCORR HDU + must already exist) + source : HDUList, optional + The HDU list containing the extension from which to extract the WCS + keywords to add to the WCSCORR table. If None, the dest is also used + as the source. + extname : str, optional + The extension name from which to take new WCS keywords. If there are + multiple extensions with that name, rows are added for each extension + version. + wcs_id : str, optional + The name of the WCS to add, as in the WCSNAMEa keyword. If + unspecified, all the WCSs in the specified extensions are added. """ - # Now update the table... - if selections is None: - # define the WCS ID for this update - wcs_key = altwcs.wcskeys(hdr)[-1] - selections = {'WCS_ID': 'TWEAK_' + fileutil.getDate(), - 'EXTVER': hdr['extver'], 'WCS_key': wcs_key} - if selections == 'IDC': - idcname = os.path.split(fileutil.osfn(fimg[0].header['idctab']))[1] - selections = {'WCS_ID': 'IDC_%s_%s' % (idcname, fileutil.getDate()), - 'EXTVER': hdr['extver'], 'WCS_key': wcs_key} + if source is None: + source = dest + + numext = fileutil.countExtn(source, extname) + if numext == 0: + raise ValueError('No %s extensions found in the source HDU list.' + % extname) + + # Current implementation assumes the same WCS keywords are in each + # extension version; if this should not be assumed then this can be + # modified... + wcs_keys = altwcs.wcskeys(source[(extname, 1)].header) + wcshdr = stwcs.wcsutil.HSTWCS(source, ext=(extname, 1)).wcs2header() + wcs_keywords = wcshdr.keys() + + if 'O' in wcs_keys: + wcs_keys.remove('O') # 'O' is reserved for original OPUS WCS + + # If we're looking for a particular wcs_id, test ahead of time that it's + # actually present in the specified extension headers + if wcs_id: + wcs_key = '' + for wcs_key in wcs_keys: + wcsname = source[(extname, 1)].header['WCSNAME' + wcs_key] + if wcs_id == wcsname: + break + else: + raise ValueError('A WCS with name %s was not found in the %s ' + '%s extension headers in the source HDU list.' + % (wcs_id, extname)) + wcs_keys = [wcs_key] # We're only interested in this one + # create new table for hdr and populate it with the newly updated values - new_table = create_wcscorr() - if hdr.has_key('extname'): - extname = hdr['extname'] - else: - extname = 'PRIMARY' - if hdr.has_key('extver'): - extver = hdr['extver'] - else: - extver = 1 - extn = (extname, extver) - wcshdr = stwcs.wcsutil.HSTWCS(fimg, ext=extn).wcs2header() - # ===> NOTE: need to add checks to insure that these IDs are unique - # Update selection column values - for key in selections: - new_table.data.field(key)[0] = selections[key] - - for key in wcshdr: - if key in new_table.data.names: - new_table.data.field(key)[0] = hdr[key] - - for key in DEFAULT_PRI_KEYS: - if key in new_table.data.names: - new_table.data.field(key)[0] = fimg[0].header[key] + new_table = create_wcscorr(numrows=len(wcs_keys) * numext) + old_table = dest['WCSCORR'] + + idx = -1 + for wcs_key in wcs_keys: + for extver in range(1, numext + 1): + extn = (extname, extver) + hdr = source[extn].header + wcsname = hdr['WCSNAME' + wcs_key] + selection = {'WCS_ID': wcsname, 'EXTVER': extver, + 'WCS_key': wcs_key} + + # Ensure that an entry for this WCS is not already in the dest + # table; if so just skip it + rowind = find_wcscorr_row(old_table.data, selection) + if np.any(rowind): + continue + + idx += 1 + + wcs = stwcs.wcsutil.HSTWCS(source, ext=extn, wcskey=wcs_key) + wcshdr = wcs.wcs2header() + + # Update selection column values + for key, val in selection.iteritems(): + new_table.data.field(key)[idx] = val + + for key in wcs_keywords: + if key in new_table.data.names: + new_table.data.field(key)[idx] = wcshdr[key + wcs_key] + + for key in DEFAULT_PRI_KEYS: + if key in new_table.data.names: + new_table.data.field(key)[idx] = source[0].header[key] + + # If idx was never incremented, no rows were added, so there's nothing else + # to do... + if idx < 0: + return + # Now, we need to merge this into the existing table - old_table = fimg['WCSCORR'] rowind = find_wcscorr_row(old_table.data, {'wcs_id': ''}) old_nrows = np.where(rowind)[0][0] + new_nrows = new_table.data.shape[0] # check to see if there is room for the new row - if (old_nrows + 1) > old_table.data.shape[0]: + if (old_nrows + new_nrows) > old_table.data.shape[0]: # if not, create a new table with 'pad_rows' new empty rows upd_table = pyfits.new_table(old_table.columns, nrows=old_table.data.shape[0] + pad_rows) else: upd_table = old_table + # Now, add for name in old_table.columns.names: - upd_table.data.field(name)[old_nrows:old_nrows+1] = \ + upd_table.data.field(name)[old_nrows:old_nrows + new_nrows] = \ new_table.data.field(name) - upd_table.header.update('TROWS', old_nrows + 1) + upd_table.header.update('TROWS', old_nrows + new_nrows) # replace old extension with newly updated table extension - fimg['WCSCORR'] = upd_table + dest['WCSCORR'] = upd_table + def restore_file_from_wcscorr(image, id='OPUS', wcskey=''): """ Copies the values of the WCS from the WCSCORR based on ID specified by user. @@ -302,6 +368,7 @@ def restore_file_from_wcscorr(image, id='OPUS', wcskey=''): if close_image: fimg.close() + def create_wcscorr(descrip=False, numrows=1, padding=0): """ Return the basic definitions for a WCSCORR table. |