From 616fc9ebf3632fb885e139f343ccf8fc1017a21b Mon Sep 17 00:00:00 2001 From: embray Date: Tue, 5 Apr 2011 16:11:19 +0000 Subject: Various cleanup and small bug fixes. In particular, init_wcscorr() now works what I believe to be 'correctly'--it applies all existing WCSs from the SCI extension headers to the new WCSCORR table in the correct order (wcs_key w/ 'O' first; extver). git-svn-id: http://svn.stsci.edu/svn/ssb/stsci_python/stsci_python/trunk/stwcs@12393 fe389314-cf27-0410-b35b-8c050e845b92 --- wcsutil/wcscorr.py | 173 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 107 insertions(+), 66 deletions(-) (limited to 'wcsutil/wcscorr.py') diff --git a/wcsutil/wcscorr.py b/wcsutil/wcscorr.py index 1ff10c5..9b4a39e 100644 --- a/wcsutil/wcscorr.py +++ b/wcsutil/wcscorr.py @@ -16,14 +16,15 @@ DEFAULT_PRI_KEYS = ['PA_V3'] ### WCSEXT table related keyword archive functions ### def init_wcscorr(input, force=False): - """ This function will initialize the WCSCORR table if it is not already present, - and look for WCS keywords with a prefix of 'O' as the original OPUS - generated WCS as the initial row for the table or use the current WCS - keywords as initial row if no 'O' prefix keywords are found. + """ + This function will initialize the WCSCORR table if it is not already present, + and look for WCS keywords with a prefix of 'O' as the original OPUS + generated WCS as the initial row for the table or use the current WCS + keywords as initial row if no 'O' prefix keywords are found. - This function will NOT overwrite any rows already present. + This function will NOT overwrite any rows already present. - This function works on all SCI extensions at one time. + This function works on all SCI extensions at one time. """ # TODO: Create some sort of decorator or (for Python2.5) context for @@ -38,7 +39,8 @@ def init_wcscorr(input, force=False): # Verify that a WCSCORR extension does not already exist... for extn in fimg: - if extn.header.has_key('extname') and extn.header['extname'] == 'WCSCORR': + if extn.header.has_key('extname') and \ + extn.header['extname'] == 'WCSCORR': if not force: return else: @@ -49,10 +51,12 @@ def init_wcscorr(input, force=False): # create new table with more rows than needed initially to make it easier to # add new rows later - wcsext = create_wcscorr(numrows=numsci,padding=numsci*4) + wcsext = create_wcscorr(numrows=numsci, padding=numsci * 4) # Assign the correct EXTNAME value to this table extension - wcsext.header.update('TROWS',numsci*2,comment='Number of updated rows in table') - wcsext.header.update('EXTNAME','WCSCORR',comment='Table with WCS Update history') + wcsext.header.update('TROWS', numsci * 2, + comment='Number of updated rows in table') + wcsext.header.update('EXTNAME', 'WCSCORR', + comment='Table with WCS Update history') used_wcskeys = None wcs1 = stwcs.wcsutil.HSTWCS(fimg,ext=('SCI',1)) @@ -61,13 +65,15 @@ def init_wcscorr(input, force=False): 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,{'WCS_ID':'OPUS','EXTVER':extver,'WCS_key':'O'}) + for extver in xrange(1, numsci + 1): + rowind = find_wcscorr_row(wcsext.data, + {'WCS_ID': 'OPUS', 'EXTVER': extver, + 'WCS_key':'O'}) # There should only EVER be a single row for each extension with OPUS values rownum = np.where(rowind)[0][0] #print 'Archiving OPUS WCS in row number ',rownum,' in WCSCORR table for SCI,',extver - hdr = fimg['SCI',extver].header + hdr = fimg['SCI', extver].header # define set of WCS keywords which need to be managed and copied to the table if used_wcskeys is None: used_wcskeys = altwcs.wcskeys(hdr) @@ -77,8 +83,9 @@ def init_wcscorr(input, force=False): if 'O' in used_wcskeys: wkey = 'O' else: - wkey = " " - wcshdr = stwcs.wcsutil.HSTWCS(fimg,ext=('SCI',extver),wcskey=wkey).wcs2header(idc2hdr=idc2header) + wkey = ' ' + wcs = stwcs.wcsutil.HSTWCS(fimg, ext=('SCI', extver), wcskey=wkey) + wcshdr = wcs.wcs2header(idc2hdr=idc2header) for key in DEFAULT_PRI_KEYS: prihdr_keys = [] @@ -99,26 +106,28 @@ def init_wcscorr(input, force=False): # Now that we have archived the OPUS alternate WCS, remove it from the list # of used_wcskeys - if "O" in used_wcskeys: - used_wcskeys.remove("O") + if 'O' in used_wcskeys: + used_wcskeys.remove('O') # Now copy remaining alternate WCSs into table - for extver in xrange(1,numsci+1): - hdr = fimg['SCI',extver].header + for uwkey in used_wcskeys: if wkey == ' ': break - for uwkey in used_wcskeys: - wcshdr = stwcs.wcsutil.HSTWCS(fimg,ext=('SCI',extver),wcskey=uwkey).wcs2header() - if 'WCSNAME'+uwkey not in wcshdr: - idctab =fileutil.osfn(fimg[0].header['idctab']) + for extver in xrange(1, numsci + 1): + hdr = fimg['SCI', extver].header + wcs = stwcs.wcsutil.HSTWCS(fimg, ext=('SCI', extver), + wcskey=uwkey) + wcshdr = wcs.wcs2header() + if 'WCSNAME' + uwkey not in wcshdr: + 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 + '_' + fileutil.getDate() else: - wcsid = wcshdr['WCSNAME'+uwkey] + wcsid = wcshdr['WCSNAME' + uwkey] # identify next empty row - rowind = find_wcscorr_row(wcsext.data,selections={'wcs_id':' '}) + rowind = find_wcscorr_row(wcsext.data, selections={'wcs_id': ''}) rows = np.where(rowind) if len(rows[0]) > 0: rownum = np.where(rowind)[0][0] @@ -134,7 +143,7 @@ def init_wcscorr(input, force=False): # Look for standard WCS keyword values for key in wcs_keywords: if key in wcsext.data.names: - wcsext.data.field(key)[rownum] = wcshdr[key+uwkey] + wcsext.data.field(key)[rownum] = wcshdr[key + uwkey] # Now get any keywords from PRIMARY header needed for WCS updates for key in prihdr_keys: wcsext.data.field(key)[rownum] = fimg[0].header[key] @@ -168,8 +177,9 @@ def find_wcscorr_row(wcstab, selections): return mask def archive_wcs_file(image, wcs_id=None): - """ Update WCSCORR table with rows for each SCI extension to record the - newly updated WCS keyword values. + """ + Update WCSCORR table with rows for each SCI extension to record the + newly updated WCS keyword values. """ if not isinstance(image, pyfits.HDUList): @@ -184,29 +194,35 @@ def archive_wcs_file(image, wcs_id=None): if close_image: fimg.close() -def update_wcscorr(fimg,hdr,selections=None): - """ Update WCSCORR table with a new row for this extension header. It +def update_wcscorr(fimg, hdr, selections=None): + """ + Update WCSCORR table with a new row 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). """ + # 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} + 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_'+idcname+'_'+fileutil.getDate(),'EXTVER':hdr['extver'],'WCS_key':wcs_key} + selections = {'WCS_ID': 'IDC_%s_%s' % (idcname, fileutil.getDate()), + 'EXTVER': hdr['extver'], 'WCS_key': wcs_key} # 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() + 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: @@ -222,19 +238,21 @@ def update_wcscorr(fimg,hdr,selections=None): # Now, we need to merge this into the existing table old_table = fimg['WCSCORR'] - rowind = find_wcscorr_row(old_table.data,{'wcs_id':''}) + rowind = find_wcscorr_row(old_table.data, {'wcs_id': ''}) old_nrows = np.where(rowind)[0][0] # check to see if there is room for the new row if (old_nrows + 1) > 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) + 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] = new_table.data.field(name) - upd_table.header.update('TROWS',old_nrows+1) + upd_table.data.field(name)[old_nrows:old_nrows+1] = \ + new_table.data.field(name) + upd_table.header.update('TROWS', old_nrows + 1) # replace old extension with newly updated table extension fimg['WCSCORR'] = upd_table @@ -285,7 +303,8 @@ def restore_file_from_wcscorr(image, id='OPUS', wcskey=''): fimg.close() def create_wcscorr(descrip=False, numrows=1, padding=0): - """ Return the basic definitions for a WCSCORR table. + """ + Return the basic definitions for a WCSCORR table. The dtype definitions for the string columns are set to the maximum allowed so that all new elements will have the same max size which will be automatically truncated to this limit upon updating (if needed). @@ -293,44 +312,66 @@ def create_wcscorr(descrip=False, numrows=1, padding=0): The table is initialized with rows corresponding to the OPUS solution for all the 'SCI' extensions. """ + trows = numrows + padding # define initialized arrays as placeholders for column data - def_float64_zeros = np.array([0.0]*trows,dtype=np.float64) + # TODO: I'm certain there's an easier way to do this... for example, simply + # define the column names and formats, then create an empty array using + # them as a dtype, then create the new table from that array. + def_float64_zeros = np.array([0.0] * trows, dtype=np.float64) def_float64_ones = def_float64_zeros + 1.0 - def_range_1nrows = np.array(range(1,numrows+1),dtype=np.int16) - def_float_col = {'format':'D','array':def_float64_zeros.copy()} - def_float1_col = {'format':'D','array':def_float64_ones.copy()} - def_str40_col = {'format':'40A','array':np.array(['']*trows,dtype="S40")} - def_str24_col = {'format':'24A','array':np.array(['']*trows,dtype="S24")} - def_int32_col = {'format':'J','array':np.array([0]*trows,dtype=np.int32)} + def_float_col = {'format': 'D', 'array': def_float64_zeros.copy()} + def_float1_col = {'format': 'D', 'array':def_float64_ones.copy()} + def_str40_col = {'format': '40A', + 'array': np.array([''] * trows, dtype='S40')} + def_str24_col = {'format': '24A', + 'array': np.array([''] * trows, dtype='S24')} + def_int32_col = {'format': 'J', + 'array': np.array([0]*trows,dtype=np.int32)} # If more columns are needed, simply add their definitions to this list - col_names = [('CRVAL1',def_float_col),('CRVAL2',def_float_col), - ('CRPIX1',def_float_col),('CRPIX2',def_float_col), - ('CD1_1',def_float_col),('CD1_2',def_float_col), - ('CD2_1',def_float_col),('CD2_2',def_float_col), - ('CTYPE1',def_str24_col),('CTYPE2',def_str24_col), - ('ORIENTAT',def_float_col),('PA_V3',def_float_col), - ('Delta_RA',def_float_col),('Delta_Dec',def_float_col), - ('RMS_RA',def_float_col),('RMS_Dec',def_float_col), - ('Delta_Orientat',def_float_col),('Delta_Scale',def_float1_col), - ('NMatch',def_int32_col),('Catalog',def_str40_col)] + col_names = [('CRVAL1', def_float_col), ('CRVAL2', def_float_col), + ('CRPIX1', def_float_col), ('CRPIX2', def_float_col), + ('CD1_1', def_float_col), ('CD1_2', def_float_col), + ('CD2_1', def_float_col), ('CD2_2', def_float_col), + ('CTYPE1', def_str24_col), ('CTYPE2', def_str24_col), + ('ORIENTAT', def_float_col), ('PA_V3', def_float_col), + ('Delta_RA', def_float_col), ('Delta_Dec', def_float_col), + ('RMS_RA', def_float_col), ('RMS_Dec', def_float_col), + ('Delta_Orientat', def_float_col), + ('Delta_Scale', def_float1_col), + ('NMatch', def_int32_col), ('Catalog', def_str40_col)] # Define selector columns - id_col = pyfits.Column(name='WCS_ID',format='40A',array=np.array(['OPUS']*numrows+['']*padding,dtype="S24")) - extver_col = pyfits.Column(name='EXTVER',format='I',array=np.array(range(1,numrows+1),dtype=np.int16)) - wcskey_col = pyfits.Column(name='WCS_key',format='A',array=np.array(['O']*numrows+['']*padding,dtype="S")) + id_col = pyfits.Column(name='WCS_ID', format='40A', + array=np.array(['OPUS'] * numrows + [''] * padding, + dtype='S24')) + extver_col = pyfits.Column(name='EXTVER', format='I', + array=np.array(range(1, numrows + 1), + dtype=np.int16)) + wcskey_col = pyfits.Column(name='WCS_key', format='A', + array=np.array(['O'] * numrows + [''] * padding, + dtype='S')) # create list of remaining columns to be added to table - col_list = [id_col,extver_col,wcskey_col] # start with selector columns + col_list = [id_col, extver_col, wcskey_col] # start with selector columns for c in col_names: cdef = copy.deepcopy(c[1]) - col_list.append(pyfits.Column(name=c[0],format=cdef['format'],array=cdef['array'])) + col_list.append(pyfits.Column(name=c[0], format=cdef['format'], + array=cdef['array'])) if descrip: - col_list.append(pyfits.Column(name='Descrip',format='128A',array=np.array(['Original WCS computed by OPUS']*numrows,dtype="S128"))) + col_list.append( + pyfits.Column(name='Descrip', format='128A', + array=np.array( + ['Original WCS computed by OPUS'] * numrows, + dtype='S128'))) # Now create the new table from the column definitions - newtab = pyfits.new_table(pyfits.ColDefs(col_list),nrows=trows) + newtab = pyfits.new_table(pyfits.ColDefs(col_list), nrows=trows) + # The fact that setting .name is necessary should be considered a bug in + # pyfits. + # TODO: Make sure this is fixed in pyfits, then remove this + newtab.name = 'WCSCORR' return newtab -- cgit