Coverage for /wheeldirectory/casa-6.7.0-12-py3.10.el8/lib/py/lib/python3.10/site-packages/casatasks/private/task_setjy.py: 34%

329 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-10-31 17:39 +0000

1from glob import glob 

2import os 

3import re 

4import sys 

5import shutil 

6 

7# the solution here to findCalModels should be reworked 

8# CASA5 uses the casa dict to set the default roots parameter values 

9# and that dict is not available in CASA6, where ctsys.resolve is 

10# available 

11# Here: defaultRoots is defined differently for CASA6 and CASA5 and 

12# that values is used as the default value for the roots parameter in 

13# findCalModels. 

14# Inside findCalModels there is a new section at the top to use 

15# ctsys.resolve to make the initial attempt to find the models. 

16# If that fails or is unavailable it falls back to the CASA5 code. 

17 

18 

19from .setjy_helper import * 

20from .parallel.parallel_data_helper import ParallelDataHelper 

21from .parallel.parallel_task_helper import ParallelTaskHelper 

22from .mstools import write_history 

23from casatools import ctsys, ms, imager, calibrater 

24from casatasks import casalog 

25 

26# used in one type comparison 

27strType = str 

28 

29# default roots argument for findCalModels 

30defaultRoots = ['.'] 

31 

32# Helper class for Multi-MS processing (by SC) 

33class SetjyHelper(): 

34 def __init__(self, msfile=None): 

35 self.__msfile = msfile 

36 

37 def resetModelCol(self): 

38 rstatus = True 

39 # Hide the log info 

40 casalog.post("Resetting the log filter to WARN", "DEBUG") 

41 casalog.post("Initialize the MODEL columns of sub-MSs to default 1", "DEBUG") 

42 casalog.filter('WARN') 

43 

44 myms = ms() 

45 try: 

46 try: 

47 myms.open(self.__msfile) 

48 submslist = myms.getreferencedtables() 

49 parentms = myms.name() 

50 myms.close() 

51 except: 

52 if (os.path.exists(os.path.join(self.__msfile,'SUBMSS'))): 

53 casalog.post("MS may be corrupted. Try to initialize sub-MSs anyway...","DEBUG") 

54 submslist = [os.path.abspath(os.path.join(self.__msfile,'SUBMSS',fn)) 

55 for fn in os.listdir(os.path.join(self.__msfile,'SUBMSS')) if fn.endswith('.ms') ] 

56 else: 

57 rstatus = False 

58 

59 mycb = calibrater() 

60 if parentms!= submslist[0]: 

61 for subms in submslist: 

62 mycb.open(subms, addcorr=False, addmodel=True) 

63 mycb.close() 

64 except: 

65 rstatus = False 

66 

67 casalog.filter('INFO') 

68 

69 return rstatus 

70 

71 

72def setjy(vis=None, field=None, spw=None, 

73 selectdata=None, timerange=None, scan=None, intent=None, observation=None, 

74 scalebychan=None, standard=None, model=None, 

75 listmodels=None, fluxdensity=None, spix=None, reffreq=None, polindex=None, 

76 polangle=None, rotmeas=None, fluxdict=None, 

77 useephemdir=None, interpolation=None, usescratch=None, ismms=None): 

78 """Fills the model column for flux density calibrators.""" 

79 

80 casalog.origin('setjy') 

81 casalog.post("standard="+standard,'DEBUG1') 

82 mylocals = locals() 

83 

84 if not listmodels: # listmmodels=T does not require vis  

85 sh = SetjyHelper(vis) 

86 rstat = sh.resetModelCol() 

87 

88 

89 # Take care of the trivial parallelization 

90 if ( not listmodels and ParallelDataHelper.isMMSAndNotServer(vis) and usescratch): 

91 # jagonzal: We actually operate in parallel when usescratch=True because only 

92 # in this case there is a good trade-off between the parallelization overhead 

93 # and speed up due to the load involved with MODEL_DATA column creation 

94 # Create the default MODEL columns in all sub-MSs to avoid corruption of the MMS 

95 # when there are NULL MS selections 

96 # 

97 # TT: Use ismms is used to change behavior of some of the execption handling 

