casa
$Rev:20696$
|
00001 from glob import glob 00002 import os 00003 import sys 00004 import shutil 00005 from setjy_helper import * 00006 from taskinit import * 00007 from parallel.parallel_task_helper import ParallelTaskHelper 00008 00009 def setjy(vis=None, field=None, spw=None, 00010 selectdata=None, timerange=None, scan=None, observation=None, 00011 modimage=None, listmodels=None, 00012 scalebychan=None, fluxdensity=None, spix=None, reffreq=None, 00013 standard=None, useephemdir=None, usescratch=None): 00014 """Fills the model column for flux density calibrators.""" 00015 00016 casalog.origin('setjy') 00017 # Take care of the trivial parallelization 00018 if ( not listmodels and ParallelTaskHelper.isParallelMS(vis)): 00019 # jagonzal: We actually operate in parallel when usescratch=True because only 00020 # in this case there is a good trade-off between the parallelization overhead 00021 # and speed up due to the load involved with MODEL_DATA column creation 00022 if (usescratch): 00023 helper = ParallelTaskHelper('setjy', locals()) 00024 retval = helper.go() 00025 # jagonzal: When usescratch=False, we operate sequentially, but it is necessary 00026 # to iterate trough the list of individual sub-MSs, because each one has its own 00027 # set of keywords (where the visibility model header is set) 00028 else: 00029 myms = mstool() 00030 myms.open(vis) 00031 subMS_list = myms.getreferencedtables() 00032 myms.close() 00033 retval = True 00034 for subMS in subMS_list: 00035 retval_i = setjy_core(subMS, field, spw, selectdata, timerange, 00036 scan, observation, modimage, listmodels, scalebychan, 00037 fluxdensity, spix, reffreq, standard, useephemdir, usescratch) 00038 if not retval_i: 00039 retval = False 00040 casalog.post("setjy failed for sub-MS %s" % (subMS),'WARNING') 00041 00042 # jagonzal: Gather the models from the keywords of each individual sub-MS 00043 mytb = tbtool() 00044 keywords_MMS = {} 00045 for subMS in subMS_list: 00046 mytb.open(subMS) 00047 keywords_subMS = mytb.getkeywords() 00048 for key in keywords_subMS: 00049 if key.count("model"): 00050 keywords_MMS[key] = keywords_subMS[key] 00051 mytb.close() 00052 00053 # jagonzal: Copy the models to the keywords of each individual sub-MS 00054 for subMS in subMS_list: 00055 mytb.open(subMS,nomodify=False) 00056 for key in keywords_MMS: 00057 mytb.putkeyword(key,keywords_MMS[key]) 00058 mytb.close() 00059 00060 00061 else: 00062 retval = setjy_core(vis, field, spw, selectdata, timerange, 00063 scan, observation, modimage, listmodels, scalebychan, 00064 fluxdensity, spix, reffreq, standard, useephemdir, usescratch) 00065 00066 return retval 00067 00068 00069 def setjy_core(vis=None, field=None, spw=None, 00070 selectdata=None, timerange=None, scan=None, observation=None, 00071 modimage=None, listmodels=None, 00072 scalebychan=None, fluxdensity=None, spix=None, reffreq=None, 00073 standard=None, useephemdir=None, usescratch=None): 00074 """Fills the model column for flux density calibrators.""" 00075 00076 retval = True 00077 clnamelist=[] 00078 try: 00079 # Here we only list the models available, but don't perform any operation 00080 if listmodels: 00081 casalog.post("Listing model candidates (listmodels == True).") 00082 if vis: 00083 casalog.post("%s is NOT being modified." % vis) 00084 00085 if standard=='Butler-JPL-Horizons 2012': 00086 ssmoddirs = findCalModels(target='SolarSystemModels', 00087 roots=[casa['dirs']['data']], 00088 exts=['.im','.ms','tab']) 00089 if ssmoddirs==set([]): 00090 casalog.post("No models were found. Missing SolarSystemModels in the CASA data directory","WARN") 00091 for d in ssmoddirs: 00092 lsmodims(d,modpat='*Tb.dat', header='Tb models of solar system objects available for %s' % standard) 00093 elif standard=='Butler-JPL-Horizons 2010': 00094 availmodellist=['Venus', 'Mars', 'Jupiter', 'Uranus', 'Neptune', 'Pluto', 00095 'Io', 'Europa', 'Ganymede', 'Callisto', 'Titan','Triton', 00096 'Ceres', 'Pallas', 'Vesta', 'Juno', 'Victoria', 'Davida'] 00097 print "Solar system objects recognized by %s:" % standard 00098 print availmodellist 00099 else: 00100 lsmodims('.', modpat='*.im* *.mod*') 00101 calmoddirs = findCalModels() 00102 ssmoddirs=None 00103 for d in calmoddirs: 00104 lsmodims(d) 00105 00106 # Actual operation, when either the MODEL_DATA column or visibility model header are set 00107 else: 00108 if not os.path.isdir(vis): 00109 #casalog.post(vis + " must be a valid MS unless listmodels is True.", 00110 # "SEVERE") 00111 raise Exception, "%s is not a valid MS" % vis 00112 #return False 00113 00114 myms = mstool() 00115 myim = imtool() 00116 00117 if type(vis) == str and os.path.isdir(vis): 00118 n_selected_rows = nselrows(vis, field, spw, observation, timerange, scan) 00119 00120 # jagonzal: When usescratch=True, creating the MODEL column only on a sub-set of 00121 # Sub-MSs causes problems because ms::open requires all the tables in ConCatTable 00122 # to have the same description (MODEL data column must exist in all Sub-MSs) 00123 # 00124 # This is a bit of an over-doing but it is necessary for the sake of transparency 00125 # 00126 # Besides, this is also the same behavior as when running setjy vs a normal MS 00127 # 00128 # Finally, This does not affect the normal MS case because nselrows throws an 00129 # exception when the user enters an invalid data selection, but it works for the 00130 # MMS case because every sub-Ms contains a copy of the entire MMS sub-tables 00131 if ((not n_selected_rows) and (not usescratch)): 00132 # jagonzal: Turn this SEVERE into WARNING, as explained above 00133 casalog.post("No rows were selected.", "WARNING") 00134 return True 00135 else: 00136 myim.open(vis, usescratch=usescratch) 00137 00138 else: 00139 raise Exception, 'Visibility data set not found - please verify the name' 00140 00141 # If modimage is not an absolute path, see if we can find exactly 1 match in the likely places. 00142 if modimage and modimage[0] != '/': 00143 cwd = os.path.abspath('.') 00144 calmoddirs = [cwd] 00145 calmoddirs += findCalModels(roots=[cwd, 00146 casa['dirs']['data']]) 00147 candidates = [] 00148 for calmoddir in calmoddirs: 00149 cand = calmoddir + '/' + modimage 00150 if os.path.isdir(cand): 00151 candidates.append(cand) 00152 if not candidates: 00153 casalog.post("%s was not found for modimage in %s." %(modimage, 00154 ', '.join(calmoddirs)), 00155 'SEVERE') 00156 return False 00157 elif len(candidates) > 1: 00158 casalog.post("More than 1 candidate for modimage was found:", 00159 'SEVERE') 00160 for c in candidates: 00161 casalog.post("\t" + c, 'SEVERE') 00162 casalog.post("Please pick 1 and use the absolute path (starting with /).", 00163 'SEVERE') 00164 return False 00165 else: 00166 modimage = candidates[0] 00167 casalog.post("Using %s for modimage." % modimage, 'INFO') 00168 00169 # Write the parameters to HISTORY before the tool writes anything. 00170 try: 00171 param_names = setjy.func_code.co_varnames[:setjy.func_code.co_argcount] 00172 param_vals = [eval(p) for p in param_names] 00173 retval &= write_history(myms, vis, 'setjy', param_names, 00174 param_vals, casalog) 00175 except Exception, instance: 00176 casalog.post("*** Error \'%s\' updating HISTORY" % (instance), 00177 'WARN') 00178 00179 # Split the process for solar system objects 00180 # To maintain the behavior of SetJy such that if a flux density is specified 00181 # we use it rather than the model, we need to check the state of the 00182 # input fluxdensity JSK 10/25/2012 00183 userFluxDensity = fluxdensity is not None 00184 if userFluxDensity and isinstance(fluxdensity, list): 00185 userFluxDensity = fluxdensity[0] > 0.0 00186 elif userFluxDensity: 00187 userFluxDensity = fluxdensity > 0.0 00188 00189 if standard=="Butler-JPL-Horizons 2012" and not userFluxDensity: 00190 casalog.post("Using Butler-JPL-Horizons 2012") 00191 ssmoddirs = findCalModels(target='SolarSystemModels', 00192 roots=[casa['dirs']['data']], 00193 exts=['.im','.ms','tab']) 00194 if ssmoddirs==set([]): 00195 raise Exception, "Missing Tb models in the data directory" 00196 00197 setjyutil=ss_setjy_helper(myim,vis,casalog) 00198 setjyutil.setSolarObjectJy(field=field,spw=spw,scalebychan=scalebychan, 00199 timerange=timerange,observation=str(observation), scan=scan, useephemdir=useephemdir) 00200 clnamelist=setjyutil.getclnamelist() 00201 else: 00202 myim.setjy(field=field, spw=spw, modimage=modimage, 00203 fluxdensity=fluxdensity, spix=spix, reffreq=reffreq, 00204 standard=standard, scalebychan=scalebychan, time=timerange, 00205 observation=str(observation), scan=scan) 00206 myim.close() 00207 00208 # This block should catch errors mainly from the actual operation mode 00209 except Exception, instance: 00210 casalog.post('%s' % instance,'SEVERE') 00211 retval=False 00212 raise instance 00213 00214 finally: 00215 if standard=='Butler-JPL-Horizons 2012': 00216 for cln in clnamelist: 00217 if os.path.isdir(cln): 00218 shutil.rmtree(cln) 00219 00220 00221 return retval 00222 00223 00224 def better_glob(pats): 00225 """ 00226 Unlike ls, glob.glob('pat1 pat2') does not return 00227 the union of matches to pat1 and pat2. This does. 00228 """ 00229 retset = set([]) 00230 patlist = pats.split() 00231 for p in patlist: 00232 retset.update(glob(p)) 00233 return retset 00234 00235 00236 def lsmodims(path, modpat='*', header='Candidate modimages'): 00237 """ 00238 Does an ls -d of files or directories in path matching modpat. 00239 00240 Header describes what is being listed. 00241 """ 00242 if os.path.isdir(path): 00243 if better_glob(path + '/' + modpat): 00244 print "\n%s (%s) in %s:" % (header, modpat, path) 00245 sys.stdout.flush() 00246 os.system('cd ' + path + ';ls -d ' + modpat) 00247 else: 00248 print "\nNo %s matching '%s' found in %s" % (header.lower(), 00249 modpat, path) 00250 00251 00252 def findCalModels(target='CalModels', 00253 roots=['.', casa['dirs']['data']], 00254 permexcludes = ['.svn', 'regression', 'ephemerides', 00255 'geodetic', 'gui'], 00256 exts=['.ms', '.im', '.tab']): 00257 """ 00258 Returns a set of directories ending in target that are in the trees of roots. 00259 00260 Because casa['dirs']['data'] can contain a lot, and CASA tables are 00261 directories, branches matching permexcludes or exts are excluded for speed. 00262 """ 00263 retset = set([]) 00264 for root in roots: 00265 # Do a walk to find target directories in root. 00266 # 7/5/2011: glob('/export/data_1/casa/gnuactive/data/*/CalModels/*') doesn't work. 00267 for path, dirs, fnames in os.walk(root, followlinks=True): 00268 excludes = permexcludes[:] 00269 for ext in exts: 00270 excludes += [d for d in dirs if ext in d] 00271 for d in excludes: 00272 if d in dirs: 00273 dirs.remove(d) 00274 if path.split('/')[-1] == target: 00275 retset.add(path) 00276 return retset 00277 00278 00279 def nselrows(vis, field='', spw='', obs='', timerange='', scan=''): 00280 00281 retval = 0 00282 myms = mstool() 00283 00284 msselargs = {'vis': vis} 00285 if field: 00286 msselargs['field'] = field 00287 if spw: 00288 msselargs['spw'] = spw 00289 if obs: 00290 msselargs['observation'] = obs 00291 if timerange: 00292 msselargs['time'] = timerange 00293 if scan: 00294 msselargs['scan'] = scan 00295 00296 # ms.msseltoindex only goes by the subtables - it does NOT check 00297 # whether the main table has any rows matching the selection. 00298 try: 00299 selindices = myms.msseltoindex(**msselargs) 00300 except Exception, instance: 00301 casalog.post('nselrowscore exception: %s' % instance,'SEVERE') 00302 raise instance 00303 00304 query = [] 00305 if field: 00306 query.append("FIELD_ID in " + str(selindices['field'].tolist())) 00307 if spw: 00308 query.append("DATA_DESC_ID in " + str(selindices['spw'].tolist())) 00309 if obs: 00310 query.append("OBSERVATION_ID in " + str(selindices['obsids'].tolist())) 00311 00312 # I don't know why ms.msseltoindex takes a time argument 00313 # - It doesn't seem to appear in the output. 00314 00315 if scan: 00316 query.append("SCAN_NUMBER in " + str(selindices['scan'].tolist())) 00317 00318 mytb = tbtool() 00319 mytb.open(vis) 00320 00321 if (len(query)>0): 00322 retval = mytb.nrows() 00323 mytb.close() 00324 else: 00325 try: 00326 st = mytb.query(' and '.join(query),style='python') # Does style matter here? 00327 retval = st.nrows() 00328 mytb.close() 00329 except Exception, instance: 00330 casalog.post('nselrowscore exception: %s' % instance,'SEVERE') 00331 mytb.close() 00332 raise Exception, instance 00333 00334 return retval