casa
$Rev:20696$
|
00001 # 00002 # This file was generated using xslt from its XML file 00003 # 00004 # Copyright 2008, Associated Universities Inc., Washington DC 00005 # 00006 import sys 00007 import os 00008 #from casac import * 00009 import casac 00010 import string 00011 import time 00012 import inspect 00013 import gc 00014 import numpy 00015 from odict import odict 00016 from taskmanager import tm 00017 from task_peel import peel 00018 class peel_cli_: 00019 __name__ = "peel" 00020 __async__ = {} 00021 rkey = None 00022 i_am_a_casapy_task = None 00023 # The existence of the i_am_a_casapy_task attribute allows help() 00024 # (and other) to treat casapy tasks as a special case. 00025 00026 def __init__(self) : 00027 self.__bases__ = (peel_cli_,) 00028 self.__doc__ = self.__call__.__doc__ 00029 00030 self.parameters={'vis':None, 'dirs':None, 'remove':None, 'calmode':None, 'async':None} 00031 00032 00033 def result(self, key=None): 00034 #### here we will scan the task-ids in __async__ 00035 #### and add any that have completed... 00036 if key is not None and self.__async__.has_key(key) and self.__async__[key] is not None: 00037 ret = tm.retrieve(self.__async__[key]) 00038 if ret['state'] == "done" : 00039 self.__async__[key] = None 00040 elif ret['state'] == 'crashed' : 00041 self.__async__[key] = None 00042 return ret 00043 return None 00044 00045 00046 def __call__(self, vis=None, dirs=None, remove=None, calmode=None, async=None): 00047 00048 """Do direction dependent selfcal(s) and optionally remove annoying sources. 00049 Unfortunately at some level gains are direction-dependent, typically 00050 because of either deviations between the true antenna voltage patterns and 00051 the models being used, and/or fluctuations in one layer or another of the 00052 Earth's atmosphere. Bright sources located in the edges of the primary 00053 beam therefore corrupt images of the central portions of the primary beam 00054 in two ways. The most obvious way is by throwing a corrupted version of 00055 the PSF across the image. Since it is corrupted, it cannot be deconvolved 00056 away without first correcting the gains. The second problem is that a 00057 bright source can dominate the solutions of "classical" selfcalibration, 00058 essentially forcing it to solve the gains for the direction of the bright 00059 source instead of the pointing center. 00060 00061 Solving for and removing the effects of direction-dependent gains is known 00062 in various forms as "peeling", "modcal", or most prosaically, 00063 direction-dependent selfcalibration. This task attempts 00064 direction-dependent selfcalibration in the requested list of directions, 00065 and optionally removes the associated sources. 00066 00067 The usual risks of selfcalibration (imperfect model and possibly 00068 insufficient constraints) are particularly severe for peeling. Approach it 00069 with trepidation and stop as soon as possible. Peeling can ameliorate the 00070 effects of heterogeneous arrays, but it is better to use the right antenna 00071 voltage patterns a priori. 00072 00073 Do not peel unless necessary. 00074 00075 Still here? All right...read carefully... 00076 00077 Your desire to peel probably stems from the center of your "science field" 00078 being spoiled by the distorted PSFs of bright sources near the edge of the 00079 primary beam. The fact that their PSFs are interfering with your field of 00080 interest means that your science sources are interfering with the sources 00081 to be peeled! Thus before doing any peeling you should remove a model of 00082 your science field from the visibilities. However, the model should not 00083 include any artifacts from the sources to be peeled. The easiest way to 00084 produce such a model is to clean down to the threshhold of the brightest 00085 artifacts. peel does not (yet) do this for you! You are also of course 00086 responsible for returning the model of your science field to the 00087 visibilities once you have finished peeling. Obviously, if your science 00088 sources are fainter than the artifacts, removing them and replacing them is 00089 not necessary. 00090 00091 If more than one source must be peeled there is a chance (calculated using 00092 Murphy's Law) that they are interfering with each other. peel does not yet 00093 simultaneously solve for the gains in more than direction, so interfering 00094 sources must be approached by peeling the brightest source down to the 00095 level of the brightest artifacts in its vicinity, and next peeling whatever 00096 is currently causing the worst artifacts, continuing as necessary. 00097 00098 If the interactions are especially strong, the cycle will have to be 00099 iterated, refining the model(s) along the way. The convergence is often 00100 safer and faster if the first iteration of the cycle only solves for the 00101 phases, and leaves phase + amplitude selfcalibration to the final 00102 iteration. 00103 00104 Any given run of peel is nearly guaranteed to reduce the artifacts from the 00105 source being peeled, so it can be tempting to continue peeling until the 00106 artifacts drop below the noise. Resist that temptation! The number of 00107 fitted parameters accumulates with each peel, so repeated peels force the 00108 image toward the originally assumed model. Even if the total number of 00109 fitted parameters remains much smaller than the number of visibilities, the 00110 interactions between peeled sources and the central field take their toll 00111 on the science field. peel sees residual PSF sidelobes from the science 00112 region as artifacts that must be minimized. Whether removing some flux 00113 from the science source(s) is a risk or a certainty, the number of peels 00114 should be kept down. Overpeeling becomes easier to spot with experience, 00115 but the symptoms are strongly telescope-dependent. 00116 00117 00118 00119 00120 Example: 00121 00122 # Start with a phase-only peel, and keep the source so it can be phase + 00123 # amplitude peeled if necessary. 00124 peel(vis='my.ms', calmode="p", remove=False) 00125 00126 # Examine the result with viewer. 00127 00128 # OK, do a phase + amplitude removal. 00129 peel(vis='my.ms', calmode="pa") 00130 00131 """ 00132 if not hasattr(self, "__globals__") or self.__globals__ == None : 00133 self.__globals__=sys._getframe(len(inspect.stack())-1).f_globals 00134 #casac = self.__globals__['casac'] 00135 casalog = self.__globals__['casalog'] 00136 #casalog = casac.casac.logsink() 00137 self.__globals__['__last_task'] = 'peel' 00138 self.__globals__['taskname'] = 'peel' 00139 ### 00140 self.__globals__['update_params'](func=self.__globals__['taskname'],printtext=False,ipython_globals=self.__globals__) 00141 ### 00142 ### 00143 #Handle globals or user over-ride of arguments 00144 # 00145 function_signature_defaults=dict(zip(self.__call__.func_code.co_varnames,self.__call__.func_defaults)) 00146 useLocalDefaults = False 00147 00148 for item in function_signature_defaults.iteritems(): 00149 key,val = item 00150 keyVal = eval(key) 00151 if (keyVal == None): 00152 #user hasn't set it - use global/default 00153 pass 00154 else: 00155 #user has set it - use over-ride 00156 if (key != 'self') : 00157 useLocalDefaults = True 00158 00159 myparams = {} 00160 if useLocalDefaults : 00161 for item in function_signature_defaults.iteritems(): 00162 key,val = item 00163 keyVal = eval(key) 00164 exec('myparams[key] = keyVal') 00165 self.parameters[key] = keyVal 00166 if (keyVal == None): 00167 exec('myparams[key] = '+ key + ' = self.itsdefault(key)') 00168 keyVal = eval(key) 00169 if(type(keyVal) == dict) : 00170 if len(keyVal) > 0 : 00171 exec('myparams[key] = ' + key + ' = keyVal[len(keyVal)-1][\'value\']') 00172 else : 00173 exec('myparams[key] = ' + key + ' = {}') 00174 00175 else : 00176 async = self.parameters['async'] 00177 myparams['vis'] = vis = self.parameters['vis'] 00178 myparams['dirs'] = dirs = self.parameters['dirs'] 00179 myparams['remove'] = remove = self.parameters['remove'] 00180 myparams['calmode'] = calmode = self.parameters['calmode'] 00181 00182 00183 result = None 00184 00185 # 00186 # The following is work around to avoid a bug with current python translation 00187 # 00188 mytmp = {} 00189 00190 mytmp['vis'] = vis 00191 mytmp['dirs'] = dirs 00192 mytmp['remove'] = remove 00193 mytmp['calmode'] = calmode 00194 pathname='file:///'+os.environ.get('CASAPATH').split()[0]+'/share/xml/' 00195 trec = casac.casac.utils().torecord(pathname+'peel.xml') 00196 00197 casalog.origin('peel') 00198 try : 00199 #if not trec.has_key('peel') or not casac.casac.utils().verify(mytmp, trec['peel']) : 00200 #return False 00201 00202 casac.casac.utils().verify(mytmp, trec['peel'], True) 00203 scriptstr=[''] 00204 saveinputs = self.__globals__['saveinputs'] 00205 saveinputs('peel', 'peel.last', myparams, self.__globals__,scriptstr=scriptstr) 00206 if async : 00207 count = 0 00208 keybase = time.strftime("%y%m%d.%H%M%S") 00209 key = keybase + "_" + str(count) 00210 while self.__async__.has_key(key) : 00211 count += 1 00212 key = keybase + "_" + str(count) 00213 result = tm.execute('peel', vis, dirs, remove, calmode) 00214 print "Use: " 00215 print " tm.retrieve(return_value) # to retrieve the status" 00216 print 00217 self.rkey = key 00218 self.__async__[key] = result 00219 else : 00220 tname = 'peel' 00221 spaces = ' '*(18-len(tname)) 00222 casalog.post('\n##########################################'+ 00223 '\n##### Begin Task: ' + tname + spaces + ' #####') 00224 casalog.post(scriptstr[1][1:]+'\n', 'INFO') 00225 result = peel(vis, dirs, remove, calmode) 00226 casalog.post('##### End Task: ' + tname + ' ' + spaces + ' #####'+ 00227 '\n##########################################') 00228 00229 except Exception, instance: 00230 if(self.__globals__.has_key('__rethrow_casa_exceptions') and self.__globals__['__rethrow_casa_exceptions']) : 00231 raise 00232 else : 00233 #print '**** Error **** ',instance 00234 tname = 'peel' 00235 casalog.post('An error occurred running task '+tname+'.', 'ERROR') 00236 pass 00237 00238 gc.collect() 00239 return result 00240 # 00241 # 00242 # 00243 def paramgui(self, useGlobals=True, ipython_globals=None): 00244 """ 00245 Opens a parameter GUI for this task. If useGlobals is true, then any relevant global parameter settings are used. 00246 """ 00247 import paramgui 00248 if not hasattr(self, "__globals__") or self.__globals__ == None : 00249 self.__globals__=sys._getframe(len(inspect.stack())-1).f_globals 00250 00251 if useGlobals: 00252 if ipython_globals == None: 00253 myf=self.__globals__ 00254 else: 00255 myf=ipython_globals 00256 00257 paramgui.setGlobals(myf) 00258 else: 00259 paramgui.setGlobals({}) 00260 00261 paramgui.runTask('peel', myf['_ip']) 00262 paramgui.setGlobals({}) 00263 00264 # 00265 # 00266 # 00267 def defaults(self, param=None, ipython_globals=None, paramvalue=None, subparam=None): 00268 if not hasattr(self, "__globals__") or self.__globals__ == None : 00269 self.__globals__=sys._getframe(len(inspect.stack())-1).f_globals 00270 if ipython_globals == None: 00271 myf=self.__globals__ 00272 else: 00273 myf=ipython_globals 00274 00275 a = odict() 00276 a['vis'] = '' 00277 a['dirs'] = "" 00278 a['remove'] = True 00279 a['calmode'] = 'p' 00280 00281 a['async']=False 00282 00283 ### This function sets the default values but also will return the list of 00284 ### parameters or the default value of a given parameter 00285 if(param == None): 00286 myf['__set_default_parameters'](a) 00287 elif(param == 'paramkeys'): 00288 return a.keys() 00289 else: 00290 if(paramvalue==None and subparam==None): 00291 if(a.has_key(param)): 00292 return a[param] 00293 else: 00294 return self.itsdefault(param) 00295 else: 00296 retval=a[param] 00297 if(type(a[param])==dict): 00298 for k in range(len(a[param])): 00299 valornotval='value' 00300 if(a[param][k].has_key('notvalue')): 00301 valornotval='notvalue' 00302 if((a[param][k][valornotval])==paramvalue): 00303 retval=a[param][k].copy() 00304 retval.pop(valornotval) 00305 if(subparam != None): 00306 if(retval.has_key(subparam)): 00307 retval=retval[subparam] 00308 else: 00309 retval=self.itsdefault(subparam) 00310 else: 00311 retval=self.itsdefault(subparam) 00312 return retval 00313 00314 00315 # 00316 # 00317 def check_params(self, param=None, value=None, ipython_globals=None): 00318 if ipython_globals == None: 00319 myf=self.__globals__ 00320 else: 00321 myf=ipython_globals 00322 # print 'param:', param, 'value:', value 00323 try : 00324 if str(type(value)) != "<type 'instance'>" : 00325 value0 = value 00326 value = myf['cu'].expandparam(param, value) 00327 matchtype = False 00328 if(type(value) == numpy.ndarray): 00329 if(type(value) == type(value0)): 00330 myf[param] = value.tolist() 00331 else: 00332 #print 'value:', value, 'value0:', value0 00333 #print 'type(value):', type(value), 'type(value0):', type(value0) 00334 myf[param] = value0 00335 if type(value0) != list : 00336 matchtype = True 00337 else : 00338 myf[param] = value 00339 value = myf['cu'].verifyparam({param:value}) 00340 if matchtype: 00341 value = False 00342 except Exception, instance: 00343 #ignore the exception and just return it unchecked 00344 myf[param] = value 00345 return value 00346 # 00347 # 00348 def description(self, key='peel', subkey=None): 00349 desc={'peel': 'Do direction dependent selfcal(s) and optionally remove annoying sources.', 00350 'vis': 'Name of the input visibility set.', 00351 'dirs': 'List of directions to peel.', 00352 'remove': 'Subtract the selfcalibrated source(s) from the data.', 00353 'calmode': 'Type of selfcal to do. (p: Phase only, a: Ampl only. ap: both', 00354 00355 'async': 'If true the taskname must be started using peel(...)' 00356 } 00357 00358 if(desc.has_key(key)) : 00359 return desc[key] 00360 00361 def itsdefault(self, paramname) : 00362 a = {} 00363 a['vis'] = '' 00364 a['dirs'] = "" 00365 a['remove'] = True 00366 a['calmode'] = 'p' 00367 00368 #a = sys._getframe(len(inspect.stack())-1).f_globals 00369 00370 if a.has_key(paramname) : 00371 return a[paramname] 00372 peel_cli = peel_cli_()