casa
$Rev:20696$
|
00001 from taskinit import * 00002 import time 00003 import os 00004 import sys 00005 import flaghelper as fh 00006 00007 def flagcmd( 00008 vis=None, 00009 inpmode=None, 00010 inpfile=None, 00011 tablerows=None, 00012 reason=None, 00013 useapplied=None, 00014 tbuff=None, 00015 ants=None, 00016 action=None, 00017 flagbackup=None, 00018 clearall=None, 00019 rowlist=None, 00020 plotfile=None, 00021 savepars=None, 00022 outfile=None, 00023 async=None, 00024 ): 00025 00026 # 00027 # Task flagcmd 00028 # Reads flag commands from file or string and applies to MS 00029 00030 try: 00031 from xml.dom import minidom 00032 except: 00033 raise Exception, 'Failed to load xml.dom.minidom into python' 00034 00035 casalog.origin('flagcmd') 00036 00037 aflocal = casac.agentflagger() 00038 mslocal = casac.ms() 00039 mslocal2 = casac.ms() 00040 00041 try: 00042 # Use a default ntime to open the MS. The user-set ntime will be 00043 # used in the tool later 00044 ntime = 0.0 00045 00046 # Open the MS and attach it to the tool 00047 if (type(vis) == str) & os.path.exists(vis): 00048 aflocal.open(vis, ntime) 00049 else: 00050 raise Exception, \ 00051 'Visibility data set not found - please verify the name' 00052 00053 00054 # Check if vis is a cal table: 00055 # typevis = 1 --> cal table 00056 # typevis = 0 --> MS 00057 # typevis = 2 --> MMS 00058 iscal = False 00059 typevis = fh.isCalTable(vis) 00060 if typevis == 1: 00061 iscal = True 00062 00063 if action != 'apply' and action != 'list': 00064 raise ValueError, 'Unsupported action for cal tables. Only apply and list are supported.' 00065 00066 if inpmode == 'table' and isinstance(inpfile, str) and inpfile == '': 00067 raise ValueError, 'inpmode=\'table\' needs an MS as inpfile' 00068 00069 flagcmds = {} 00070 if inpmode == 'table' and fh.isCalTable(inpfile) == 0: 00071 # Read flag cmds from the MS 00072 flagcmds = readCalCmds(vis, inpfile, [], tablerows, reason, useapplied) 00073 listmode = 'cmd' 00074 00075 elif inpmode == 'list': 00076 # Read flag cmds from a list 00077 flagcmds = readCalCmds(vis, '', inpfile, [], reason, True) 00078 listmode = '' 00079 else: 00080 raise ValueError, 'Unsupported inpmode for cal tables' 00081 00082 # Apply flag cmds 00083 if flagcmds.keys().__len__() == 0: 00084 raise Exception, 'There is 0 flag cmds in input' 00085 00086 # List flags on the screen/logger 00087 if action == 'list': 00088 casalog.post('Executing action = list') 00089 listFlagCmd(myflags=flagcmds, myoutfile='', listmode=listmode) 00090 00091 elif action == 'apply': 00092 casalog.post('Executing action = apply') 00093 applyCalCmds(aflocal, vis, flagcmds, tablerows, flagbackup, outfile) 00094 00095 # Save the flag cmds to an output file 00096 if savepars: 00097 # These cmds came from the internal FLAG_CMD, only list on the screen 00098 if outfile == '': 00099 casalog.post('Saving to FLAG_CMD is not supported', 'WARN') 00100 00101 else: 00102 casalog.post('Saving commands to ' + outfile) 00103 fh.writeFlagCmd(vis, flagcmds, vrows=tablerows, 00104 applied=False, add_reason='', outfile=outfile) 00105 00106 00107 00108 else: 00109 # Input vis is an MS 00110 00111 # Get overall MS time range for later use (if needed) 00112 mslocal2.open(vis) 00113 timd = mslocal2.range(['time']) 00114 mslocal2.close() 00115 00116 ms_startmjds = timd['time'][0] 00117 ms_endmjds = timd['time'][1] 00118 t = qa.quantity(ms_startmjds, 's') 00119 t1sdata = t['value'] 00120 ms_starttime = qa.time(t, form='ymd', prec=9)[0][0] 00121 ms_startdate = qa.time(t, form=['ymd', 'no_time'])[0] 00122 t0 = qa.totime(ms_startdate + '/00:00:00.00') 00123 t0d = qa.convert(t0, 'd') 00124 t0s = qa.convert(t0, 's') 00125 t = qa.quantity(ms_endmjds, 's') 00126 t2sdata = t['value'] 00127 ms_endtime = qa.time(t, form='ymd', prec=9)[0] 00128 # NOTE: could also use values from OBSERVATION table col TIME_RANGE 00129 casalog.post('MS spans timerange ' + ms_starttime + ' to ' 00130 + ms_endtime) 00131 00132 myflagcmd = {} 00133 cmdlist = [] 00134 00135 if action == 'clear': 00136 casalog.post('Action "clear" will disregard inpmode (no reading)') 00137 # Clear flag commands from FLAG_CMD in vis 00138 msfile = vis 00139 00140 if clearall: 00141 casalog.post('Deleting all rows from FLAG_CMD in MS ' 00142 + msfile) 00143 clearFlagCmd(msfile, myrowlist=rowlist) 00144 else: 00145 casalog.post('Safety Mode: you chose not to set clearall=True, no action' 00146 ) 00147 return 00148 00149 elif inpmode == 'table': 00150 00151 casalog.post('Reading from FLAG_CMD table') 00152 # Read from FLAG_CMD table into command list 00153 if inpfile == '': 00154 msfile = vis 00155 else: 00156 msfile = inpfile 00157 00158 # Read only the selected rows for action = apply and 00159 # always read all rows with APPLIED=True for action = unapply 00160 if action == 'unapply': 00161 myflagcmd = readFromTable(msfile, useapplied=True, 00162 myreason=reason) 00163 else: 00164 myflagcmd = readFromTable(msfile, myflagrows=tablerows, 00165 useapplied=useapplied, myreason=reason) 00166 00167 listmode = 'cmd' 00168 elif inpmode == 'list': 00169 00170 # ##### TO DO: take time ranges calculation into account ?????? 00171 # Parse the input file 00172 try: 00173 if inpfile == '' or inpfile == []: 00174 casalog.post('Input list is empty', 'ERROR') 00175 00176 elif isinstance(inpfile, list): 00177 casalog.post('Reading from input list') 00178 cmdlist = inpfile 00179 00180 casalog.post('Input ' + str(cmdlist.__len__()) 00181 + ' lines from input list') 00182 # Make a FLAG_CMD compatible dictionary and select by reason 00183 myflagcmd = fh.makeDict(cmdlist, reason) 00184 00185 listmode = '' 00186 elif isinstance(inpfile, str): 00187 00188 casalog.post('Reading from input file') 00189 cmdlist = fh.readFile(inpfile) 00190 00191 # Make a FLAG_CMD compatible dictionary and select by reason 00192 myflagcmd = fh.makeDict(cmdlist, reason) 00193 listmode = 'file' 00194 00195 else: 00196 casalog.post('Unsupported input file type', 'ERROR') 00197 00198 except: 00199 00200 raise Exception, 'Error reading the input list %s' %inpfile 00201 00202 # List of command keys in dictionary 00203 vrows = myflagcmd.keys() 00204 casalog.post('Read ' + str(vrows.__len__()) 00205 + ' lines from list') 00206 00207 elif inpmode == 'xml': 00208 00209 casalog.post('Reading from Flag.xml') 00210 # Read from Flag.xml (also needs Antenna.xml) 00211 if inpfile == '': 00212 flagtable = vis 00213 else: 00214 flagtable = inpfile 00215 00216 # Actually parse table. Fail if Flag.xml or Antenna.xml is not found 00217 try: 00218 myflags = fh.readXML(flagtable, mytbuff=tbuff) 00219 except: 00220 raise Exception 00221 00222 casalog.post('%s' % myflags, 'DEBUG') 00223 00224 # Construct flags per antenna, selecting by reason if desired 00225 # Never sort! 00226 if ants != '' or reason != '': 00227 myflagcmd = selectFlags(myflags, myantenna=ants, 00228 myreason=reason, myflagsort='') 00229 else: 00230 myflagcmd = myflags 00231 00232 listmode = 'online' 00233 00234 else: 00235 raise Exception, 'Input type is not supported' 00236 00237 # Before performing any action on the flag cmds, check them! 00238 if myflagcmd.__len__() == 0: 00239 raise Exception, 'There are no flag commands in input' 00240 00241 casalog.post('Flagcmd dictionary is: %s'%myflagcmd, 'DEBUG') 00242 00243 # Specific for some actions 00244 # Get the commands as a list of strings with reason back in 00245 # TODO: maybe this is not needed anymore!!!!!!!!!!!!!!! 00246 if action == 'apply' or action == 'unapply' or action == 'list': 00247 00248 # Turn into command string list (add reason back in) 00249 mycmdlist = [] 00250 keylist = myflagcmd.keys() 00251 if keylist.__len__() > 0: 00252 for key in keylist: 00253 cmdstr = myflagcmd[key]['command'] 00254 if myflagcmd[key]['reason'] != '': 00255 cmdstr += " reason='" + myflagcmd[key]['reason' 00256 ] + "'" 00257 mycmdlist.append(cmdstr) 00258 00259 casalog.post('Extracted ' + str(mycmdlist.__len__()) 00260 + ' flag commands', 'DEBUG') 00261 00262 casalog.post('%s' % mycmdlist, 'DEBUG') 00263 casalog.post('%s' % myflagcmd, 'DEBUG') 00264 00265 # 00266 # ACTION to perform on input file 00267 # 00268 casalog.post('Executing action = ' + action) 00269 00270 # List the flag commands from inpfile on the screen 00271 # and save them or not to outfile 00272 if action == 'list': 00273 00274 # List the flag cmds on the screen 00275 listFlagCmd(myflagcmd, myoutfile='', listmode=listmode) 00276 00277 # Save the flag cmds to the outfile 00278 if savepars: 00279 # These cmds came from the internal FLAG_CMD, only list on the screen 00280 if outfile == '': 00281 if inpmode == 'table' and inpfile == '': 00282 pass 00283 else: 00284 casalog.post('Saving commands to FLAG_CMD') 00285 fh.writeFlagCmd(vis, myflagcmd, vrows=keylist, 00286 applied=False, add_reason='', outfile='') 00287 else: 00288 casalog.post('Saving commands to ' + outfile) 00289 fh.writeFlagCmd(vis, myflagcmd, vrows=keylist, 00290 applied=False, add_reason='', outfile=outfile) 00291 00292 elif action == 'apply' or action == 'unapply': 00293 00294 # Apply/Unapply the flag commands to the data 00295 apply = True 00296 00297 # Preserve the order of the cmd list. When unapply, the order 00298 # should not be preserved, because the unapply list should run 00299 # before the re-apply list in the FlagAgentList.apply() method 00300 preserve_order = True 00301 00302 # Get the list of parameters 00303 cmdlist = [] 00304 cmdkeys = myflagcmd.keys() 00305 for key in cmdkeys: 00306 cmdline = myflagcmd[key]['command'] 00307 cmdlist.append(cmdline) 00308 00309 # Select the data 00310 00311 # Select a loose union of the data selection from the list. 00312 # The loose union will be calculated for field and spw only. 00313 # Antenna, correlation and timerange should be handled by the agent 00314 unionpars = {} 00315 if cmdlist.__len__() > 1: 00316 unionpars = fh.getUnion(vis, myflagcmd) 00317 if len(unionpars.keys()) > 0: 00318 casalog.post('Pre-selecting a subset of the MS: ') 00319 casalog.post('%s' % unionpars) 00320 else: 00321 casalog.post('Iterating through the entire MS') 00322 00323 elif cmdlist.__len__() == 1: 00324 00325 # Get all the selection parameters, but set correlation to '' 00326 cmd0 = myflagcmd[cmdkeys[0]]['command'] 00327 unionpars = fh.getSelectionPars(cmd0) 00328 casalog.post('The selected subset of the MS will be: ') 00329 casalog.post('%s' % unionpars) 00330 00331 aflocal.selectdata(unionpars) 00332 00333 # Parse the agents parameters 00334 if action == 'unapply': 00335 apply = False 00336 preserve_order = False 00337 00338 list2save = fh.setupAgent(aflocal, myflagcmd, tablerows, 00339 apply, True) 00340 if list2save == {}: 00341 raise Exception, 'Cannot setup the agent(s)' 00342 00343 # Initialize the Agents 00344 aflocal.init() 00345 00346 # Backup the flags before running 00347 if flagbackup: 00348 fh.backupFlags(aflocal, msfile='', prename='flagcmd') 00349 00350 # Run the tool 00351 stats = aflocal.run(True, preserve_order) 00352 00353 aflocal.done() 00354 00355 # Update the APPLIED column 00356 valid_rows = list2save.keys() 00357 if valid_rows.__len__ > 0: 00358 00359 if savepars: 00360 # These flags came from internal FLAG_CMD. Always update APPLIED 00361 if outfile == '': 00362 if inpmode == 'table' and inpfile == '': 00363 updateTable(vis, mycol='APPLIED', 00364 myval=apply, myrowlist=valid_rows) 00365 else: 00366 # save to FLAG_CMD 00367 casalog.post('Saving commands to FLAG_CMD') 00368 fh.writeFlagCmd(vis, myflagcmd, 00369 vrows=valid_rows, applied=apply, 00370 add_reason='', outfile='') 00371 else: 00372 00373 # Save to a file 00374 # Still need to update APPLIED column 00375 if inpmode == 'table' and inpfile == '': 00376 updateTable(vis, mycol='APPLIED', 00377 myval=apply, myrowlist=valid_rows) 00378 00379 casalog.post('Saving commands to file ' 00380 + outfile) 00381 fh.writeFlagCmd(vis, myflagcmd, 00382 vrows=valid_rows, applied=apply, 00383 add_reason='', outfile=outfile) 00384 else: 00385 00386 # Do not save cmds but maybe update APPLIED 00387 if inpmode == 'table' and inpfile == '': 00388 updateTable(vis, mycol='APPLIED', myval=apply, 00389 myrowlist=valid_rows) 00390 else: 00391 00392 casalog.post('There are no valid commands to save', 00393 'WARN') 00394 00395 elif action == 'plot': 00396 00397 keylist = myflagcmd.keys() 00398 if keylist.__len__() > 0: 00399 # Plot flag commands from FLAG_CMD or xml 00400 casalog.post('Warning: will only reliably plot individual per-antenna flags' 00401 ) 00402 newplotflags(myflagcmd, plotfile, t1sdata, t2sdata) 00403 else: 00404 casalog.post('Warning: empty flag dictionary, nothing to plot' 00405 ) 00406 elif action == 'extract': 00407 # Output flag dictionary 00408 casalog.post('Returning extracted dictionary') 00409 return myflagcmd 00410 00411 00412 except Exception, instance: 00413 00414 aflocal.done() 00415 casalog.post('%s' % instance, 'ERROR') 00416 raise 00417 00418 # write history 00419 if not iscal: 00420 try: 00421 mslocal.open(vis, nomodify=False) 00422 mslocal.writehistory(message='taskname = flagcmd', 00423 origin='flagcmd') 00424 mslocal.writehistory(message='vis = "' + str(vis) + '"', 00425 origin='flagcmd') 00426 mslocal.writehistory(message='action = "' + str(action) + '"' 00427 , origin='flagcmd') 00428 00429 mslocal.writehistory(message='inpmode = "' + str(inpmode) + '"' 00430 , origin='flagcmd') 00431 00432 mslocal.close() 00433 except: 00434 casalog.post('Cannot open vis for history, ignoring', 'WARN') 00435 00436 return 00437 00438 00439 # ************************************************************************ 00440 # Helper Functions 00441 # ************************************************************************ 00442 00443 00444 def readFromTable( 00445 msfile, 00446 myflagrows=[], 00447 useapplied=True, 00448 myreason='any', 00449 ): 00450 '''Read flag commands from rows of the FLAG_CMD table of msfile 00451 If useapplied=False then include only rows with APPLIED=False 00452 If myreason is anything other than '', then select on that''' 00453 00454 # 00455 # Return flagcmd structure: 00456 # 00457 # The flagcmd key is the integer row number from FLAG_CMD 00458 # 00459 # Dictionary structure: 00460 # key : 'id' (string) 00461 # 'mode' (string) flag mode '','clip','shadow','quack' 00462 # 'antenna' (string) 00463 # 'timerange' (string) 00464 # 'reason' (string) 00465 # 'time' (float) in mjd seconds 00466 # 'interval' (float) in mjd seconds 00467 # 'cmd' (string) string (for COMMAND col in FLAG_CMD) 00468 # 'type' (string) 'FLAG' / 'UNFLAG' 00469 # 'applied' (bool) set to True here on read-in 00470 # 'level' (int) set to 0 here on read-in 00471 # 'severity' (int) set to 0 here on read-in 00472 00473 # Open and read columns from FLAG_CMD 00474 mstable = msfile + '/FLAG_CMD' 00475 00476 # Note, tb.getcol doesn't allow random row access, read all 00477 00478 try: 00479 tb.open(mstable) 00480 f_time = tb.getcol('TIME') 00481 f_interval = tb.getcol('INTERVAL') 00482 f_type = tb.getcol('TYPE') 00483 f_reas = tb.getcol('REASON') 00484 f_level = tb.getcol('LEVEL') 00485 f_severity = tb.getcol('SEVERITY') 00486 f_applied = tb.getcol('APPLIED') 00487 f_cmd = tb.getcol('COMMAND') 00488 tb.close() 00489 except: 00490 casalog.post('Error reading table ' + mstable, 'ERROR') 00491 raise Exception 00492 00493 nrows = f_time.__len__() 00494 00495 myreaslist = [] 00496 00497 # Parse myreason 00498 if type(myreason) == str: 00499 if myreason != 'any': 00500 myreaslist.append(myreason) 00501 elif type(myreason) == list: 00502 myreaslist = myreason 00503 else: 00504 casalog.post('Cannot read reason; it contains unknown variable types' 00505 , 'ERROR') 00506 return 00507 00508 myflagcmd = {} 00509 if nrows > 0: 00510 nflagd = 0 00511 if myflagrows.__len__() > 0: 00512 rowlist = myflagrows 00513 else: 00514 rowlist = range(nrows) 00515 # Prune rows if needed 00516 if not useapplied: 00517 rowl = [] 00518 for i in rowlist: 00519 if not f_applied[i]: 00520 rowl.append(i) 00521 rowlist = rowl 00522 if myreaslist.__len__() > 0: 00523 rowl = [] 00524 for i in rowlist: 00525 if myreaslist.count(f_reas[i]) > 0: 00526 rowl.append(i) 00527 rowlist = rowl 00528 00529 for i in rowlist: 00530 flagd = {} 00531 cmd = f_cmd[i] 00532 if cmd == '': 00533 casalog.post('Ignoring empty COMMAND string', 'WARN') 00534 continue 00535 00536 # Extract antenna and timerange strings from cmd 00537 antstr = '' 00538 timstr = '' 00539 00540 flagd['id'] = str(i) 00541 flagd['antenna'] = '' 00542 flagd['mode'] = '' 00543 flagd['time'] = f_time[i] 00544 flagd['interval'] = f_interval[i] 00545 flagd['type'] = f_type[i] 00546 flagd['reason'] = f_reas[i] 00547 flagd['level'] = f_level[i] 00548 flagd['severity'] = f_severity[i] 00549 flagd['applied'] = f_applied[i] 00550 00551 # If shadow, remove the addantenna dictionary 00552 if cmd.__contains__('shadow') \ 00553 and cmd.__contains__('addantenna'): 00554 i0 = cmd.rfind('addantenna') 00555 if cmd[i0 + 11] == '{': 00556 # It is a dictionary. Remove it from line 00557 i1 = cmd.rfind('}') 00558 antpar = cmd[i0 + 11:i1 + 1] 00559 temp = cmd[i0:i1 + 1] 00560 newcmd = cmd.replace(temp, '') 00561 antpardict = fh.convertStringToDict(antpar) 00562 flagd['addantenna'] = antpardict 00563 cmd = newcmd 00564 00565 flagd['command'] = cmd 00566 00567 keyvlist = cmd.split() 00568 if keyvlist.__len__() > 0: 00569 for keyv in keyvlist: 00570 try: 00571 (xkey, val) = keyv.split('=') 00572 except: 00573 print 'Error: not key=value pair for ' + keyv 00574 break 00575 xval = val 00576 # strip quotes from value 00577 if xval.count("'") > 0: 00578 xval = xval.strip("'") 00579 if xval.count('"') > 0: 00580 xval = xval.strip('"') 00581 00582 if xkey == 'mode': 00583 flagd['mode'] = xval 00584 elif xkey == 'timerange': 00585 timstr = xval 00586 elif xkey == 'antenna': 00587 flagd['antenna'] = xval 00588 elif xkey == 'id': 00589 flagd['id'] = xval 00590 00591 # STM 2010-12-08 Do not put timerange if not in command 00592 # if timstr=='': 00593 # .... # Construct timerange from time,interval 00594 # .... centertime = f_time[i] 00595 # .... interval = f_interval[i] 00596 # .... startmjds = centertime - 0.5*interval 00597 # .... t = qa.quantity(startmjds,'s') 00598 # .... starttime = qa.time(t,form="ymd",prec=9) 00599 # .... endmjds = centertime + 0.5*interval 00600 # .... t = qa.quantity(endmjds,'s') 00601 # .... endtime = qa.time(t,form="ymd",prec=9) 00602 # .... timstr = starttime+'~'+endtime 00603 flagd['timerange'] = timstr 00604 # Keep original key index, might need this later 00605 myflagcmd[i] = flagd 00606 nflagd += 1 00607 casalog.post('Read ' + str(nflagd) 00608 + ' rows from FLAG_CMD table in ' + msfile) 00609 else: 00610 casalog.post('FLAG_CMD table in %s is empty, no flags extracted' 00611 % msfile, 'WARN') 00612 00613 return myflagcmd 00614 00615 00616 def readFromCmd(cmdlist, ms_startmjds, ms_endmjds): 00617 '''Read the parameters from a list of commands''' 00618 00619 # Read a list of strings and return a dictionary of parameters 00620 myflagd = {} 00621 nrows = cmdlist.__len__() 00622 if nrows == 0: 00623 casalog.post('WARNING: empty flag command list', 'WARN') 00624 return myflagd 00625 00626 t = qa.quantity(ms_startmjds, 's') 00627 ms_startdate = qa.time(t, form=['ymd', 'no_time'])[0] 00628 t0 = qa.totime(ms_startdate + '/00:00:00.0') 00629 # t0d = qa.convert(t0,'d') 00630 t0s = qa.convert(t0, 's') 00631 00632 ncmds = 0 00633 for i in range(nrows): 00634 cmdstr = cmdlist[i] 00635 # break string into key=val sets 00636 keyvlist = cmdstr.split() 00637 if keyvlist.__len__() > 0: 00638 ant = '' 00639 timstr = '' 00640 tim = 0.5 * (ms_startmjds + ms_endmjds) 00641 intvl = ms_endmjds - ms_startmjds 00642 reas = '' 00643 cmd = '' 00644 fid = str(i) 00645 mode = '' 00646 typ = 'FLAG' 00647 appl = False 00648 levl = 0 00649 sevr = 0 00650 fmode = '' 00651 for keyv in keyvlist: 00652 # check for comment character # 00653 if keyv.count('#') > 0: 00654 # break out of loop parsing keyvals 00655 break 00656 try: 00657 (xkey, val) = keyv.split('=') 00658 except: 00659 print 'Not a key=val pair: ' + keyv 00660 break 00661 xval = val 00662 # Use eval to deal with conversion from string 00663 # xval = eval(val) 00664 # strip quotes from value (if still a string) 00665 if type(xval) == str: 00666 if xval.count("'") > 0: 00667 xval = xval.strip("'") 00668 if xval.count('"') > 0: 00669 xval = xval.strip('"') 00670 00671 # Strip these out of command string 00672 if xkey == 'reason': 00673 reas = xval 00674 elif xkey == 'applied': 00675 appl = False 00676 if xval == 'True': 00677 appl = True 00678 elif xkey == 'level': 00679 levl = int(xval) 00680 elif xkey == 'severity': 00681 sevr = int(xval) 00682 elif xkey == 'time': 00683 tim = xval 00684 elif xkey == 'interval': 00685 intvl = xval 00686 else: 00687 # Extract (but keep in string) 00688 if xkey == 'timerange': 00689 timstr = xval 00690 # Extract TIME,INTERVAL 00691 try: 00692 (startstr, endstr) = timstr.split('~') 00693 except: 00694 if timstr.count('~') == 0: 00695 # print 'Assuming a single start time ' 00696 startstr = timstr 00697 endstr = timstr 00698 else: 00699 print 'Not a start~end range: ' + timstr 00700 print "ERROR: too may ~'s " 00701 raise Exception, 'Error parsing ' \ 00702 + timstr 00703 t = qa.totime(startstr) 00704 starts = qa.convert(t, 's') 00705 if starts['value'] < 1.E6: 00706 # assume a time offset from ref 00707 starts = qa.add(t0s, starts) 00708 startmjds = starts['value'] 00709 if endstr == '': 00710 endstr = startstr 00711 t = qa.totime(endstr) 00712 ends = qa.convert(t, 's') 00713 if ends['value'] < 1.E6: 00714 # assume a time offset from ref 00715 ends = qa.add(t0s, ends) 00716 endmjds = ends['value'] 00717 tim = 0.5 * (startmjds + endmjds) 00718 intvl = endmjds - startmjds 00719 elif xkey == 'antenna': 00720 00721 ant = xval 00722 elif xkey == 'id': 00723 fid = xval 00724 elif xkey == 'unflag': 00725 if xval == 'True': 00726 typ = 'UNFLAG' 00727 elif xkey == 'mode': 00728 fmode = xval 00729 cmd = cmd + ' ' + keyv 00730 # Done parsing keyvals 00731 # Make sure there is a non-blank command string after reason/id extraction 00732 if cmd != '': 00733 flagd = {} 00734 flagd['id'] = fid 00735 flagd['mode'] = fmode 00736 flagd['antenna'] = ant 00737 flagd['timerange'] = timstr 00738 flagd['reason'] = reas 00739 flagd['command'] = cmd 00740 flagd['time'] = tim 00741 flagd['interval'] = intvl 00742 flagd['type'] = typ 00743 flagd['level'] = levl 00744 flagd['severity'] = sevr 00745 flagd['applied'] = appl 00746 # Insert into main dictionary 00747 myflagd[ncmds] = flagd 00748 ncmds += 1 00749 00750 casalog.post('Parsed ' + str(ncmds) + ' flag command strings') 00751 00752 return myflagd 00753 00754 00755 def readFromFile( 00756 cmdlist, 00757 ms_startmjds, 00758 ms_endmjds, 00759 myreason='', 00760 ): 00761 '''Parse list of flag command strings and return dictionary of flagcmds 00762 Inputs: 00763 cmdlist (list,string) list of command strings (default for TIME,INTERVAL) 00764 ms_startmjds (float) starting mjd (sec) of MS (default for TIME,INTERVAL) 00765 ms_endmjds (float) ending mjd (sec) of MS''' 00766 00767 # 00768 # Usage: myflagcmd = getflags(cmdlist) 00769 # 00770 # Dictionary structure: 00771 # fid : 'id' (string) 00772 # 'mode' (string) flag mode '','clip','shadow','quack' 00773 # 'antenna' (string) 00774 # 'timerange' (string) 00775 # 'reason' (string) 00776 # 'time' (float) in mjd seconds 00777 # 'interval' (float) in mjd seconds 00778 # 'cmd' (string) string (for COMMAND col in FLAG_CMD) 00779 # 'type' (string) 'FLAG' / 'UNFLAG' 00780 # 'applied' (bool) set to True here on read-in 00781 # 'level' (int) set to 0 here on read-in 00782 # 'severity' (int) set to 0 here on read-in 00783 # 00784 # v3.2 Updated STM 2010-12-03 (3.2.0) handle comments # again 00785 # v3.2 Updated STM 2010-12-08 (3.2.0) bug fixes in flagsort use, parsing 00786 # v3.3 Updated STM 2010-12-20 (3.2.0) bug fixes parsing errors 00787 # 00788 00789 myflagd = {} 00790 nrows = cmdlist.__len__() 00791 if nrows == 0: 00792 casalog.post('WARNING: empty flag command list', 'WARN') 00793 return myflagd 00794 00795 # Parse the reason 00796 reasonlist = [] 00797 if type(myreason) == str: 00798 if myreason != '': 00799 reasonlist.append(myreason) 00800 elif type(myreason) == list: 00801 reasonlist = myreason 00802 else: 00803 casalog.post('Cannot read reason; it contains unknown variable types' 00804 , 'ERROR') 00805 return 00806 00807 t = qa.quantity(ms_startmjds, 's') 00808 ms_startdate = qa.time(t, form=['ymd', 'no_time'])[0] 00809 t0 = qa.totime(ms_startdate + '/00:00:00.0') 00810 # t0d = qa.convert(t0,'d') 00811 t0s = qa.convert(t0, 's') 00812 00813 rowlist = [] 00814 00815 # IMPLEMENT THIS LATER 00816 # First select by reason. Simple selection... 00817 # if reasonlist.__len__() > 0: 00818 # for i in range(nrows): 00819 # cmdstr = cmdlist[i] 00820 # keyvlist = cmdstr.split() 00821 # if keyvlist.__len__() > 0: 00822 # for keyv in keyvlist: 00823 # (xkey, xval) = keyv.split('=') 00824 # 00825 # if type(xval) == str: 00826 # if xval.count("'") > 0: 00827 # xval = xval.strip("'") 00828 # if xval.count('"') > 0: 00829 # xval = xval.strip('"') 00830 # 00831 # if xkey == 'reason': 00832 # if reasonlist.count(xval) > 0 00833 # else: 00834 rowlist = range(nrows) 00835 00836 # Now read the only the commands from the file that satisfies the reason selection 00837 00838 ncmds = 0 00839 # for i in range(nrows): 00840 for i in rowlist: 00841 cmdstr = cmdlist[i] 00842 00843 # break string into key=val sets 00844 keyvlist = cmdstr.split() 00845 if keyvlist.__len__() > 0: 00846 ant = '' 00847 timstr = '' 00848 tim = 0.5 * (ms_startmjds + ms_endmjds) 00849 intvl = ms_endmjds - ms_startmjds 00850 reas = '' 00851 cmd = '' 00852 fid = str(i) 00853 mode = '' 00854 typ = 'FLAG' 00855 appl = False 00856 levl = 0 00857 sevr = 0 00858 fmode = '' 00859 for keyv in keyvlist: 00860 # check for comment character # 00861 if keyv.count('#') > 0: 00862 # break out of loop parsing keyvals 00863 break 00864 try: 00865 (xkey, val) = keyv.split('=') 00866 except: 00867 print 'Not a key=val pair: ' + keyv 00868 break 00869 xval = val 00870 # Use eval to deal with conversion from string 00871 # xval = eval(val) 00872 # strip quotes from value (if still a string) 00873 if type(xval) == str: 00874 if xval.count("'") > 0: 00875 xval = xval.strip("'") 00876 if xval.count('"') > 0: 00877 xval = xval.strip('"') 00878 00879 # Strip these out of command string 00880 if xkey == 'reason': 00881 reas = xval 00882 elif xkey == 'applied': 00883 00884 appl = False 00885 if xval == 'True': 00886 appl = True 00887 elif xkey == 'level': 00888 levl = int(xval) 00889 elif xkey == 'severity': 00890 sevr = int(xval) 00891 elif xkey == 'time': 00892 tim = xval 00893 elif xkey == 'interval': 00894 intvl = xval 00895 else: 00896 # Extract (but keep in string) 00897 if xkey == 'timerange': 00898 timstr = xval 00899 # Extract TIME,INTERVAL 00900 try: 00901 (startstr, endstr) = timstr.split('~') 00902 except: 00903 if timstr.count('~') == 0: 00904 # print 'Assuming a single start time ' 00905 startstr = timstr 00906 endstr = timstr 00907 else: 00908 print 'Not a start~end range: ' + timstr 00909 print "ERROR: too may ~'s " 00910 raise Exception, 'Error parsing ' \ 00911 + timstr 00912 t = qa.totime(startstr) 00913 starts = qa.convert(t, 's') 00914 if starts['value'] < 1.E6: 00915 # assume a time offset from ref 00916 starts = qa.add(t0s, starts) 00917 startmjds = starts['value'] 00918 if endstr == '': 00919 endstr = startstr 00920 t = qa.totime(endstr) 00921 ends = qa.convert(t, 's') 00922 if ends['value'] < 1.E6: 00923 # assume a time offset from ref 00924 ends = qa.add(t0s, ends) 00925 endmjds = ends['value'] 00926 tim = 0.5 * (startmjds + endmjds) 00927 intvl = endmjds - startmjds 00928 elif xkey == 'antenna': 00929 00930 ant = xval 00931 elif xkey == 'id': 00932 fid = xval 00933 elif xkey == 'unflag': 00934 if xval == 'True': 00935 typ = 'UNFLAG' 00936 elif xkey == 'mode': 00937 fmode = xval 00938 cmd = cmd + ' ' + keyv 00939 # Done parsing keyvals 00940 # Make sure there is a non-blank command string after reason/id extraction 00941 if cmd != '': 00942 flagd = {} 00943 flagd['id'] = fid 00944 flagd['mode'] = fmode 00945 flagd['antenna'] = ant 00946 flagd['timerange'] = timstr 00947 flagd['reason'] = reas 00948 flagd['command'] = cmd 00949 flagd['time'] = tim 00950 flagd['interval'] = intvl 00951 flagd['type'] = typ 00952 flagd['level'] = levl 00953 flagd['severity'] = sevr 00954 flagd['applied'] = appl 00955 # Insert into main dictionary 00956 myflagd[ncmds] = flagd 00957 ncmds += 1 00958 00959 casalog.post('Parsed ' + str(ncmds) + ' flag command strings') 00960 00961 return myflagd 00962 00963 00964 def updateTable( 00965 msfile, 00966 mycol='', 00967 myval=None, 00968 myrowlist=[], 00969 ): 00970 '''Update commands in myrowlist of the FLAG_CMD table of msfile 00971 Usage: updateflagcmd(msfile,myrow,mycol,myval)''' 00972 00973 # Example: 00974 # 00975 # updateflagcmd(msfile,mycol='APPLIED',myval=True) 00976 # Mark all rows as APPLIED=True 00977 # 00978 # updateflagcmd(msfile,mycol='APPLIED',myval=True,myrowlist=[0,1,2]) 00979 # Mark rows 0,1,2 as APPLIED=True 00980 # 00981 00982 if mycol == '': 00983 casalog.post('WARNING: No column to was specified to update; doing nothing' 00984 , 'WARN') 00985 return 00986 00987 # Open and read columns from FLAG_CMD 00988 mstable = msfile + '/FLAG_CMD' 00989 try: 00990 tb.open(mstable, nomodify=False) 00991 except: 00992 raise Exception, 'Error opening table ' + mstable 00993 00994 nrows = int(tb.nrows()) 00995 00996 # Check against allowed colnames 00997 colnames = tb.colnames() 00998 if colnames.count(mycol) < 1: 00999 casalog.post('Error: column mycol=' + mycol + ' not one of: ' 01000 + str(colnames)) 01001 return 01002 01003 nlist = myrowlist.__len__() 01004 01005 if nlist > 0: 01006 rowlist = myrowlist 01007 else: 01008 01009 rowlist = range(nrows) 01010 nlist = nrows 01011 01012 if nlist > 0: 01013 try: 01014 tb.putcell(mycol, rowlist, myval) 01015 except: 01016 raise Exception, 'Error updating FLAG_CMD column ' + mycol \ 01017 + ' to value ' + str(myval) 01018 01019 casalog.post('Updated ' + str(nlist) 01020 + ' rows of FLAG_CMD table in MS') 01021 tb.close() 01022 01023 01024 def listFlagCmd( 01025 myflags=None, 01026 myantenna='', 01027 myreason='', 01028 myoutfile='', 01029 listmode='', 01030 ): 01031 '''List flags in myflags dictionary 01032 01033 Format according to listmode: 01034 ='' do nothing 01035 ='file' Format for flag command strings 01036 ='cmd' Format for FLAG_CMD flags 01037 ='online' Format for online flags''' 01038 01039 # 01040 # Dictionary structure: 01041 # fid : 'id' (string) 01042 # 'mode' (string) flag mode '','clip','shadow','quack' 01043 # 'antenna' (string) 01044 # 'timerange' (string) 01045 # 'reason' (string) 01046 # 'time' (float) in mjd seconds 01047 # 'interval' (float) in mjd seconds 01048 # 'cmd' (string) string (for COMMAND col in FLAG_CMD) 01049 # 'type' (string) 'FLAG' / 'UNFLAG' 01050 # 'applied' (bool) 01051 # 'level' (int) 01052 # 'severity' (int) 01053 # 01054 01055 useid = False 01056 doterm = False 01057 01058 if myoutfile != '': 01059 try: 01060 lfout = open(myoutfile, 'w') 01061 except: 01062 raise Exception, 'Error opening list output file ' \ 01063 + myoutfile 01064 01065 keylist = myflags.keys() 01066 if keylist.__len__() == 0: 01067 casalog.post('There are no flags to list', 'WARN') 01068 return 01069 # Sort keys 01070 # keylist.sort 01071 01072 # Set up any selection 01073 if myantenna != '': 01074 casalog.post('Selecting flags by antenna="' + str(myantenna) 01075 + '"') 01076 myantlist = myantenna.split(',') 01077 01078 if myreason != '': 01079 casalog.post('Selecting flags by reason="' + str(myreason) + '"' 01080 ) 01081 myreaslist = myreason.split(',') 01082 01083 if listmode == 'online': 01084 phdr = '%8s %12s %8s %32s %48s' % ('Key', 'FlagID', 'Antenna', 01085 'Reason', 'Timerange') 01086 elif listmode == 'cmd': 01087 phdr = '%8s %45s %32s %6s %7s %3s %3s %s' % ( 01088 'Row', 01089 'Timerange', 01090 'Reason', 01091 'Type', 01092 'Applied', 01093 'Level', 01094 'Severity', 01095 'Command', 01096 ) 01097 elif listmode == 'file': 01098 phdr = '%8s %32s %s' % ('Key', 'Reason', 'Command') 01099 else: 01100 return 01101 01102 if myoutfile != '': 01103 # list to output file 01104 print >> lfout, phdr 01105 else: 01106 # list to logger and screen 01107 if doterm: 01108 print phdr 01109 01110 casalog.post(phdr) 01111 01112 # Loop over flags 01113 for key in keylist: 01114 fld = myflags[key] 01115 # Get fields 01116 skey = str(key) 01117 if fld.has_key('id') and useid: 01118 fid = fld['id'] 01119 else: 01120 fid = str(key) 01121 if fld.has_key('antenna'): 01122 ant = fld['antenna'] 01123 else: 01124 ant = 'Unset' 01125 if fld.has_key('timerange'): 01126 timr = fld['timerange'] 01127 else: 01128 timr = 'Unset' 01129 if fld.has_key('reason'): 01130 reas = fld['reason'] 01131 else: 01132 reas = 'Unset' 01133 if fld.has_key('command'): 01134 cmd = fld['command'] 01135 if fld.has_key('addantenna'): 01136 addantenna = fld['addantenna'] 01137 cmd = cmd + ' addantenna=' + str(addantenna) 01138 else: 01139 01140 cmd = 'Unset' 01141 if fld.has_key('type'): 01142 typ = fld['type'] 01143 else: 01144 typ = 'FLAG' 01145 if fld.has_key('level'): 01146 levl = str(fld['level']) 01147 else: 01148 levl = '0' 01149 if fld.has_key('severity'): 01150 sevr = str(fld['severity']) 01151 else: 01152 sevr = '0' 01153 if fld.has_key('applied'): 01154 appl = str(fld['applied']) 01155 else: 01156 appl = 'Unset' 01157 01158 # Print out listing 01159 if myantenna == '' or myantlist.count(ant) > 0: 01160 if myreason == '' or myreaslist.count(reas) > 0: 01161 if listmode == 'online': 01162 pstr = '%8s %12s %8s %32s %48s' % (skey, fid, ant, 01163 reas, timr) 01164 elif listmode == 'cmd': 01165 pstr = '%8s %45s %32s %6s %7s %3s %3s %s' % ( 01166 skey, 01167 timr, 01168 reas, 01169 typ, 01170 appl, 01171 levl, 01172 sevr, 01173 cmd, 01174 ) 01175 else: 01176 pstr = '%8s %32s %s' % (skey, reas, cmd) 01177 if myoutfile != '': 01178 # list to output file 01179 print >> lfout, pstr 01180 else: 01181 # list to logger and screen 01182 if doterm: 01183 print pstr 01184 casalog.post(pstr) 01185 if myoutfile != '': 01186 lfout.close() 01187 01188 01189 01190 01191 def selectFlags( 01192 myflags=None, 01193 myantenna='', 01194 myreason='any', 01195 myflagsort='', 01196 ): 01197 01198 # 01199 # Return dictionary of input flags using selection by antenna/reason 01200 # and grouped/sorted by flagsort. 01201 # 01202 # selectFlags: Return dictionary of flags using selection by antenna/reason 01203 # and grouped/sorted by flagsort. 01204 # myflags (dictionary) input flag dictionary (e.g. from readflagxml 01205 # myantenna (string) selection by antenna(s) 01206 # myreason (string) selection by reason(s) 01207 # myflagsort (string) toggle for flag group/sort 01208 # 01209 # Usage: myflagd = selectFlags(myflags,antenna,reason,flagsort) 01210 # 01211 # Dictionary structure: 01212 # fid : 'id' (string) 01213 # 'mode' (string) flag mode '','clip','shadow','quack','online' 01214 # 'antenna' (string) 01215 # 'timerange' (string) 01216 # 'reason' (string) 01217 # 'time' (float) in mjd seconds 01218 # 'interval' (float) in mjd seconds 01219 # 'cmd' (string) command string (for COMMAND col in FLAG_CMD) 01220 # 'type' (string) 'FLAG' / 'UNFLAG' 01221 # 'applied' (bool) set to True here on read-in 01222 # 'level' (int) set to 0 here on read-in 01223 # 'severity' (int) set to 0 here on read-in 01224 # 01225 # NOTE: flag sorting is needed to avoid error "Too many flagging agents instantiated" 01226 # If myflagsort='' keep individual flags separate 01227 # ='antenna' combine all flags with a particular antenna 01228 # 01229 # 01230 # Check if any operation is needed 01231 if myantenna == '' and myreason == '' and myflagsort == '': 01232 print 'No selection or sorting needed - sortflags returning input dictionary' 01233 casalog.post('No selection or sorting needed - sortflags returning input dictionary' 01234 ) 01235 flagd = myflags 01236 return flagd 01237 # 01238 flagd = {} 01239 nflagd = 0 01240 keylist = myflags.keys() 01241 print 'Selecting from ' + str(keylist.__len__()) \ 01242 + ' flagging commands' 01243 if keylist.__len__() > 0: 01244 # 01245 # Sort by key 01246 # 01247 keylist.sort() 01248 # 01249 # Construct flag command list for selected ant,reason 01250 # 01251 # print 'Selecting flags by antenna="'+str(myantenna)+'"' 01252 casalog.post('Selecting flags by antenna="' + str(myantenna) 01253 + '"') 01254 myantlist = myantenna.split(',') 01255 01256 # print 'Selecting flags by reason="'+str(myreason)+'"' 01257 casalog.post('Selecting flags by reason="' + str(myreason) + '"' 01258 ) 01259 myreaslist = [] 01260 # Parse myreason 01261 if type(myreason) == str: 01262 if myreason == '': 01263 print 'WARNING: reason= is treated as selection on a blank REASON!' 01264 casalog.post('WARNING: reason= is treated as selection on a blank REASON!' 01265 , 'WARN') 01266 if myreason != 'any': 01267 myreaslist.append(myreason) 01268 elif type(myreason) == list: 01269 myreaslist = myreason 01270 else: 01271 print 'ERROR: reason contains unallowed variable type' 01272 casalog.post('ERROR: reason contains unknown variable type' 01273 , 'SEVERE') 01274 return 01275 if myreaslist.__len__() > 0: 01276 print 'Selecting for reasons: ' + str(myreaslist) 01277 casalog.post('Selecting for reasons: ' + str(myreaslist)) 01278 else: 01279 print 'No selection on reason' 01280 casalog.post('No selection on reason') 01281 01282 # Note antenna and reason selection checks for inclusion not exclusivity 01283 doselect = myantenna != '' or myreaslist.__len__() > 0 01284 01285 # Now loop over flags, break into sorted and unsorted groups 01286 nsortd = 0 01287 sortd = {} 01288 sortdlist = [] 01289 nunsortd = 0 01290 unsortd = {} 01291 unsortdlist = [] 01292 if myflagsort == 'antenna': 01293 # will be resorting by antenna 01294 for key in keylist: 01295 myd = myflags[key] 01296 mymode = myd['mode'] 01297 ant = myd['antenna'] 01298 # work out number of selections for this flag command 01299 nselect = 0 01300 if myd.has_key('timerange'): 01301 if myd['timerange'] != '': 01302 nselect += 1 01303 if myd.has_key('spw'): 01304 if myd['spw'] != '': 01305 nselect += 1 01306 if myd.has_key('field'): 01307 if myd['field'] != '': 01308 nselect += 1 01309 if myd.has_key('corr'): 01310 if myd['corr'] != '': 01311 nselect += 1 01312 if myd.has_key('scan'): 01313 if myd['scan'] != '': 01314 nselect += 1 01315 if myd.has_key('intent'): 01316 if myd['intent'] != '': 01317 nselect += 1 01318 if myd.has_key('feed'): 01319 if myd['feed'] != '': 01320 nselect += 1 01321 if myd.has_key('uvrange'): 01322 if myd['uvrange'] != '': 01323 nselect += 1 01324 if myd.has_key('observation'): 01325 if myd['observation'] != '': 01326 nselect += 1 01327 # check if we can sort this by antenna 01328 antsort = False 01329 # can only sort mode manualflag together 01330 if mymode == 'online': 01331 antsort = nselect == 1 01332 elif mymode == '' or mymode == 'manualflag': 01333 # must have non-blank antenna selection 01334 if ant != '': 01335 # exclude flags with multiple/no selection 01336 if myd.has_key('timerange'): 01337 antsort = myd['timerange'] != '' \ 01338 and nselect == 1 01339 01340 if antsort: 01341 if ant.count('&') > 0: 01342 # for baseline specifications split on ; 01343 antlist = ant.split(';') 01344 else: 01345 # for antenna specifications split on , 01346 antlist = ant.split(',') 01347 # break this flag by antenna 01348 for a in antlist: 01349 if myantenna == '' or myantlist.count(a) > 0: 01350 addf = False 01351 reas = myd['reason'] 01352 reaslist = reas.split(',') 01353 reastr = '' 01354 if myreaslist.__len__() > 0: 01355 for r in myreaslist: 01356 if r == reas or reaslist.count(r) \ 01357 > 0: 01358 addf = True 01359 # check if this is a new reason 01360 if reastr != '': 01361 rlist = reastr.split(',') 01362 if rlist.count(r) == 0: 01363 reastr += ',' + r 01364 else: 01365 reastr = r 01366 else: 01367 addf = True 01368 reastr = reas 01369 # 01370 if addf: 01371 # check if this is a new antenna 01372 if sortd.has_key(a): 01373 # Already existing flag for this antenna, add this one 01374 t = sortd[a]['timerange'] 01375 tlist = t.split(',') 01376 timelist = myd['timerange' 01377 ].split(',') 01378 for tim in timelist: 01379 # check if this is a new timerange 01380 if tlist.count(tim) == 0: 01381 t += ',' + tim 01382 sortd[a]['timerange'] = t 01383 reas = sortd[a]['reason'] 01384 if reastr != '': 01385 reas += ',' + reastr 01386 sortd[a]['reason'] = reas 01387 # adjust timerange in command string 01388 cmdstr = '' 01389 cmdlist = sortd[a]['cmd'].split() 01390 for cmd in cmdlist: 01391 (cmdkey, cmdval) = cmd.split('=' 01392 ) 01393 if cmdkey == 'timerange': 01394 cmdstr += " timerange='" \ 01395 + t + "'" 01396 elif cmdkey == 'reason': 01397 cmdstr += " reason='" \ 01398 + reastr + "'" 01399 else: 01400 cmdstr += ' ' + cmd 01401 sortd[a]['cmd'] = cmdstr 01402 # adjust other keys 01403 if myd['level'] > sortd[a]['level']: 01404 sortd[a]['level'] = myd['level'] 01405 if myd['severity'] \ 01406 > sortd[a]['severity']: 01407 sortd[a]['severity'] = \ 01408 myd['severity'] 01409 else: 01410 # add this flag (copy most of it) 01411 sortd[a] = myd 01412 sortd[a]['id'] = a 01413 sortd[a]['antenna'] = a 01414 sortd[a]['reason'] = reastr 01415 else: 01416 # cannot compress flags from this mode, add to unsortd instead 01417 # doesn't clash 01418 unsortd[nunsortd] = myd 01419 nunsortd += 1 01420 sortdlist = sortd.keys() 01421 nsortd = sortdlist.__len__() 01422 unsortdlist = unsortd.keys() 01423 else: 01424 # All flags are in unsorted list 01425 unsortd = myflags.copy() 01426 unsortdlist = unsortd.keys() 01427 nunsortd = unsortdlist.__len__() 01428 01429 print 'Found ' + str(nsortd) + ' sorted flags and ' \ 01430 + str(nunsortd) + ' incompressible flags' 01431 casalog.post('Found ' + str(nsortd) + ' sorted flags and ' 01432 + str(nunsortd) + ' incompressible flags') 01433 01434 # selection on unsorted flags 01435 if doselect and nunsortd > 0: 01436 keylist = unsortd.keys() 01437 for key in keylist: 01438 myd = unsortd[key] 01439 ant = myd['antenna'] 01440 antlist = ant.split(',') 01441 reas = myd['reason'] 01442 reaslist = reas.split(',') 01443 # break this flag by antenna 01444 antstr = '' 01445 reastr = '' 01446 addf = False 01447 01448 for a in antlist: 01449 if myantenna == '' or myantlist.count(a) > 0: 01450 addr = False 01451 if myreaslist.__len__() > 0: 01452 for r in myreaslist: 01453 if reas == r or reaslist.count(r) > 0: 01454 addr = True 01455 # check if this is a new reason 01456 rlist = reastr.split(',') 01457 if reastr != '': 01458 rlist = reastr.split(',') 01459 if rlist.count(r) == 0: 01460 reastr += ',' + r 01461 else: 01462 reastr = r 01463 else: 01464 addr = True 01465 reastr = reas 01466 if addr: 01467 addf = True 01468 if antstr != '': 01469 # check if this is a new antenna 01470 alist = antstr.split(',') 01471 if alist.count(a) == 0: 01472 antstr += ',' + a 01473 else: 01474 antstr = a 01475 if addf: 01476 flagd[nflagd] = myd 01477 flagd[nflagd]['antenna'] = antstr 01478 flagd[nflagd]['reason'] = reastr 01479 nflagd += 1 01480 flagdlist = flagd.keys() 01481 elif nunsortd > 0: 01482 # just copy to flagd w/o selection 01483 flagd = unsortd.copy() 01484 flagdlist = flagd.keys() 01485 nflagd = flagdlist.__len__() 01486 01487 if nsortd > 0: 01488 # Add sorted keys back in to flagd 01489 print 'Adding ' + str(nsortd) + ' sorted flags to ' \ 01490 + str(nflagd) + ' incompressible flags' 01491 casalog.post('Adding ' + str(nsortd) + ' sorted flags to ' 01492 + str(nflagd) + ' incompressible flags') 01493 sortdlist.sort() 01494 for skey in sortdlist: 01495 flagd[nflagd] = sortd[skey] 01496 nflagd += 1 01497 01498 if nflagd > 0: 01499 print 'Found total of ' + str(nflagd) \ 01500 + ' flags meeting selection/sorting criteria' 01501 casalog.post('Found total of ' + str(nflagd) 01502 + ' flags meeting selection/sorting criteria') 01503 else: 01504 print 'No flagging commands found meeting criteria' 01505 casalog.post('No flagging commands found meeting criteria') 01506 else: 01507 print 'No flags found in input dictionary' 01508 casalog.post('No flags found in input dictionary') 01509 01510 return flagd 01511 01512 01513 # Done 01514 01515 01516 def clearFlagCmd(msfile, myrowlist=[]): 01517 # 01518 # Delete flag commands (rows) from the FLAG_CMD table of msfile 01519 # 01520 # Open and read columns from FLAG_CMD 01521 01522 mstable = msfile + '/FLAG_CMD' 01523 try: 01524 tb.open(mstable, nomodify=False) 01525 except: 01526 raise Exception, 'Error opening table ' + mstable 01527 01528 nrows = int(tb.nrows()) 01529 casalog.post('There were ' + str(nrows) + ' rows in FLAG_CMD') 01530 if nrows > 0: 01531 if myrowlist.__len__() > 0: 01532 rowlist = myrowlist 01533 else: 01534 rowlist = range(nrows) 01535 try: 01536 tb.removerows(rowlist) 01537 casalog.post('Deleted ' + str(rowlist.__len__()) 01538 + ' from FLAG_CMD table in MS') 01539 except: 01540 tb.close() 01541 raise Exception, 'Error removing rows ' + str(rowlist) \ 01542 + ' from table ' + mstable 01543 01544 nnew = int(tb.nrows()) 01545 else: 01546 casalog.post('No rows to clear') 01547 01548 tb.close() 01549 01550 01551 def plotflags( 01552 myflags, 01553 plotname, 01554 t1sdata, 01555 t2sdata, 01556 ): 01557 01558 try: 01559 import casac 01560 except ImportError, e: 01561 print 'failed to load casa:\n', e 01562 exit(1) 01563 qatool = casac.quanta() 01564 qa = casac.qa = qatool 01565 01566 try: 01567 import pylab as pl 01568 except ImportError, e: 01569 print 'failed to load pylab:\n', e 01570 exit(1) 01571 01572 # get list of flag keys 01573 keylist = myflags.keys() 01574 01575 # get list of antennas 01576 myants = [] 01577 for key in keylist: 01578 ant = myflags[key]['antenna'] 01579 if myants.count(ant) == 0: 01580 myants.append(ant) 01581 myants.sort() 01582 01583 antind = 0 01584 if plotname == '': 01585 pl.ion() 01586 else: 01587 pl.ioff() 01588 01589 f1 = pl.figure() 01590 ax1 = f1.add_axes([.15, .1, .75, .85]) 01591 # ax1.set_ylabel('antenna') 01592 # ax1.set_xlabel('time') 01593 badflags = [] 01594 for thisant in myants: 01595 antind += 1 01596 for thisflag in myflags: 01597 if myflags[thisflag]['antenna'] == thisant: 01598 # print thisant, myflags[thisflag]['reason'], myflags[thisflag]['timerange'] 01599 thisReason = myflags[thisflag]['reason'] 01600 if thisReason == 'FOCUS_ERROR': 01601 thisColor = 'red' 01602 thisOffset = 0.3 01603 elif thisReason == 'SUBREFLECTOR_ERROR': 01604 thisColor = 'blue' 01605 thisOffset = .15 01606 elif thisReason == 'ANTENNA_NOT_ON_SOURCE': 01607 thisColor = 'green' 01608 thisOffset = 0 01609 elif thisReason == 'ANTENNA_NOT_IN_SUBARRAY': 01610 thisColor = 'black' 01611 thisOffset = -.15 01612 else: 01613 thisColor = 'orange' 01614 thisOffset = 0.3 01615 mytimerange = myflags[thisflag]['timerange'] 01616 if mytimerange != '': 01617 t1 = mytimerange[:mytimerange.find('~')] 01618 t2 = mytimerange[mytimerange.find('~') + 1:] 01619 (t1s, t2s) = (qa.convert(t1, 's')['value'], 01620 qa.convert(t2, 's')['value']) 01621 else: 01622 t1s = t1sdata 01623 t2s = t2sdata 01624 myTimeSpan = t2s - t1s 01625 if myTimeSpan < 10000: 01626 ax1.plot([t1s, t2s], [antind + thisOffset, antind 01627 + thisOffset], color=thisColor, lw=2, 01628 alpha=.7) 01629 else: 01630 badflags.append((thisant, myTimeSpan, thisReason)) 01631 01632 # #badflags are ones which span a time longer than that used above 01633 # #they can be so long that including them compresses the time axis so that none of the other flags are visible 01634 # print 'badflags', badflags 01635 myXlim = ax1.get_xlim() 01636 myXrange = myXlim[1] - myXlim[0] 01637 legendFontSize = 12 01638 ax1.text(myXlim[0] + 0.050000000000000003 * myXrange, 29, 'FOCUS', 01639 color='red', size=legendFontSize) 01640 ax1.text(myXlim[0] + .17 * myXrange, 29, 'SUBREFLECTOR', 01641 color='blue', size=legendFontSize) 01642 ax1.text(myXlim[0] + .42 * myXrange, 29, 'OFF SOURCE', color='green' 01643 , size=legendFontSize) 01644 ax1.text(myXlim[0] + .62 * myXrange, 29, 'NOT IN SUBARRAY', 01645 color='black', size=legendFontSize) 01646 ax1.text(myXlim[0] + .90 * myXrange, 29, 'Other', color='orange', 01647 size=legendFontSize) 01648 ax1.set_ylim([0, 30]) 01649 01650 ax1.set_yticks(range(1, len(myants) + 1)) 01651 ax1.set_yticklabels(myants) 01652 ax1.set_xticks(pl.linspace(myXlim[0], myXlim[1], 3)) 01653 01654 mytime = [myXlim[0], (myXlim[1] + myXlim[0]) / 2.0, myXlim[1]] 01655 myTimestr = [] 01656 for time in mytime: 01657 q1 = qa.quantity(time, 's') 01658 time1 = qa.time(q1, form='ymd', prec=9)[0] 01659 myTimestr.append(time1) 01660 01661 ax1.set_xticklabels([myTimestr[0], (myTimestr[1])[11:], 01662 (myTimestr[2])[11:]]) 01663 # print myTimestr 01664 if plotname == '': 01665 pl.draw() 01666 else: 01667 pl.savefig(plotname, dpi=150) 01668 return 01669 01670 01671 def newplotflags( 01672 myflags, 01673 plotname, 01674 t1sdata, 01675 t2sdata, 01676 ): 01677 # 01678 # Function to plot flagging dictionary 01679 # Adapted from J.Marvil 01680 # Updated STM v4.1 2011-11-02 to handle ALMA flags 01681 # Updated STM v4.2 2012-02-16 trim flag times to data times 01682 # Updated STM v4.2 2012-04-10 bug fix in trim flag times to data times 01683 # Updated STM v4.2 2012-04-10 messages to logger 01684 try: 01685 import casac 01686 except ImportError, e: 01687 print 'failed to load casa:\n', e 01688 exit(1) 01689 01690 # After the swig converstion, it seems that the following 01691 # line is not needed anymore 01692 # qa = casac.qa = qatool = casac.quanta() 01693 01694 try: 01695 import pylab as pl 01696 except ImportError, e: 01697 print 'failed to load pylab:\n', e 01698 exit(1) 01699 01700 # list of supported colors (in order) 01701 colorlist = [ 01702 'red', 01703 'blue', 01704 'green', 01705 'black', 01706 'cyan', 01707 'magenta', 01708 'yellow', 01709 'orange', 01710 ] 01711 ncolors = colorlist.__len__() 01712 01713 # get list of flag keys 01714 keylist = myflags.keys() 01715 01716 # get lists of antennas and reasons 01717 # make plotting dictionary 01718 myants = [] 01719 myreas = [] 01720 plotflag = {} 01721 ipf = 0 01722 for key in keylist: 01723 antstr = myflags[key]['antenna'] 01724 reastr = myflags[key]['reason'] 01725 timstr = myflags[key]['timerange'] 01726 if antstr != '': 01727 # flags that have antenna specified 01728 antlist = antstr.split(',') 01729 nantlist = antlist.__len__() 01730 else: 01731 # Special 01732 antlist = ['All'] 01733 nantlist = 1 01734 # 01735 realist = reastr.split(',') 01736 nrealist = realist.__len__() 01737 # 01738 timlist = timstr.split(',') 01739 ntimlist = timlist.__len__() 01740 # 01741 # Break these into nants x ntimes flags 01742 # Trick is assigning multiple reasons 01743 # Normal cases: 01744 # A. One reason, single/multiple antennas x times 01745 # B. Multiple reasons=times, single/multiple antenna(s) 01746 # C. Single time, multiple antennas/reasons 01747 # D. Multiple reasons, no way to correspond with times 01748 # 01749 timmin = 1.0E11 01750 timmax = 0.0 01751 if nrealist == 1: 01752 # simplest case, single reason 01753 reas = realist[0] 01754 if reas == '': 01755 reas = 'Unknown' 01756 if myreas.count(reas) == 0: 01757 myreas.append(reas) 01758 for ia in range(nantlist): 01759 ant = antlist[ia] 01760 if myants.count(ant) == 0: 01761 myants.append(ant) 01762 for it in range(ntimlist): 01763 times = timlist[it] 01764 plotflag[ipf] = {} 01765 plotflag[ipf]['antenna'] = ant 01766 plotflag[ipf]['reason'] = reas 01767 plotflag[ipf]['timerange'] = times 01768 plotflag[ipf]['show'] = True 01769 ipf += 1 01770 elif nrealist == ntimlist: 01771 # corresponding reasons and times 01772 for ia in range(nantlist): 01773 ant = antlist[ia] 01774 if myants.count(ant) == 0: 01775 myants.append(ant) 01776 for it in range(ntimlist): 01777 times = timlist[it] 01778 reas = realist[it] 01779 if reas == '': 01780 reas = 'Unknown' 01781 if myreas.count(reas) == 0: 01782 myreas.append(reas) 01783 plotflag[ipf] = {} 01784 plotflag[ipf]['antenna'] = ant 01785 plotflag[ipf]['reason'] = reas 01786 plotflag[ipf]['timerange'] = times 01787 plotflag[ipf]['show'] = True 01788 ipf += 1 01789 else: 01790 # no correspondence between multiple reasons and ants/times 01791 # assign reason 'Miscellaneous' 01792 reas = 'Miscellaneous' 01793 if myreas.count(reas) == 0: 01794 myreas.append(reas) 01795 for ia in range(nantlist): 01796 ant = antlist[ia] 01797 if myants.count(ant) == 0: 01798 myants.append(ant) 01799 for it in range(ntimlist): 01800 times = timlist[it] 01801 plotflag[ipf] = {} 01802 plotflag[ipf]['antenna'] = ant 01803 plotflag[ipf]['reason'] = reas 01804 plotflag[ipf]['timerange'] = times 01805 plotflag[ipf]['show'] = True 01806 ipf += 1 01807 01808 myants.sort() 01809 nants = myants.__len__() 01810 nreas = myreas.__len__() 01811 casalog.post('Found ' + str(nreas) + ' reasons to plot for ' 01812 + str(nants) + ' antennas') 01813 npf = ipf 01814 casalog.post('Found ' + str(npf) + ' total flag ranges to plot') 01815 01816 # sort out times 01817 for ipf in range(npf): 01818 times = plotflag[ipf]['timerange'] 01819 if times != '': 01820 if times.count('~') > 0: 01821 t1 = times[:times.find('~')] 01822 t2 = times[times.find('~') + 1:] 01823 else: 01824 t1 = times 01825 t2 = t1 01826 (t1s, t2s) = (qa.convert(t1, 's')['value'], qa.convert(t2, 01827 's')['value']) 01828 plotflag[ipf]['t1s'] = t1s 01829 plotflag[ipf]['t2s'] = t2s 01830 if t1s < timmin: 01831 timmin = t1s 01832 if t2s > timmax: 01833 timmax = t2s 01834 # min,max times 01835 q1 = qa.quantity(timmin, 's') 01836 time1 = qa.time(q1, form='ymd', prec=9)[0] 01837 q2 = qa.quantity(timmax, 's') 01838 time2 = qa.time(q2, form='ymd', prec=9)[0] 01839 casalog.post('Found flag times from ' + time1 + ' to ' + time2) 01840 01841 # sort out blank times 01842 for ipf in range(npf): 01843 times = plotflag[ipf]['timerange'] 01844 if times == '': 01845 if t2sdata >= t1sdata > 0: 01846 plotflag[ipf]['t1s'] = t1sdata 01847 plotflag[ipf]['t2s'] = t2sdata 01848 else: 01849 plotflag[ipf]['t1s'] = timmin 01850 plotflag[ipf]['t2s'] = timmax 01851 01852 # if flag times are beyond range of data, trim them 01853 # Added STM 2012-02-16, fixed STM 2012-04-10 01854 ndropped = 0 01855 if t2sdata >= t1sdata > 0 and (timmin < t1sdata or timmax 01856 > t2sdata): 01857 # min,max data times 01858 q1 = qa.quantity(t1sdata, 's') 01859 tdata1 = qa.time(q1, form='ymd', prec=9)[0] 01860 q2 = qa.quantity(t2sdata, 's') 01861 tdata2 = qa.time(q2, form='ymd', prec=9)[0] 01862 casalog.post('WARNING: Trimming flag times to data limits ' 01863 + tdata1 + ' to ' + tdata2) 01864 01865 for ipf in range(npf): 01866 t1s = plotflag[ipf]['t1s'] 01867 t2s = plotflag[ipf]['t2s'] 01868 if t1s < t1sdata: 01869 if t2s >= t1sdata: 01870 # truncate to t1sdata 01871 plotflag[ipf]['t1s'] = t1sdata 01872 else: 01873 # entirely outside data range, do not plot 01874 plotflag[ipf]['show'] = False 01875 ndropped += 1 01876 01877 if t2s > t2sdata: 01878 if t1s <= t2sdata: 01879 # truncate to t2sdata 01880 plotflag[ipf]['t2s'] = t2sdata 01881 else: 01882 # entirely outside data range, do not plot 01883 plotflag[ipf]['show'] = False 01884 ndropped += 1 01885 01886 if ndropped > 0: 01887 casalog.post('WARNING: Trimming dropped ' + str(ndropped) 01888 + ' flags entirely') 01889 01890 # make reason dictionary with mapping of colors and offsets (-0.3 to 0.3) 01891 readict = {} 01892 reakeys = [] 01893 if nreas > ncolors: 01894 for i in range(nreas): 01895 reas = myreas[i] 01896 readict[reas] = {} 01897 if i < ncolors - 1: 01898 colr = colorlist[i] 01899 readict[reas]['color'] = colr 01900 readict[reas]['index'] = i 01901 offs = 0.3 - float(i) * 0.6 / float(ncolors - 1) 01902 readict[reas]['offset'] = offs 01903 reakeys.append(reas) 01904 else: 01905 colr = colorlist[ncolors - 1] 01906 readict[reas]['color'] = colr 01907 readict[reas]['index'] = ncolors - 1 01908 readict[reas]['offset'] = -0.3 01909 reakeys.append('Other') 01910 readict['Other'] = {} 01911 readict['Other']['color'] = colorlist[ncolors - 1] 01912 readict['Other']['index'] = ncolors - 1 01913 readict['Other']['offset'] = -0.3 01914 else: 01915 for i in range(nreas): 01916 reas = myreas[i] 01917 reakeys.append(reas) 01918 colr = colorlist[i] 01919 offs = 0.3 - float(i) * 0.6 / float(ncolors - 1) 01920 readict[reas] = {} 01921 readict[reas]['color'] = colr 01922 readict[reas]['index'] = i 01923 readict[reas]['offset'] = offs 01924 nlegend = reakeys.__len__() 01925 casalog.post('Will plot ' + str(nlegend) + ' reasons in legend') 01926 01927 antind = 0 01928 if plotname == '': 01929 pl.ion() 01930 else: 01931 pl.ioff() 01932 01933 f1 = pl.figure() 01934 ax1 = f1.add_axes([.15, .1, .75, .85]) 01935 # ax1.set_ylabel('antenna') 01936 # ax1.set_xlabel('time') 01937 # badflags=[] 01938 nplotted = 0 01939 for thisant in myants: 01940 antind += 1 01941 for ipf in range(npf): 01942 if plotflag[ipf]['show'] and plotflag[ipf]['antenna'] \ 01943 == thisant: 01944 # plot this flag 01945 thisReason = plotflag[ipf]['reason'] 01946 thisColor = readict[thisReason]['color'] 01947 thisOffset = readict[thisReason]['offset'] 01948 t1s = plotflag[ipf]['t1s'] 01949 t2s = plotflag[ipf]['t2s'] 01950 myTimeSpan = t2s - t1s 01951 01952 ax1.plot([t1s, t2s], [antind + thisOffset, antind 01953 + thisOffset], color=thisColor, lw=2, alpha=.7) 01954 nplotted += 1 01955 01956 casalog.post('Plotted ' + str(nplotted) + ' flags') 01957 01958 myXlim = ax1.get_xlim() 01959 myXrange = myXlim[1] - myXlim[0] 01960 # Pad the time axis? 01961 PadTime = 0.050000000000000003 01962 if PadTime > 0: 01963 xPad = PadTime * myXrange 01964 x0 = myXlim[0] - xPad 01965 x1 = myXlim[1] + xPad 01966 ax1.set_xlim(x0, x1) 01967 myXrange = x1 - x0 01968 else: 01969 # print ' Rescaled x axis' 01970 x0 = myXlim[0] 01971 x1 = myXlim[1] 01972 01973 legendFontSize = 12 01974 myYupper = nants + nlegend + 1.5 01975 # place legend text 01976 i = nants 01977 x = x0 + 0.050000000000000003 * myXrange 01978 for reas in reakeys: 01979 i += 1 01980 colr = readict[reas]['color'] 01981 ax1.text(x, i, reas, color=colr, size=legendFontSize) 01982 ax1.set_ylim([0, myYupper]) 01983 01984 ax1.set_yticks(range(1, len(myants) + 1)) 01985 ax1.set_yticklabels(myants) 01986 # print ' Relabled y axis' 01987 01988 nxticks = 3 01989 ax1.set_xticks(pl.linspace(myXlim[0], myXlim[1], nxticks)) 01990 01991 mytime = [] 01992 myTimestr = [] 01993 for itim in range(nxticks): 01994 time = myXlim[0] + (myXlim[1] - myXlim[0]) * float(itim) \ 01995 / float(nxticks - 1) 01996 mytime.append(time) 01997 q1 = qa.quantity(time, 's') 01998 time1 = qa.time(q1, form='ymd', prec=9)[0] 01999 if itim > 0: 02000 time1s = time1[11:] 02001 else: 02002 time1s = time1 02003 myTimestr.append(time1s) 02004 02005 ax1.set_xticklabels(myTimestr) 02006 # print myTimestr 02007 if plotname == '': 02008 pl.draw() 02009 else: 02010 pl.savefig(plotname, dpi=150) 02011 return 02012 02013 02014 def isModeValid(line): 02015 '''Check if mode is valid based on a line 02016 molinede --> line with strings 02017 Returns True if mode is either one of the following: 02018 '',manual,clip,quack,shadow,elevation ''' 02019 02020 if line.__contains__('mode'): 02021 if line.__contains__('manual') or line.__contains__('clip') \ 02022 or line.__contains__('quack') or line.__contains__('shadow' 02023 ) or line.__contains__('elevation'): 02024 return True 02025 else: 02026 return False 02027 02028 # No mode means manual 02029 return True 02030 02031 def readCalCmds(caltable, msfile, flaglist, rows, reason, useapplied): 02032 '''Flag a cal table 02033 02034 caltable cal table name 02035 msfile optional MS with flag cmds 02036 flagcmds list with flag cmds or [] when msfile is given 02037 reason select only flag cmds with this reason(s) 02038 useapplied select APPLIED true or false 02039 ''' 02040 02041 myflagcmd = {} 02042 if msfile != '': 02043 casalog.post('Reading flag cmds from FLAG_CMD table of MS') 02044 # Read only the selected rows for action = apply and 02045 myflagcmd = readFromTable(msfile, myflagrows=rows, useapplied=useapplied, myreason=reason) 02046 02047 elif flaglist != []: 02048 # Parse the input file 02049 if isinstance(flaglist, list): 02050 casalog.post('Reading from input list') 02051 cmdlist = flaglist 02052 02053 casalog.post('Input ' + str(cmdlist.__len__()) 02054 + ' lines from input list') 02055 # Make a FLAG_CMD compatible dictionary and select by reason 02056 myflagcmd = fh.makeDict(cmdlist, reason) 02057 02058 elif isinstance(flaglist, str): 02059 02060 casalog.post('Reading from input file') 02061 cmdlist = fh.readFile(flaglist) 02062 02063 # Make a FLAG_CMD compatible dictionary and select by reason 02064 myflagcmd = fh.makeDict(cmdlist, reason) 02065 02066 else: 02067 casalog.post('Unsupported inpfile type', 'ERROR') 02068 02069 return myflagcmd 02070 02071 def applyCalCmds(aflocal, caltable, myflagcmd, tablerows, flagbackup, outfile): 02072 02073 # Get the list of parameters 02074 cmdlist = [] 02075 cmdkeys = myflagcmd.keys() 02076 for key in cmdkeys: 02077 cmdline = myflagcmd[key]['command'] 02078 cmdlist.append(cmdline) 02079 02080 # Select the data 02081 selpars = {} 02082 if cmdlist.__len__() == 1: 02083 # Get all the selection parameters, but set correlation to '' 02084 cmd0 = myflagcmd[cmdkeys[0]]['command'] 02085 selpars = fh.getSelectionPars(cmd0) 02086 casalog.post('The selected subset of the MS will be: ') 02087 casalog.post('%s' % selpars) 02088 02089 aflocal.selectdata(selpars) 02090 02091 list2save = fh.setupAgent(aflocal, myflagcmd, tablerows, True, True) 02092 if list2save == {}: 02093 raise Exception, 'Cannot setup the agent(s)' 02094 02095 # Initialize the Agents 02096 aflocal.init() 02097 02098 # Backup the flags before running 02099 if flagbackup: 02100 fh.backupFlags(aflocal, msfile='', prename='flagcmd') 02101 02102 # Run the tool 02103 aflocal.run(True, True) 02104 02105 aflocal.done() 02106 02107 02108 02109 02110 02111 02112 02113 02114 02115 02116 02117 02118 02119 02120 02121 02122 02123