98 # for MMS case. It is a hidden task parameter only modified when input vis 

99 # is identified as MMS via SetjyHelper.resetModel(). 

100 

101 #sh = SetjyHelper(vis) 

102 #rstat = sh.resetModelCol() 

103 

104 if not rstat: 

105 raise RuntimeError("Could not initialize MODEL columns in sub-MSs", 'SEVERE') 

106 

107 ismms=rstat 

108 mylocals['ismms']=ismms 

109 helper = ParallelTaskHelper('setjy', mylocals) 

110 helper._consolidateOutput = False 

111 retval = helper.go() 

112 

113 # Remove the subMS names from the returned dictionary. Pick the first dictionary from 

114 # the list of subMS dictionaries 

115 if (any(isinstance(v, dict) for v in retval.values())): 

116 for subMS in retval: 

117 dict_i = retval[subMS] 

118 # Take the first *non-empty dict* (CAS-13645) 

119 if isinstance(dict_i,dict) and dict_i: 

120 retval = dict_i 

121 break 

122 else: 

123 raise RuntimeError("Error in parallel processing of MMS, retval: {}". 

124 format(retval),'SEVERE') 

125 

126 else: 

127 retval = setjy_core(vis, field, spw, selectdata, timerange, 

128 scan, intent, observation, scalebychan, standard, model, 

129 listmodels, fluxdensity, spix, reffreq, 

130 polindex, polangle, rotmeas, fluxdict, 

131 useephemdir, interpolation, usescratch, ismms) 

132 

133 return retval 

134 

135 

136def setjy_core(vis=None, field=None, spw=None, 

137 selectdata=None, timerange=None, scan=None, intent=None, observation=None, 

138 scalebychan=None, standard=None, model=None, listmodels=None, 

139 fluxdensity=None, spix=None, reffreq=None, 

140 polindex=None, polangle=None, rotmeas=None, fluxdict=None, 

141 useephemdir=None, interpolation=None, usescratch=None, ismms=None): 

142 """Fills the model column for flux density calibrators.""" 

143 

144 retval = {} 

145 clnamelist=[] 

146 # remove componentlist generated 

147 deletecomp = True 

148 #deletecomp = False  

149 try: 

150 # Here we only list the models available, but don't perform any operation 

151 if listmodels: 

152 casalog.post("Listing model candidates (listmodels == True).") 

153 if vis: 

154 casalog.post("%s is NOT being modified." % vis) 

155 

156 if standard=='Butler-JPL-Horizons 2012': 

157 tpm_supported_objects = ['Ceres','Lutetia','Pallas','Vesta'] 

158 ssmoddirs = findCalModels(target='SolarSystemModels', 

159 exts=['.im','.ms','tab']) 

160 sstpmdirs = findCalModels(target='SolarSystemModels', 

161 exts=['.im','.ms','tab']) 

162 if ssmoddirs==set([]): 

163 casalog.post("No models were found. Missing SolarSystemModels in the CASA data directory","WARN") 

164 for d in ssmoddirs: 

165 lsmodims(d,modpat='*Tb*.dat', header='Tb models of solar system objects available for %s' % standard) 

166 for d in sstpmdirs: 

167 lsmodims(d,modpat='*fd_time.dat', header='Time variable models of asteroids available for %s [only applicable for the observation date 2014.01.01 0UT and beyond]' % standard) 

168 elif standard=='Butler-JPL-Horizons 2010': 

169 availmodellist=['Venus', 'Mars', 'Jupiter', 'Uranus', 'Neptune', 'Pluto', 

170 'Io', 'Europa', 'Ganymede', 'Callisto', 'Titan','Triton', 

171 'Ceres', 'Pallas', 'Vesta', 'Juno', 'Victoria', 'Davida'] 

172 casalog.post("Solar system objects recognized by %s:" % standard) 

173 casalog.posta(vailmodellist) 

174 else: 

175 lsmodims('.', modpat='*.im* *.mod*') 

176 calmoddirs = findCalModels() 

177 ssmoddirs=None 

178 for d in calmoddirs: 

179 lsmodims(d) 

180 

181 # Actual operation, when either the MODEL_DATA column or visibility model header are set 

182 else: 

183 if not os.path.isdir(vis): 

