casa
$Rev:20696$
|
00001 00002 # ------------------------------------------------------------------------------ 00003 00004 # caltab_convert2.py 00005 00006 # NB: 00007 # 0. I threw this code together because it's temporary, so I'm not happy with 00008 # the design. 00009 # 1. These functions are provided as a convenience to convert old-format 00010 # caltables to new-format caltables. 00011 # 2. BPOLY and GSPLINE caltables are not supported. 00012 # 3. The information transferred should be enough for most calibration purposes. 00013 # 4. Simple bugs will be fixed. If new features are required, however, you must 00014 # recalculate a new-format caltable. 00015 00016 # Modification history: 00017 # --------------------- 00018 # 2011 Jan 30 - Nick Elias, NRAO 00019 # Initial version. 00020 00021 # ------------------------------------------------------------------------------ 00022 00023 # Imports 00024 00025 import os 00026 00027 import numpy 00028 00029 from casac import casac 00030 00031 # ------------------------------------------------------------------------------ 00032 00033 # caltab_convert2 00034 00035 # NB: I threw this code together because it's temporary, so I'm not happy with 00036 # the design. 00037 00038 # NB: The type of the PARAM (and PARAMERR) columns in the new-format caltable 00039 # cannot be determined from the old-format caltable, so it must be supplied by 00040 # the user (see the inputs). It is either 'float' or 'complex'. It should be 00041 # easy to choose the correct value. Delays, WVR, etc. type calibration data 00042 # correspond to 'float'. Gains, bandpass, polarization, etc. type calibration 00043 # data correspond to 'complex'. If you are not sure what to use, ask George 00044 # Moellenbrock or Nick Elias. 00045 00046 # NB: If all of the values in the NUM_CHAN column of the old-format caltable 00047 # are 1, this function assumes that the calibration is averaged over frequency 00048 # for each spectral window. The average frequency is the median over all 00049 # channels listed in the MS. This scheme ignores user channel selection 00050 # information, which is not available. 00051 00052 # NB: The REF_ANT column in the old-format caltable (analogous to the ANTENNA2 00053 # column in the new-format caltable) is messed up, which means that I fill 00054 # ANTENNA2 with -1. Hopefully, that will not create a fatal problem. 00055 00056 # Inputs: 00057 # ------- 00058 # caltabold - The name of the old-format caltable. 00059 # ms - The name of the MS associated with the old-format caltable. 00060 # pType - The type of data in the PARAM column of the new-format caltable. 00061 # The allowed types are 'float' and 'complex'. 00062 # caltabnew - The name of the new-format caltable. It is optional. The 00063 # default is caltabold + '.new'. 00064 00065 # Modification history: 00066 # --------------------- 00067 # 2012 Jan 30 - Nick Elias, NRAO 00068 # Initial version. 00069 # 2012 Mar 26 - gmoellen: fixed header information 00070 # 2012 May 09 - gmoellen: added proper cal_desc_id->spw_id conversion 00071 # 00072 # ------------------------------------------------------------------------------ 00073 00074 def caltab_convert2( caltabold, ms, pType, caltabnew='' ): 00075 00076 # Check the inputs 00077 00078 if not os.path.exists( caltabold ): 00079 raise IOError( 'Invalid old-format caltable.' ) 00080 00081 if not os.path.exists( ms ): 00082 raise IOError( 'Invalid visibility file (MS).' ) 00083 00084 pTypeTemp = pType.strip().lower() 00085 if ( pTypeTemp != 'complex' and pTypeTemp != 'float' ): 00086 raise Exception( 'Invalid parameter type ("complex" or "float").' ) 00087 00088 if caltabnew == '': caltabnew = caltabold + '.new' 00089 if os.path.exists( caltabnew ): 00090 raise IOError( 'New-format caltable already exists.' ) 00091 00092 00093 # Open the old-format caltable and get the number of rows 00094 00095 tbOld = casac.table() 00096 tbOld.open( caltabold ) 00097 nRow = tbOld.nrows() 00098 00099 # Get spwid map from old CAL_DESC subtable 00100 tbCD = casac.table() 00101 tbCD.open( caltabold+'/CAL_DESC' ) 00102 spwmap=tbCD.getcol('SPECTRAL_WINDOW_ID')[0,:] 00103 tbCD.close() 00104 00105 # Create the empty new-format caltable with the correct number of rows 00106 00107 tbNew = casac.table() 00108 tbNew.create( caltabnew, desc_new( pTypeTemp ) ) 00109 00110 tbNew.addrows( nRow ) 00111 00112 00113 # Transfer most column information from the old-format caltable to the 00114 # new-format caltable. NB: The REF_ANT column in the old-format 00115 # caltable (analogous to the ANTENNA2 column in the new-format caltable) 00116 # is messed up, which means that I fill ANTENNA2 with -1. 00117 00118 tbNew.putcol( 'ANTENNA1', tbOld.getcol( 'ANTENNA1' ) ) 00119 tbNew.putcol( 'ANTENNA2', -1.0*numpy.ones( nRow, dtype='int' ) ) 00120 tbNew.putcol( 'FIELD_ID', tbOld.getcol( 'FIELD_ID' ) ) 00121 tbNew.putcol( 'FLAG', tbOld.getcol( 'FLAG' ) ) 00122 tbNew.putcol( 'INTERVAL', tbOld.getcol( 'INTERVAL' ) ) 00123 tbNew.putcol( 'SNR', tbOld.getcol( 'SNR' ) ) 00124 # Map CAL_DESC_ID to SPECTRAL_WINDOW_ID: 00125 tbNew.putcol( 'SPECTRAL_WINDOW_ID', spwmap[tbOld.getcol( 'CAL_DESC_ID' )] ) 00126 tbNew.putcol( 'TIME', tbOld.getcol( 'TIME' ) ) 00127 tbNew.putcol( 'WEIGHT', tbOld.getcol( 'FIT_WEIGHT' ) ) 00128 00129 00130 # Transfer the parameter column from the old-format caltable to the 00131 # new-format caltable, taking the type into account. No parameter 00132 # errors are present in the old-format caltable, so they are set to 00133 # 1.0 (+j0.0). 00134 00135 param = tbOld.getcol( 'GAIN' ) 00136 if pTypeTemp == 'float': 00137 param = param.real 00138 tbNew.putcol( 'FPARAM', param ) 00139 else: 00140 tbNew.putcol( 'CPARAM', param ) 00141 00142 tbNew.putcol( 'PARAMERR', -1.0*numpy.ones(param.shape,dtype='float') ) 00143 00144 00145 # Determine the scans and put them into the new-format caltable 00146 00147 scanTimes = get_scantimes( ms ) 00148 keys = scanTimes.keys() 00149 00150 times = tbOld.getcol( 'TIME' ) 00151 scans = numpy.zeros( 0, dtype='int' ) 00152 00153 for t in times.tolist(): 00154 00155 flag = False 00156 00157 for i in range( len(keys) ): 00158 k = keys[i] 00159 if t>=scanTimes[k]['min'] and t<scanTimes[k]['max']: 00160 flag = True 00161 scans = numpy.append( scans, k ) 00162 break 00163 if i == len(keys)-1: break 00164 l = keys[i+1] 00165 if t>=scanTimes[k]['max'] and t<scanTimes[l]['min']: 00166 flag = True 00167 scans = numpy.append( scans, l ) 00168 break 00169 00170 if not flag: scans = numpy.append( scans, -1 ) 00171 00172 tbNew.putcol( 'SCAN_NUMBER', scans ) 00173 00174 00175 # Copy the appropriate subcaltables from the MS to the new-format 00176 # caltable 00177 00178 arg = 'cp -r ' + ms + '/ANTENNA ' + caltabnew 00179 os.system( arg ) 00180 00181 arg = 'cp -r ' + ms + '/FIELD ' + caltabnew 00182 os.system( arg ) 00183 00184 # arg = 'cp -r ' + caltabold + '/CAL_HISTORY ' + caltabnew + '/HISTORY' 00185 # os.system( arg ) 00186 00187 tbHis = casac.table() 00188 tbHis.open(ms+'/HISTORY') 00189 tbHis.copy(newtablename=caltabnew+'/HISTORY',deep=True,valuecopy=True,norows=True) 00190 tbHis.close() 00191 del tbHis 00192 00193 arg = 'cp -r ' + ms + '/SPECTRAL_WINDOW ' + caltabnew \ 00194 + '/SPECTRAL_WINDOW' 00195 os.system( arg ) 00196 00197 00198 # Add the info and keywords to the main table of the new-format caltable 00199 tabinfo=tbOld.info() 00200 00201 tbNew.putinfo(tabinfo) 00202 00203 if (pTypeTemp=='complex'): 00204 tbNew.putkeyword( 'ParType', 'Complex' ) 00205 if (pTypeTemp=='float'): 00206 tbNew.putkeyword( 'ParType', 'Float' ) 00207 00208 tbNew.putkeyword( 'MSName', ms ) 00209 tbNew.putkeyword( 'VisCal', tabinfo['subType'] ) 00210 00211 polBasis = get_polbasis( ms ) 00212 tbNew.putkeyword( 'PolBasis', polBasis ) 00213 00214 tbNew.putkeyword( 'ANTENNA', 'Table: ' + caltabnew + '/ANTENNA' ) 00215 tbNew.putkeyword( 'FIELD', 'Table: ' + caltabnew + '/FIELD' ) 00216 tbNew.putkeyword( 'HISTORY', 'Table: ' + caltabnew + '/HISTORY' ) 00217 tbNew.putkeyword( 'SPECTRAL_WINDOW', 00218 'Table: ' + caltabnew + '/SPECTRAL_WINDOW' ) 00219 00220 00221 # Add the column keywords to the main table of the new-format caltable 00222 00223 colList = ['INTERVAL', 'TIME'] 00224 00225 for col in colList: 00226 colKeys = tbOld.getcolkeywords( col ) 00227 if colKeys != {}: tbNew.putcolkeywords( col, colKeys ) 00228 00229 00230 # Close the old- and new- format caltables 00231 00232 tbOld.close() 00233 del tbOld 00234 00235 tbNew.close() 00236 del tbNew 00237 00238 00239 # Get the channel ranges from the CAL_DESC subtable of the old-format 00240 # caltable 00241 00242 tbDesc = casac.table() 00243 tbDesc.open( caltabold + '/CAL_DESC' ) 00244 00245 nDesc = tbDesc.nrows() 00246 rDesc = range( nDesc ) 00247 00248 spwMap = tbDesc.getcol( 'SPECTRAL_WINDOW_ID' )[0] 00249 00250 chanMin = numpy.zeros( nDesc, dtype='int' ) 00251 chanMax = numpy.zeros( nDesc, dtype='int' ) 00252 00253 for d in rDesc: 00254 chanRange = tbDesc.getcol( 'CHAN_RANGE', startrow=d, nrow=1 ) 00255 chanMin[d] = numpy.min( chanRange[0,:,:,:][0,:,0] ) 00256 chanMax[d] = numpy.max( chanRange[1,:,:,:][0,:,0] ) 00257 00258 if numpy.all( chanMax - chanMin + 1 == 1 ): 00259 gain = True 00260 else: 00261 gain = False 00262 00263 tbDesc.close() 00264 del tbDesc 00265 00266 00267 # Modify the columns of the new-format caltable according to the 00268 # channel ranges 00269 00270 tbSPW = casac.table() 00271 tbSPW.open( caltabnew + '/SPECTRAL_WINDOW', nomodify=False ) 00272 00273 for d in rDesc: 00274 00275 s = int( spwMap[d] ) 00276 00277 nChan = int( chanMax[d] - chanMin[d] + 1 ) 00278 tbSPW.putcell( 'NUM_CHAN', s, nChan ) 00279 00280 chanFreq = tbSPW.getcell( 'CHAN_FREQ', s ) 00281 if gain: 00282 chanFreq = numpy.median( chanFreq ) 00283 else: 00284 chanFreq = chanFreq[chanMin[d]:chanMax[d]+1] 00285 tbSPW.putcell( 'CHAN_FREQ', s, chanFreq ) 00286 00287 chanWidth = tbSPW.getcell( 'CHAN_WIDTH', s ) 00288 if gain: 00289 chanWidth = numpy.sum( chanWidth ) 00290 else: 00291 chanWidth = chanWidth[chanMin[d]:chanMax[d]+1] 00292 tbSPW.putcell( 'CHAN_WIDTH', s, chanWidth ) 00293 tbSPW.putcell( 'EFFECTIVE_BW', s, chanWidth ) 00294 tbSPW.putcell( 'RESOLUTION', s, chanWidth ) 00295 00296 totalBandwidth = numpy.sum( chanWidth ) 00297 tbSPW.putcell( 'TOTAL_BANDWIDTH', s, totalBandwidth ) 00298 00299 tbSPW.close() 00300 del tbSPW 00301 00302 00303 # Return True 00304 00305 return True 00306 00307 # ------------------------------------------------------------------------------ 00308 00309 def get_scantimes( ms ): 00310 00311 # Open the MS 00312 00313 tbHandle = casac.table() 00314 tbHandle.open( ms ) 00315 00316 00317 # Get the time and scan columns 00318 00319 times = tbHandle.getcol( 'TIME' ) 00320 scans = tbHandle.getcol( 'SCAN_NUMBER' ) 00321 00322 00323 # Assign each time to the proper scan 00324 00325 d = dict() 00326 00327 for r in range( tbHandle.nrows() ): 00328 if not d.has_key( scans[r] ): d[scans[r]] = list() 00329 d[scans[r]].append( times[r] ) 00330 00331 tbHandle.close() 00332 del tbHandle 00333 00334 00335 # Get the minimum and maximum time for each scan 00336 00337 scanTimes = dict() 00338 00339 for k in d.keys(): 00340 scanTimes[k] = dict() 00341 scanTimes[k]['min'] = numpy.min( d[k] ) 00342 scanTimes[k]['max'] = numpy.max( d[k] ) 00343 00344 00345 # Return the minimum and maximum time for each scan 00346 00347 return scanTimes 00348 00349 # ------------------------------------------------------------------------------ 00350 00351 def get_polbasis( ms ): 00352 00353 # Open the MS 00354 00355 tbHandle = casac.table() 00356 tbHandle.open( ms + '/FEED' ) 00357 00358 00359 # Get the POLARIZATION_TYPE column 00360 00361 pt = tbHandle.getcol( 'POLARIZATION_TYPE' ) 00362 00363 00364 # Determine the polarization basis 00365 00366 if pt[0,:][0] == 'R' or pt[1,:][0] == 'R': 00367 polBasis = 'CIRCULAR' 00368 else: 00369 polBasis = 'LINEAR' 00370 00371 00372 # Return the polarization basis 00373 00374 return polBasis 00375 00376 # ------------------------------------------------------------------------------ 00377 00378 def desc_new( pType ): 00379 00380 desc = dict() 00381 00382 desc['ANTENNA1'] = {'comment': '', 00383 'dataManagerGroup': 'StandardStMan', 00384 'dataManagerType': 'StandardStMan', 00385 'maxlen': 0, 00386 'option': 5, 00387 'valueType': 'int'} 00388 00389 desc['ANTENNA2'] = {'comment': '', 00390 'dataManagerGroup': 'StandardStMan', 00391 'dataManagerType': 'StandardStMan', 00392 'maxlen': 0, 00393 'option': 5, 00394 'valueType': 'int'} 00395 00396 desc['FIELD_ID'] = {'comment': '', 00397 'dataManagerGroup': 'StandardStMan', 00398 'dataManagerType': 'StandardStMan', 00399 'maxlen': 0, 00400 'option': 5, 00401 'valueType': 'int'} 00402 00403 desc['FLAG'] = {'comment': '', 00404 'dataManagerGroup': 'StandardStMan', 00405 'dataManagerType': 'StandardStMan', 00406 'maxlen': 0, 00407 'ndim': -1, 00408 'option': 0, 00409 'valueType': 'boolean'} 00410 00411 desc['INTERVAL'] = {'comment': '', 00412 'dataManagerGroup': 'StandardStMan', 00413 'dataManagerType': 'StandardStMan', 00414 'maxlen': 0, 00415 'option': 5, 00416 'valueType': 'double'} 00417 00418 if pType.lower() == 'float': 00419 desc['FPARAM'] = {'comment': '', 00420 'dataManagerGroup': 'StandardStMan', 00421 'dataManagerType': 'StandardStMan', 00422 'maxlen': 0, 00423 'ndim': -1, 00424 'option': 0, 00425 'valueType': 'float'} 00426 else: 00427 desc['CPARAM'] = {'comment': '', 00428 'dataManagerGroup': 'StandardStMan', 00429 'dataManagerType': 'StandardStMan', 00430 'maxlen': 0, 00431 'ndim': -1, 00432 'option': 0, 00433 'valueType': 'complex'} 00434 00435 desc['PARAMERR'] = {'comment': '', 00436 'dataManagerGroup': 'StandardStMan', 00437 'dataManagerType': 'StandardStMan', 00438 'maxlen': 0, 00439 'ndim': -1, 00440 'option': 0, 00441 'valueType': 'float'} 00442 00443 desc['SCAN_NUMBER'] = {'comment': '', 00444 'dataManagerGroup': 'StandardStMan', 00445 'dataManagerType': 'StandardStMan', 00446 'maxlen': 0, 00447 'option': 5, 00448 'valueType': 'int'} 00449 00450 desc['SNR'] = {'comment': '', 00451 'dataManagerGroup': 'StandardStMan', 00452 'dataManagerType': 'StandardStMan', 00453 'maxlen': 0, 00454 'ndim': -1, 00455 'option': 0, 00456 'valueType': 'float'} 00457 00458 desc['SPECTRAL_WINDOW_ID'] = {'comment': '', 00459 'dataManagerGroup': 'StandardStMan', 00460 'dataManagerType': 'StandardStMan', 00461 'maxlen': 0, 00462 'option': 5, 00463 'valueType': 'int'} 00464 00465 desc['TIME'] = {'comment': '', 00466 'dataManagerGroup': 'StandardStMan', 00467 'dataManagerType': 'StandardStMan', 00468 'maxlen': 0, 00469 'option': 5, 00470 'valueType': 'double'} 00471 00472 desc['WEIGHT'] = {'comment': '', 00473 'dataManagerGroup': 'StandardStMan', 00474 'dataManagerType': 'StandardStMan', 00475 'maxlen': 0, 00476 'ndim': -1, 00477 'option': 0, 00478 'valueType': 'float'} 00479 00480 desc['_define_hypercolumn_'] = {} 00481 00482 return desc 00483