184 #casalog.post(vis + " must be a valid MS unless listmodels is True.", 

185 # "SEVERE") 

186 raise Exception("%s is not a valid MS" % vis) 

187 if 'Butler-JPL-Horizons' in standard and not usescratch: 

188 raise RuntimeError(f"usescratch={usescratch} and standard={standard}. " 

189 +"Virtual model can not be used for an ephemeris object calibrator. Use usescratch=True.") 

190 myms = ms() 

191 myim = imager() 

192 if ismms==None: ismms=False 

193 if type(vis) == str and os.path.isdir(vis): 

194 n_selected_rows = nselrows(vis, field, spw, observation, timerange, scan, intent, usescratch, ismms) 

195 # jagonzal: When usescratch=True, creating the MODEL column only on a sub-set of 

196 # Sub-MSs causes problems because ms::open requires all the tables in ConCatTable  

197 # to have the same description (MODEL data column must exist in all Sub-MSs) 

198 # 

199 # This is a bit of an over-doing but it is necessary for the sake of transparency 

200 # 

201 # Besides, this is also the same behavior as when running setjy vs a normal MS 

202 # 

203 # Finally, This does not affect the normal MS case because nselrows throws an 

204 # exception when the user enters an invalid data selection, but it works for the  

205 # MMS case because every sub-Ms contains a copy of the entire MMS sub-tables 

206 ##if ((not n_selected_rows) and ((not usescratch) or (standard=="Butler-JPL-Horizons 2012"))) : 

207 #mylocals = locals() 

208 #if ((not n_selected_rows) and ((usescratch) or (standard=="Butler-JPL-Horizons 2012"))) : 

209 if ((not n_selected_rows) and ((ismms) or (standard=="Butler-JPL-Horizons 2012"))) : 

210 # jagonzal: Turn this SEVERE into WARNING, as explained above 

211 casalog.post("No rows were selected.", "WARNING") 

212 return {} 

213 else: 

214 if (not n_selected_rows): 

215 raise Exception("No rows were selected. Please check your data selection") 

216 myim.open(vis, usescratch=usescratch) 

217 

218 else: 

219 raise Exception('Visibility data set not found - please verify the name') 

220 

221 # remove modimage handling to use 'model' parameter only (use modimage internally??) 

222 

223 #if modimage==None: # defined as 'hidden' with default '' in the xml 

224 # # but the default value does not seem to set so deal 

225 # # with it here... 

226 # modimage='' 

227 #if model: 

228 # modimage=model 

229 #elif not model and modimage: 

230 # casalog.post("The modimage parameter is deprecated please use model instead", "WARNING") 

231 # If modimage is not an absolute path, see if we can find exactly 1 match in the likely places. 

232 #if modimage and modimage[0] != '/': 

233 if model and model[0] != '/': 

234 cwd = os.path.abspath('.') 

235 calmoddirs = [cwd] 

236 calmoddirs += findCalModels() 

237 

238 candidates = [] 

239 for calmoddir in calmoddirs: 

240 cand = os.path.join(calmoddir,model) 

241 if os.path.isdir(cand): 

242 candidates.append(cand) 

243 if not candidates: 

244 raise RuntimeError("%s was not found for model in %s." %(model, 

245 ', '.join(calmoddirs))) 

246 

247 elif len(candidates) > 1: 

248 casalog.post("More than 1 candidate for model was found:", 

249 'SEVERE') 

250 for c in candidates: 

251 casalog.post("\t" + c, 'SEVERE') 

252 raise RuntimeError("Please pick 1 and use the absolute path (starting with /).") 

253 

254 else: 

255 model = candidates[0] 

256 casalog.post("Using %s for model." % model, 'INFO') 

257 

258 # Write the parameters to HISTORY before the tool writes anything. 

259 try: 

260 param_names = setjy.__code__.co_varnames[:setjy.__code__.co_argcount] 

261 vars = locals() 

262 param_vals = [vars[p] for p in param_names] 

263 

264 write_history(myms, vis, 'setjy', param_names, 

265 param_vals, casalog) 

266 except Exception as instance: 

267 casalog.post("*** Error \'%s\' updating HISTORY" % (instance), 

268 'WARN') 

269 

270 # Split the process for solar system objects 

271 # To maintain the behavior of SetJy such that if a flux density is specified 

272 # we use it rather than the model, we need to check the state of the  

273 # input fluxdensity JSK 10/25/2012 

274 # TT comment 07/01/2013: some what redundant as fluxdensity is moved to  

275 # a subparameter but leave fluxdensity=-1 for backward compatibility 

276 userFluxDensity = fluxdensity is not None 

277 if userFluxDensity and isinstance(fluxdensity, list): 

278 userFluxDensity = fluxdensity[0] > 0.0 

279 elif userFluxDensity: 

280 userFluxDensity = fluxdensity > 0.0 

281 

282 #in mpirun somehow subparameter defaulting does not work properly,  

283 #it seems to pick up default defined in "constraint" clause in the task xml instead 

284 #of the one defined in "param", so userFluxDensity is not reliable to use in here 

285 # (and somewhat redundant in this case). 

286 #if standard=="Butler-JPL-Horizons 2012" and not userFluxDensity: 

287 if standard=="Butler-JPL-Horizons 2012": 

288 casalog.post("Using Butler-JPL-Horizons 2012") 

289 ssmoddirs = findCalModels(target='SolarSystemModels', 

290 exts=['.im','.ms','tab']) 

291 if ssmoddirs==set([]): 

292 raise Exception("Missing Tb or fd models in the data directory") 

293 

294 setjyutil=ss_setjy_helper(myim,vis,casalog) 

295 retval=setjyutil.setSolarObjectJy(field=field,spw=spw,scalebychan=scalebychan, 

296 timerange=timerange,observation=str(observation), scan=scan, 

297 intent=intent, useephemdir=useephemdir,usescratch=usescratch) 

298 clnamelist=setjyutil.getclnamelist() 

299 

300 else: 

301 # Need to branch out the process for fluxscale since the input dictionary may  

302 # contains multiple fields. Since fluxdensity parameter is just a vector contains  

303 # IQUV flux densities and so need to run im.setjy per field  

304 

305 if standard=="fluxscale": 

306 instandard="Perley-Butler 2010" 

307 # function to return selected field, spw, etc 

308 fieldidused=parse_fluxdict(fluxdict, vis, field, spw, observation, timerange, 

309 scan, intent, usescratch) 

310 

311 if len(fieldidused): 

312 

313 retval={} 

314 for selfld in fieldidused: 

315 #selspix=fluxdict[selfld]["spidx"][1] # setjy only support alpha for now 

316 selspix=fluxdict[selfld]["spidx"][1:] # omit c0 (=log(So)) 

317 if abs(selspix[0]) > 10.0: 

318 if selspix[0] < 0: 

319 msg = 'less than -10!' 

320 else: 

321 msg = 'greater than 10!' 

322 raise Exception(f'Field {selfld}: the spectral index is {msg}') 

323 # set all (even if fluxdensity = -1 

324 if spw=='': 

325 selspw = [] 

326 invalidspw = [] 

327 for ispw in fluxdict["spwID"].tolist(): 

328 # skip spw if fluxd=-1 

329 if fluxdict[selfld][str(ispw)]["fluxd"][0]>-1: 

330 selspw.append(ispw) 

331 else: 

332 invalidspw.append(ispw) 

333 if len(invalidspw): 

334 casalog.post("Fluxdict does not contains valid fluxdensity for spw="+ 

335 str(invalidspw)+ 

336 ". Model will not set for those spws.", "WARN") 

337 else: # use spw selection 

338 selspw = ms.msseltoindex(vis,spw=spw)["spw"].tolist() 

339 

340 if fluxdict[selfld]["fitFluxd"]: 

341 selfluxd = fluxdict[selfld]["fitFluxd"] 

342 selreffreq = fluxdict[selfld]["fitRefFreq"] 

343 else: 

344 # use first selected spw's flux density  

345 selfluxd = fluxdict[selfld][str(selspw[0])]['fluxd'] 

346 # assuming the fluxscale reporting the center freq of a given spw 

347 selreffreq=fluxdict["freq"][selspw[0]] 

348 casalog.post("Use fluxdensity=%s, reffreq=%s, spix=%s" % 

349 (selfluxd,selreffreq,selspix)) 

350 curretval=myim.setjy(field=selfld,spw=selspw,modimage=model, 

351 # enable spix in list 

352 fluxdensity=selfluxd, spix=selspix, reffreq=selreffreq, 

353 #fluxdensity=selfluxd, spix=[selspix], reffreq=selreffreq,  

354 standard=instandard, scalebychan=scalebychan, 

355 polindex=polindex, polangle=polangle, rotmeas=rotmeas, 

356 time=timerange, observation=str(observation), scan=scan, 

357 intent=intent, interpolation=interpolation) 

358 retval.update(curretval) 

359 else: 

360 raise Exception("No field is selected. Check fluxdict and field selection.") 

361 else: 

362 influxdensity=fluxdensity 

363 if standard=="manual": 

364 instandard="Perley-Butler 2010" # default standard when fluxdensity=-1 or 1 

365 else: 

366 instandard=standard 

367 # From the task, fluxdensity=-1 always for standard!="manual" (but possible to  

368 # for im.setjy to run with both the stanadard and fluxdensity specified. 

369 # Until CAS-6463 is fixed, need to catch and override inconsistent parameters.  

370 if userFluxDensity and instandard!='manual': 

371 influxdensity=-1 

372 #raise Exception("Use standard=\"manual\" to set the specified fluxdensity.") 

373 casalog.post("*** fluxdensity > 0 but standard != 'manual' (possibly interaction with globals), override to set fluxdensity=-1.", 'WARN') 

374 

375 

376 if spix==[]: # handle the default  

377 spix=0.0 

378 alpha = spix[0] if isinstance(spix,list) else spix 

379 if abs(alpha) > 10.0: 

380 if alpha < -10.0: 

381 msg = 'less than -10' 

382 else: 

383 msg = 'greater than 10' 

384 raise Exception(f'The spectral index is {msg}! Please check the spix parameter.') 

385 

386 # need to modify imager to accept double array for spix 

387 retval=myim.setjy(field=field, spw=spw, modimage=model, fluxdensity=influxdensity, 

388 spix=spix, reffreq=reffreq, standard=instandard, scalebychan=scalebychan, 

389 polindex=polindex, polangle=polangle, rotmeas=rotmeas, 

390 time=timerange, observation=str(observation), scan=scan, intent=intent, 

391 interpolation=interpolation) 

392 

393 myim.close() 

394 

395 finally: 

396 if standard=='Butler-JPL-Horizons 2012': 

397 for cln in clnamelist: 

398 if deletecomp and os.path.exists(cln) and os.path.isdir(cln): 

399 shutil.rmtree(cln,True) 

400 if os.path.exists(os.path.basename(vis)+"_tmp_setjyCLfile"): 

401 shutil.rmtree(os.path.basename(vis)+"_tmp_setjyCLfile") 

402 

403 return retval 

404 

405 

406def better_glob(pats): 

407 """ 

408 Unlike ls, glob.glob('pat1 pat2') does not return  

409 the union of matches to pat1 and pat2. This does. 

410 """ 

411 retset = set([]) 

412 patlist = pats.split() 

413 for p in patlist: 

414 retset.update(glob(p)) 

415 return retset 

416 

417 

418def lsmodims(path, modpat='*', header='Candidate models'): 

419 """ 

420 Does an ls -d of files or directories in path matching modpat. 

421  

422 Header describes what is being listed. 

423 """ 

424 if os.path.isdir(path): 

425 if better_glob(os.path.join(path,modpat)): 

426 casalog.post("\n%s (%s) in %s:" % (header, modpat, path)) 

427 sys.stdout.flush() 

428 os.system('cd ' + path + ';ls -d ' + modpat) 

429 else: 

430 casalog.post("\nNo %s matching '%s' found in %s" % (header.lower(), 

431 modpat, path)) 

432 

433 

434def findCalModels(target='CalModels', 

435 roots=defaultRoots, 

436 #permexcludes = ['.svn', 'regression', 'ephemerides', 

437 permexcludes = ['regression', 'ephemerides', 

438 'geodetic', 'gui'], 

439 exts=['.ms', '.im', '.tab']): 

440 """ 

441 Returns a set of directories ending in target that are in the trees of roots. 

442 

443 Because casa['dirs']['data'] can contain a lot, and CASA tables are 

444 directories, branches matching permexcludes or exts are excluded for speed. 

445 """ 

446 

447 retset = set([]) 

448 

449 standard_locations = { 'CalModels': [ 'nrao/VLA/CalModels' ], 

450 'SolarSystemModels': [ 'alma/SolarSystemModels' ] } 

451 if target in standard_locations: 

452 for p in standard_locations[target]: 

453 candidate = ctsys.resolve(p) 

454 if os.path.isdir(candidate): 

455 retset.add(candidate) 

456 

457 if len(retset) > 0: 

458 return retset 

459 

460 # exclulde all hidden(.xxx) directories 

461 regex = re.compile('^\.\S+') 

462 # extra skip for OSX  

463 if sys.platform == "darwin": 

464 permexcludes.append('Frameworks') 

465 permexcludes.append('Library') 

466 permexcludes.append('lib') 

467 for root in roots: 

468 # Do a walk to find target directories in root. 

469 # 7/5/2011: glob('/export/data_1/casa/gnuactive/data/*/CalModels/*') doesn't work. 

470 for path, dirs, fnames in os.walk(root, followlinks=True): 

471 realpath = os.path.realpath(path) 

472 if not realpath in retset: 

473 excludes = permexcludes[:] 

474 for ext in exts: 

475 excludes += [d for d in dirs if ext in d] 

476 excludes += [m.group(0) for d in dirs for m in [regex.search(d)] if m] 

477 for d in excludes: 

478 if d in dirs: 

479 dirs.remove(d) 

480 if path.split('/')[-1] == target: 

481 # make path realpath to resolve the issue with duplicated path resulted from symlinks 

482 retset.add(realpath) 

483 return retset 

484 

485 

486def nselrows(vis, field='', spw='', obs='', timerange='', scan='', intent='', usescratch=None, ismms=False): 

487 

488 # modified to use ms.msselect. If no row is selected ms.msselect will 

489 # raise an exception - TT 2013.12.13 

490 retval = 0 

491 myms = ms() 

492 #msselargs = {'vis': vis} 

493 msselargs = {} 

494 if field: 

495 msselargs['field'] = field 

496 if spw: 

497 msselargs['spw'] = spw 

498 if intent: 

499 msselargs['scanintent'] = intent 

500 

501 # only applicable for usescratch=T 

502 if usescratch: 

503 if obs: 

504 if not type(obs) == strType: 

505 sobs = str(obs) 

506 msselargs['observation'] = sobs 

507 if timerange: 

508 msselargs['time'] = timerange 

509 if scan: 

510 msselargs['scan'] = scan 

511 else: 

512 warnstr='Data selection by ' 

513 datasels=[] 

514 if timerange: datasels.append('timerange') 

515 if scan: datasels.append('scan') 

516 if obs: datasels.append('observation') 

517 if len(datasels): 

518 warnstr+=str(datasels)+' will be ignored for usescartch=False' 

519 casalog.post(warnstr,'WARN') 

520 

521 # === skip this use ms.msselect instead ==== 

522 # ms.msseltoindex only goes by the subtables - it does NOT check 

523 # whether the main table has any rows matching the selection. 

524# try: 

525# selindices = myms.msseltoindex(**msselargs) 

526# casalog.post("msselargs=",msselargs," selindices=",selindices) 

527# except Exception, instance: 

528# casalog.post('nselrowscore exception: %s' % instance,'SEVERE') 

529# raise instance 

530# query = [] 

531# if field: 

532# query.append("FIELD_ID in " + str(selindices['field'].tolist())) 

533# if spw: 

534# query.append("DATA_DESC_ID in " + str(selindices['spw'].tolist())) 

535# if obs and usescratch: 

536# query.append("OBSERVATION_ID in " + str(selindices['obsids'].tolist())) 

537 

538 # I don't know why ms.msseltoindex takes a time argument  

539 # - It doesn't seem to appear in the output. 

540 

541# if scan and usescratch: 

542# query.append("SCAN_NUMBER in " + str(selindices['scan'].tolist())) 

543 

544 #if timerange and usescratch: 

545 # query.append("TIME in [select TIME where  

546 

547 # for intent (OBS_MODE in STATE subtable), need a subquery part... 

548# if intent: 

549# query.append("STATE_ID in [select from ::STATE where OBS_MODE==pattern(\""+\ 

550# intent+"\") giving [ROWID()]]") 

551# casalog.post("query=",query) 

552# mytb = tbtool() 

553# mytb.open(vis) 

554 myms = ms() 

555 casalog.post(str(msselargs)) 

556 myms.open(vis) 

557 

558 if (len(msselargs)==0): 

559 retval = myms.nrow() 

560 myms.close() 

561 else: 

562 try: 

563# st = mytb.query(' and '.join(query),style='python') # Does style matter here? 

564# retval = st.nrows() 

565# st.close() # needed to clear tablecache?  

566# mytb.close() 

567 myms.msselect(msselargs) 

568 retval = myms.nrow(True) 

569 

570 finally: 

571 #if ismms: 

572 # casalog.post('nselrows: %s' % instance,'WARN') 

573 #else: 

574 # this is probably redundant as the exception will be handle in setjy() 

575 #casalog.post('nselrowscore exception: %s' % instance,'SEVERE') 

576 # pass 

577 

578 myms.close() 

579 #if not ismms:  

580 # raise Exception, instance 

581 #else: 

582 # casalog.post('Proceed as it appears to be dealing with a MMS...','DEBUG') 

583 

584 return retval 

585 

586def parse_fluxdict(fluxdict, vis, field='', spw='', observation='', timerange='', scan='', intent='', usescratch=None): 

587 """ 

588 Parser function for fluxdict (dictionary output from fluxscale) to set 

589 fluxdensity, spix, and reffreq parameters (as in 'manual' mode) 

590 """ 

591 # set spix and reffreq if there  

592 

593 myms = ms() 

594 

595 # dictionary for storing modified (taking AND between the data selection 

596 # and fluxdict content) 

597 modmsselargs={} 

598 

599 msselargs={} 

600 msselargs['field']=field 

601 msselargs['spw']=spw 

602 msselargs['scanintent']=intent 

603 # only applicable for usescratch=T 

604 if usescratch: 

605 if observation: 

606 msselargs['observation'] = observation 

607 if timerange: 

608 msselargs['time'] = timerange 

609 if scan: 

610 msselargs['scan'] = scan 

611 

612 try: 

613 myms.open(vis) 

614 myms.msselect(msselargs) 

615 #selindices = myms.msselectedindices() 

616 msselfldids=myms.range(["FIELD_ID"])['field_id'] 

617 except Exception as instance: 

618 casalog.post('parse_fluxdict exception: %s' % instance,'SEVERE') 

619 raise 

620 finally: 

621 myms.close() 

622 

623 # check if fluxdict is valid 

624 if fluxdict=={}: 

625 raise Exception("fluxdict is empty") 

626 else: 

627 msg="" 

628 if not "freq" in fluxdict: 

629 msg+="freq " 

630 if not "spwID" in fluxdict: 

631 msg+="spwID " 

632 if len(msg): 

633 raise Exception("Input fluxdict is missing keywords:"+msg) 

634 

635 # select fields only common to the dictionary and field selection 

636 fieldids=[] 

637 for ky in fluxdict.keys(): 

638 try: 

639 int(ky) 

640 fieldids.append(ky) # list in string field ids 

641 except: 

642 pass 

643 if not len(fieldids): 

644 casalog.post('No field ids was found in the dictionary given for fluxdict. Please check the input.', 'SEVERE') 

645 

646 

647 #if len(selindices['field']): 

648 if len(msselfldids): 

649 # also check there is common field id, note field ids in selindices are in numpy.array 

650 #selfieldids = [fd for fd in fieldids if int(fd) in selindices['field'].tolist()] 

651 selfieldids = [fd for fd in fieldids if int(fd) in msselfldids] 

652 if not len(selfieldids): 

653 raise Exception("No field was found in fluxdict for the given data selection") 

654 else: 

655 selfieldids = fieldids 

656 

657 return selfieldids