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

2054 statements  

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

1 

2import glob 

3import os 

4import math 

5import numpy 

6import re 

7import shutil 

8import pwd 

9from numpy import unique 

10 

11import subprocess 

12from collections import OrderedDict as odict 

13 

14###some helper tools 

15from casatasks import casalog as default_casalog 

16from casatools import table, quanta, measures, regionmanager, image, imager, msmetadata 

17from casatools import ms as mstool 

18from casatools import ctsys 

19 

20ms = mstool( ) 

21tb = table( ) 

22qa = quanta( ) 

23me = measures( ) 

24rg = regionmanager( ) 

25ia = image( ) 

26im = imager( ) 

27msmd=msmetadata( ) 

28 

29# trying to avoid sharing a single instance with all other functions in this module 

30iatool = image 

31 

32def _casa_version_string(): 

33 """ produce a version string with the same format as the mstools.write_history. """ 

34 return 'version: ' + ctsys.version_string() + ' ' + ctsys.version_desc() 

35 

36 

37class cleanhelper: 

38 def __init__(self, imtool='', vis='', usescratch=False, casalog=default_casalog): 

39 """ 

40 Contruct the cleanhelper object with an imager tool 

41 like so: 

42 a=cleanhelper(im, vis) 

43 """ 

44 ###fix for assumption that if it is a list of 1 it is sngle ms mode 

45 if((type(vis)==list) and (len(vis)==1)): 

46 vis=vis[0] 

47 #### 

48 if((type(imtool) != str) and (len(vis) !=0)): 

49 # for multi-mses input (not fully implemented yet) 

50 if(type(vis)!=list): 

51 vis=[vis] 

52 self.sortedvisindx=[0] 

53 self.initmultims(imtool, vis, usescratch) 

54 # else: 

55 # self.initsinglems(imtool, vis, usescratch) 

56 #self.maskimages={} 

57 self.maskimages=odict( ) 

58 self.finalimages={} 

59 self.usescratch=usescratch 

60 self.dataspecframe='LSRK' 

61 self.usespecframe='' 

62 self.inframe=False 

63 # to use phasecenter parameter in initChannelizaiton stage 

64 # this is a temporary fix need.  

65 self.srcdir='' 

66 # for multims handling 

67 self.sortedvislist=[] 

68 if not casalog: # Not good! 

69 casalog = default_casalog 

70 #casalog.setglobal(True) 

71 self._casalog = casalog 

72 

73 @staticmethod 

74 def getsubtable(visname='', subtab='SPECTRAL_WINDOW'): 

75 """needed because mms has it somewhere else 

76 """ 

77 tb.open(visname) 

78 spectable=str.split(tb.getkeyword(subtab)) 

79 

80 if(len(spectable) ==2): 

81 spectable=spectable[1] 

82 else: 

83 spectable=visname+"/"+subtab 

84 return spectable 

85 

86 @staticmethod 

87 def checkimageusage(imagename=''): 

88 """ 

89 check if images which will be written into is open elsewhere 

90 """ 

91 retval=[] 

92 if(imagename=='' or imagename==[]): 

93 return retval 

94 images=[] 

95 if(type(imagename)==str): 

96 images=[imagename] 

97 elif(type(imagename)==list): 

98 images=imagename 

99 for ima in images: 

100 for postfix in ['.model', '.image', '.residual', '.mask'] : 

101 diskim=ima+postfix 

102 if(os.path.exists(diskim)): 

103 tb.open(diskim) 

104 if(tb.ismultiused()): 

105 retval.append(diskim) 

106 tb.done() 

107 return retval 

108 

109 

110 def initsinglems(self, imtool, vis, usescratch): 

111 """ 

112 initialization for single ms case 

113 """ 

114 self.im=imtool 

115 # modified for self.vis to be a list for handling multims 

116 #self.vis=vis 

117 self.vis=[vis] 

118 self.sortedvisindx=[0] 

119 

120 if ((type(vis)==str) & (os.path.exists(vis))): 

121 self.im.open(vis, usescratch=usescratch) 

122 else: 

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

124 self.phasecenter='' 

125 self.spwindex=-1 

126 self.fieldindex=-1 

127 self.outputmask='' 

128 self.csys={} 

129 

130 def initmultims(self, imtool, vislist, usescratch): 

131 """ 

132 initialization for multi-mses  

133 """ 

134 self.im=imtool 

135 self.vis=vislist 

136 if type(vislist)==list: 

137 # self.im.selectvis(vis) 

138 if ((type(self.vis[0])==str) & (os.path.exists(self.vis[0]))): 

139 pass 

140 else: 

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

142 self.phasecenter='' 

143 self.spwindex=-1 

144 self.fieldindex=-1 

145 self.outputmask='' 

146 self.csys={} 

147 

148 def sortvislist(self,spw,mode,width): 

149 """ 

150 sorting user input vis if it is multiple MSes based on 

151 frequencies (spw). So that in sebsequent processing such 

152 as setChannelization() correctly works. 

153 Returns sorted vis. name list 

154 """ 

155 import operator 

156 reverse=False 

157 if mode=='velocity': 

158 if qa.quantity(width)['value']>0: 

159 reverse=True 

160 elif mode=='frequency': 

161 if qa.quantity(width)['value']<0: 

162 reverse=True 

163 minmaxfs = [] 

164 # get selection 

165 if len(self.vis) > 1: 

166 for i in range(len(self.vis)): 

167 visname = self.vis[i] 

168 if type(spw)==list and len(spw) > 1: 

169 inspw=spw[i] 

170 else: 

171 inspw=spw 

172 if len(inspw)==0: 

173 # empty string = select all (='*', for msselectindex) 

174 inspw='*' 

175 mssel=ms.msseltoindex(vis=visname,spw=inspw) 

176 spectable=self.getsubtable(visname, "SPECTRAL_WINDOW") 

177 tb.open(spectable) 

178 chanfreqs=tb.getvarcol('CHAN_FREQ') 

179 tb.close() 

180 kys = list(chanfreqs.keys()) 

181 selspws=mssel['spw'] 

182 # find extreme freq in each selected spw 

183 minmax0=0. 

184 firstone=True 

185 minmaxallspw=0. 

186 for chansel in mssel['channel']: 

187 if reverse: 

188 minmaxf = max(chanfreqs[kys[chansel[0]]][chansel[1]:chansel[2]+1]) 

189 else: 

190 minmaxf = min(chanfreqs[kys[chansel[0]]][chansel[1]:chansel[2]+1]) 

191 if firstone: 

192 minmaxf0=minmaxf 

193 firstone=False 

194 if reverse: 

195 minmaxallspw=max(minmaxf,minmaxf0) 

196 else: 

197 minmaxallspw=min(minmaxf,minmaxf0) 

198 minmaxfs.append(minmaxallspw) 

199 self.sortedvisindx = [x for x, y in sorted(enumerate(minmaxfs), 

200 key=operator.itemgetter(1),reverse=reverse)] 

201 self.sortedvislist = [self.vis[k] for k in self.sortedvisindx] 

202 else: 

203 self.sortedvisindx=[0] 

204 self.sortedvislist=self.vis 

205 #casalog.post("sortedvislist=" + self.sortedvislist) 

206 #casalog.post("sortedvisindx=" + self.sortedvisindx) 

207 return 

208 

209 

210 def defineimages(self, imsize, cell, stokes, mode, spw, nchan, start, 

211 width, restfreq, field, phasecenter, facets=1, outframe='', 

212 veltype='radio'): 

213 """ 

214 Define image parameters -calls im.defineimage. 

215 for processing a single field  

216 (also called by definemultiimages for multifield)  

217 """ 

218 if((type(cell)==list) and (len(cell)==1)): 

219 cell.append(cell[0]) 

220 elif ((type(cell)==str) or (type(cell)==int) or (type(cell)==float)): 

221 cell=[cell, cell] 

222 elif (type(cell) != list): 

223 raise TypeError("parameter cell %s is not understood" % str(cell)) 

224 cellx=qa.quantity(cell[0], 'arcsec') 

225 celly=qa.quantity(cell[1], 'arcsec') 

226 if(cellx['unit']==''): 

227 #string with no units given 

228 cellx['unit']='arcsec' 

229 if(celly['unit']==''): 

230 #string with no units given 

231 celly['unit']='arcsec' 

232 if((type(imsize)==list) and (len(imsize)==1)): 

233 imsize.append(imsize[0]) 

234 elif(type(imsize)==int): 

235 imsize=[imsize, imsize] 

236 elif(type(imsize) != list): 

237 raise TypeError("parameter imsize %s is not understood" % str(imsize)) 

238 

239 elstart=start 

240 if(mode=='frequency'): 

241 ##check that start and step have units 

242 if(qa.quantity(start)['unit'].find('Hz') < 0): 

243 raise TypeError("start parameter %s is not a valid frequency quantity " % str(start)) 

244 ###make sure we respect outframe 

245 if(self.usespecframe != ''): 

246 elstart=me.frequency(self.usespecframe, start) 

247 if(qa.quantity(width)['unit'].find('Hz') < 0): 

248 raise TypeError("width parameter %s is not a valid frequency quantity " % str(width)) 

249 elif(mode=='velocity'): 

250 ##check that start and step have units 

251 if(qa.quantity(start)['unit'].find('m/s') < 0): 

252 raise TypeError("start parameter %s is not a valid velocity quantity " % str(start)) 

253 ###make sure we respect outframe 

254 if(self.usespecframe != ''): 

255 elstart=me.radialvelocity(self.usespecframe, start) 

256 if(qa.quantity(width)['unit'].find('m/s') < 0): 

257 raise TypeError("width parameter %s is not a valid velocity quantity " % str(width)) 

258 else: 

259 if((type(width) != int) or 

260 (type(start) != int)): 

261 raise TypeError("start (%s), width (%s) have to be integers with mode %s" % (str(start),str(width),mode)) 

262 

263 # changes related multims handling added below (TT) 

264 # multi-mses are sorted internally (stored in self.sortedvislist and 

265 # indices in self.sortedvisindx) in frequency-wise so that first vis 

266 # contains lowest/highest frequency. Note: self.vis is in original user input order. 

267 #####understand phasecenter 

268 if(type(phasecenter)==str): 

269 ### blank means take field[0] 

270 if (phasecenter==''): 

271 fieldoo=field 

272 if(fieldoo==''): 

273 msmd.open(self.vis[self.sortedvisindx[0]]) 

274 allfields=msmd.fieldsforintent('*') 

275 fieldoo=str(allfields[0]) if(len(allfields) >0) else '0' 

276 msmd.done() 

277 #phasecenter=int(ms.msseltoindex(self.vis,field=fieldoo)['field'][0]) 

278 phasecenter=int(ms.msseltoindex(self.vis[self.sortedvisindx[0]],field=fieldoo)['field'][0]) 

279 msmd.open(self.vis[self.sortedvisindx[0]]) 

280 phasecenter=msmd.phasecenter(phasecenter) 

281 msmd.done() 

282 else: 

283 tmppc=phasecenter 

284 try: 

285 #if(len(ms.msseltoindex(self.vis, field=phasecenter)['field']) > 0): 

286 # tmppc = int(ms.msseltoindex(self.vis, 

287 # field=phasecenter)['field'][0]) 

288 # to handle multims set to the first ms that matches 

289 for i in self.sortedvisindx: 

290 try: 

291 if(len(ms.msseltoindex(self.vis[i], field=phasecenter)['field']) > 0): 

292 tmppc = int(ms.msseltoindex(self.vis[i], 

293 field=phasecenter)['field'][0]) 

294 # casalog.post("tmppc,i=" + tmppc, i) 

295 except Exception: 

296 pass 

297 

298 ##succesful must be string like '0' or 'NGC*' 

299 except Exception: 

300 ##failed must be a string 'J2000 18h00m00 10d00m00' 

301 tmppc = phasecenter 

302 phasecenter = tmppc 

303 self.phasecenter = phasecenter 

304 #casalog.post('cell' + cellx + celly + restfreq) 

305 ####understand spw 

306 if spw in (-1, '-1', '*', '', ' '): 

307 spwindex = -1 

308 else: 

309 # old, single ms case 

310 #spwindex=ms.msseltoindex(self.vis, spw=spw)['spw'].tolist() 

311 #if(len(spwindex) == 0): 

312 # spwindex = -1 

313 #self.spwindex = spwindex 

314 

315 # modified for multims hanlding 

316 # multims case 

317 if len(self.vis)>1: 

318 self.spwindex=[] 

319 # will set spwindex in datsel 

320 spwindex=-1 

321 for i in self.sortedvisindx: 

322 if type(spw)==list: 

323 inspw=spw[i] 

324 else: 

325 inspw=spw 

326 if len(inspw)==0: 

327 inspw='*' 

328 self.spwindex.append(ms.msseltoindex(self.vis[i],spw=inspw)['spw'].tolist()) 

329 # single ms 

330 else: 

331 spwindex=ms.msseltoindex(self.vis[0], spw=spw)['spw'].tolist() 

332 if(len(spwindex) == 0): 

333 spwindex = -1 

334 self.spwindex = spwindex 

335 

336 ##end spwindex 

337 

338 if self.usespecframe=='': 

339 useframe=self.dataspecframe 

340 else: 

341 useframe=self.usespecframe 

342 

343 self.im.defineimage(nx=imsize[0], ny=imsize[1], 

344 cellx=cellx, celly=celly, 

345 mode=mode, nchan=nchan, 

346 start=elstart, step=width, 

347 spw=spwindex, stokes=stokes, 

348 restfreq=restfreq, outframe=useframe, 

349 veltype=veltype, phasecenter=phasecenter, 

350 facets=facets) 

351 

352 def definemultiimages(self, rootname, imsizes, cell, stokes, mode, spw, 

353 nchan, start, width, restfreq, field, phasecenters, 

354 names=[], facets=1, outframe='', veltype='radio', 

355 makepbim=False, checkpsf=False): 

356 """ 

357 Define image parameters - multiple field version 

358 This fucntion set "private" variables (imagelist and imageids), 

359 and then calls defineimages for ecah field.  

360 """ 

361 #will do loop in reverse assuming first image is main field 

362 if not hasattr(imsizes, '__len__'): 

363 imsizes = [imsizes] 

364 self.nimages=len(imsizes) 

365 #if((len(imsizes)<=2) and ((type(imsizes[0])==int) or 

366 # (type(imsizes[0])==long))): 

367 if((len(imsizes)<=2) and (numpy.issubdtype(type(imsizes[0]), int))): 

368 self.nimages=1 

369 if(len(imsizes)==2): 

370 imsizes=[(imsizes[0], imsizes[1])] 

371 else: 

372 imsizes=[(imsizes[0], imsizes[0])] 

373 self._casalog.post('Number of images: ' + str(self.nimages), 'DEBUG1') 

374 

375 #imagelist is to have the list of image model names 

376 self.imagelist={} 

377 #imageids is to tag image to mask in aipsbox style file  

378 self.imageids={} 

379 if(type(phasecenters) == str): 

380 phasecenters=[phasecenters] 

381 if(type(phasecenters) == int or type(phasecenters) == float ): 

382 phasecenters=[phasecenters] 

383 self._casalog.post('Number of phase centers: ' + str(len(phasecenters)), 

384 'DEBUG1') 

385 

386 if((self.nimages==1) and (type(names)==str)): 

387 names=[names] 

388 if((len(phasecenters)) != (len(imsizes))): 

389 errmsg = "Mismatch between the number of phasecenters (%d), image sizes (%d) , and images (%d)" % (len(phasecenters), len(imsizes), self.nimages) 

390 self._casalog.post(errmsg, 'SEVERE') 

391 raise ValueError(errmsg) 

392 self.skipclean=False 

393 lerange=range(self.nimages) 

394 lerange.reverse() 

395 for n in lerange: 

396 self.defineimages(list(imsizes[n]), cell, stokes, mode, spw, nchan, 

397 start, width, restfreq, field, phasecenters[n], 

398 facets,outframe,veltype) 

399 if(len(names)==self.nimages): 

400 self.imageids[n]=names[n] 

401 if(rootname != ''): 

402 self.imagelist[n]=rootname+'_'+names[n] 

403 else: 

404 self.imagelist[n]=names[n] 

405 else: 

406 self.imagelist[n]=rootname+'_'+str(n) 

407 ###make the image only if it does not exits 

408 ###otherwise i guess you want to continue a clean 

409 if(not os.path.exists(self.imagelist[n])): 

410 self.im.make(self.imagelist[n]) 

411 #if(makepbim and n==0): 

412 if(makepbim): 

413 ##make .flux image  

414 # for now just make for a main field  

415 ###need to get the pointing so select the fields 

416 # single ms 

417# if len(self.vis)==1: 

418# self.im.selectvis(field=field,spw=spw) 

419# # multi-ms 

420# else:  

421# if len(self.vis) > 1: 

422# # multi-mses case: use first vis that has the specified field 

423# # (use unsorted vis list) 

424# nvis=len(self.vis) 

425# for i in range(nvis): 

426# #if type(field)!=list: 

427# # field=[field] 

428# try: 

429# selparam=self._selectlistinputs(nvis,i,self.paramlist) 

430# self.im.selectvis(vis=self.vis[i],field=selparam['field'],spw=selparam['spw']) 

431# except: 

432# pass 

433 

434 # set to default minpb(=0.1), should use input minpb? 

435 self.im.setmfcontrol() 

436 self.im.setvp(dovp=True) 

437 self.im.makeimage(type='pb', image=self.imagelist[n]+'.flux', 

438 compleximage="", verbose=False) 

439 self.im.setvp(dovp=False, verbose=False) 

440 

441 

442 def checkpsf(self,chan): 

443 """ 

444 a check to make sure selected channel plane is not entirely flagged 

445 (for chinter=T interactive clean) 

446 """ 

447 #lerange=range(self.nimages) 

448 #lerange.reverse() 

449 #for n in lerange: 

450 # self.getchanimage(self.finalimages[n]+'.psf',self.imagelist[n]+'.test.psf',chan) 

451 # ia.open(self.imagelist[n]+'.test.psf') 

452 # imdata=ia.getchunk() 

453 # casalog.post("imagelist[", n, "]=" + self.imagelist[n] + " imdata.sum()=" + imdata.sum()) 

454 #if n==0 and imdata.sum()==0.0: 

455 # self.skipclean=True  

456 # if self.skipclean: 

457 # pass 

458 # elif imdata.sum()==0.0: 

459 # self.skipclean=True 

460 

461 # need to check only for main field 

462 self.getchanimage(self.finalimages[0]+'.psf',self.imagelist[0]+'.test.psf',chan) 

463 ia.open(self.imagelist[0]+'.test.psf') 

464 imdata=ia.getchunk() 

465 if imdata.sum()==0.0: 

466 self.skipclean=True 

467 

468 

469 def makeEmptyimages(self): 

470 """ 

471 Create empty images (0.0 pixel values) for  

472 image, residual, psf 

473 must run after definemultiimages() 

474 and it is assumed that definemultiimages creates  

475 empty images (self.imagelist).  

476 """ 

477 lerange=range(self.nimages) 

478 for n in lerange: 

479 os.system('cp -r '+self.imagelist[n]+' '+self.imagelist[n]+'.image') 

480 os.system('cp -r '+self.imagelist[n]+' '+self.imagelist[n]+'.residual') 

481 os.system('cp -r '+self.imagelist[n]+' '+self.imagelist[n]+'.psf') 

482 os.system('cp -r '+self.imagelist[n]+' '+self.imagelist[n]+'.model') 

483 os.system('cp -r '+self.imagelist[n]+' '+self.imagelist[n]+'.mask') 

484 

485 

486 def makemultifieldmask(self, maskobject=''): 

487 """ 

488 This function assumes that the function definemultiimages has been run and thus 

489 self.imagelist is defined 

490 if single image use the single image version 

491 (this is not up to date for current mask handling but used in task_widefield, 

492 to be removed after task_widefield is gone) 

493 """ 

494 if((len(self.maskimages)==(len(self.imagelist)))): 

495 if(self.imagelist[0] not in self.maskimages): 

496 self.maskimages={} 

497 else: 

498 self.maskimages={} 

499 masktext=[] 

500 if (not hasattr(maskobject, '__len__')) \ 

501 or (len(maskobject) == 0) or (maskobject == ['']): 

502 return 

503 if(type(maskobject)==str): 

504 maskobject=[maskobject] 

505 if(type(maskobject) != list): 

506 ##don't know what to do with this 

507 raise TypeError('Dont know how to deal with mask object') 

508 n=0 

509 for masklets in maskobject: 

510 if(type(masklets)==str): 

511 if(os.path.exists(masklets)): 

512 if(subprocess.getoutput('file '+masklets).count('directory')): 

513 self.maskimages[self.imagelist[n]]=masklets 

514 n=n+1 

515 elif(subprocess.getoutput('file '+masklets).count('text')): 

516 masktext.append(masklets) 

517 else: 

518 raise TypeError('Can only read text mask files or mask images') 

519 else: 

520 raise TypeError(masklets+' seems to be non-existant') 

521 if(len(masktext) > 0): 

522 circles, boxes=self.readmultifieldboxfile(masktext) 

523 if(len(self.maskimages)==0): 

524 for k in range(len(self.imageids)): 

525 if(self.imagelist[k] not in self.maskimages): 

526 self.maskimages[self.imagelist[k]]=self.imagelist[k]+'.mask' 

527 for k in range(len(self.imageids)): 

528 ###initialize mask if its not there yet 

529 if(not (os.path.exists(self.maskimages[self.imagelist[k]]))): 

530 ia.fromimage(outfile=self.maskimages[self.imagelist[k]], 

531 infile=self.imagelist[k]) 

532 ia.open(self.maskimages[self.imagelist[k]]) 

533 ia.set(pixels=0.0) 

534 ia.done(verbose=False) 

535 if(self.imageids[k] in circles and self.imageids[k] in boxes): 

536 self.im.regiontoimagemask(mask=self.maskimages[self.imagelist[k]], 

537 boxes=boxes[self.imageids[k]], 

538 circles=circles[self.imageids[k]]) 

539 elif(self.imageids[k] in circles): 

540 self.im.regiontoimagemask(mask=self.maskimages[self.imagelist[k]], 

541 circles=circles[self.imageids[k]]) 

542 elif(self.imageids[k] in boxes): 

543 self.im.regiontoimagemask(mask=self.maskimages[self.imagelist[k]], 

544 boxes=boxes[self.imageids[k]]) 

545 else: 

546 ###need to make masks that select that whole image 

547 ia.open(self.maskimages[self.imagelist[k]]) 

548 ia.set(pixels=1.0) 

549 ia.done(verbose=False) 

550 

551 

552 def makemultifieldmask2(self, maskobject='',slice=-1, newformat=True, interactive=False): 

553 

554 """ 

555 Create mask images for multiple fields (flanking fields)  

556 This new makemultifieldmask to accomodate different kinds of masks supported 

557 in clean with flanking fields. 

558 

559 Keyword arguments: 

560 maskobject -- input mask, a list (of string or of list(s)) or a string  

561 slice -- channel slice (to handle chaniter mode): default = -1 (all) 

562 newformat -- if mask is read from new format text file: default = True  

563 

564 Prerequiste: definemultiimages has already ran so that imagelist is defined  

565  

566 Notes:  

567 * It makes empty mask images at begenning, calls makemaskimage, and if no 

568 mask to be specified, the corresponding empty mask image is removed 

569  

570 * When clean is executed in commnad line style (e.g. clean(vis='..', ..)) 

571 it is possible to have mask parameter consists of a mix of strings and int lists 

572 (i.e. mask=[['newreg.txt',[55,55,65,70]],['outliermask.rgn']]), and this function 

573 should be able to parse these properly. - although this won't work for the task execution 

574 by go() and tends to messed up inp() after such execution  

575  

576 * Currently it is made to handle old outlier text file format and boxfile-style 

577 mask box specification for backward compartibility. But it is planned to 

578 be removed for 3.4. 

579 

580 * This is a refactored version of the previous makemultifieldmask2 

581 and calls makemaskimage() for each field.  

582 this was called makemultifieldmask3 in CASA 3.3 release but now renamed  

583 makemultifieldmask2 as the previous makemultifieldmask2 was removed. 

584 """ 

585 #casalog.post("Inside makemultifieldmask2") 

586 if((len(self.maskimages)==(len(self.imagelist)))): 

587 if(self.imagelist[0] not in self.maskimages): 

588 self.maskimages=odict() 

589 else: 

590 self.maskimages=odict() 

591 # clean up temp mask image  

592 if os.path.exists('__tmp_mask'): 

593 shutil.rmtree('__tmp_mask') 

594 

595 if (not hasattr(maskobject, '__len__')) \ 

596 or (len(maskobject) == 0) or (maskobject == ['']): 

597 return 

598 # for empty maskobject list  

599 if all([msk==[''] or msk==[] for msk in maskobject]): 

600 return 

601 # determine number of input elements 

602 if (type(maskobject)==str): 

603 maskobject=[maskobject] 

604 if(type(maskobject) != list): 

605 ##don't know what to do with this 

606 raise TypeError('Dont know how to deal with maskobject with type: %s' % type(maskobject)) 

607 #if(type(maskobject[0])==int or type(maskobject[0])==float): 

608 if(numpy.issubdtype(type(maskobject[0]),int) or numpy.issubdtype(type(maskobject[0]),float)): 

609 maskobject=[maskobject] 

610 if(type(maskobject[0][0])==list): 

611 #if(type(maskobject[0][0][0])!=int and type(maskobject[0][0][0])!=float):  

612 if not (numpy.issubdtype(type(maskobject[0][0][0]),int) or \ 

613 numpy.issubdtype(type(maskobject[0][0][0]),float)): 

614 maskobject=maskobject[0] 

615 

616 # define maskimages 

617 if(len(self.maskimages)==0): 

618 for k in range(len(self.imageids)): 

619 if(self.imagelist[k] not in self.maskimages): 

620 self.maskimages[self.imagelist[k]]=self.imagelist[k]+'.mask' 

621 # initialize maskimages - create empty maskimages 

622 # --- use outframe or dataframe for mask creation 

623 # * It appears somewhat duplicating with makemaskimage  

624 # but it is necessary to create a maskimage for 

625 # each field at this point...  

626 if self.usespecframe=='': 

627 maskframe=self.dataspecframe 

628 else: 

629 maskframe=self.usespecframe 

630 #casalog.post("Frame : " + maskframe) 

631 #casalog.post("dataframe : " + self.dataspecframe + " useframe : " + self.usespecframe) 

632 for k in range(len(self.imagelist)): 

633 if(not (os.path.exists(self.maskimages[self.imagelist[k]]))): 

634 ia.fromimage(outfile=self.maskimages[self.imagelist[k]], 

635 infile=self.imagelist[k]) 

636 ia.open(self.maskimages[self.imagelist[k]]) 

637 ia.set(pixels=0.0) 

638 #mcsys=ia.coordsys().torecord() 

639 #if mcsys['spectral2']['conversion']['system']!=maskframe: 

640 # mcsys['spectral2']['conversion']['system']=maskframe 

641 #ia.setcoordsys(mcsys) 

642 # 

643 ## This code to set the maskframe is copied from makemaskimages() 

644# mycsys=ia.coordsys() 

645# if mycsys.torecord()['spectral2']['conversion']['system']!=maskframe: 

646# mycsys.setreferencecode(maskframe,'spectral',True) 

647# self.csys=mycsys.torecord() 

648# if self.csys['spectral2']['conversion']['system']!=maskframe: 

649# self.csys['spectral2']['conversion']['system']=maskframe 

650# ia.setcoordsys(self.csys) 

651 

652 ia.done(verbose=False) 

653 

654 self.setReferenceFrameLSRK(img =self.maskimages[self.imagelist[k]]) 

655 

656 # take out extra []'s 

657 maskobject=self.flatten(maskobject) 

658 masktext=[] 

659 # to keep backward compatibility for a mixed outlier file 

660 # look for boxfiles contains multiple boxes with image ids 

661 for maskid in range(len(maskobject)): 

662 if type(maskobject[maskid])==str: 

663 maskobject[maskid] = [maskobject[maskid]] 

664 

665 for masklets in maskobject[maskid]: 

666 if type(masklets)==str: 

667 if (os.path.exists(masklets) and 

668 (not subprocess.getoutput('file '+masklets).count('directory')) and 

669 (not subprocess.getoutput('file '+masklets).split(':')[-1].count('data'))): 

670 # extract boxfile name 

671 masktext.append(masklets) 

672 

673 # === boxfile handling === 

674 #extract boxfile mask info only for now the rest is 

675 #processed by makemaskimage. - DEPRECATED and will be removed  

676 #in 3.4 

677 # 

678 #group circles and boxes in dic for each image field  

679 circles, boxes, oldfmts=self.readmultifieldboxfile(masktext) 

680 

681 # Loop over imagename 

682 # take out text file names contain multifield boxes and field info  

683 # from maskobject and create updated one (updatedmaskobject) 

684 # by adding boxlists to it instead. 

685 # Use readmultifieldboxfile to read old outlier/box text file format 

686 # Note: self.imageids and boxes's key are self.imagelist for new outlier 

687 # format while for the old format, they are 'index' in string. 

688 

689 #maskobject_tmp = maskobject  

690 # need to do a deep copy 

691 import copy 

692 maskobject_tmp=copy.deepcopy(maskobject) 

693 updatedmaskobject = [] 

694 for maskid in range(len(maskobject_tmp)): 

695 if len(circles)!=0 or len(boxes)!=0: 

696 # remove the boxfiles from maskobject list 

697 for txtf in masktext: 

698 if maskobject_tmp[maskid].count(txtf) and oldfmts[txtf]: 

699 maskobject_tmp[maskid].remove(txtf) 

700 updatedmaskobject = maskobject_tmp 

701 else: 

702 updatedmaskobject = maskobject 

703 # adjust no. of elements of maskoject list with [] 

704 if len(updatedmaskobject)-len(self.imagelist)<0: 

705 for k in range(len(self.imagelist)-len(updatedmaskobject)): 

706 updatedmaskobject.append([]) 

707 #for maskid in range(len(self.maskimages)): 

708 

709 # === boxfile handling ==== 

710 for maskid in self.maskimages.keys(): 

711 # for handling old format 

712 #if nmaskobj <= maskid: 

713 # add circles,boxes back 

714 maskindx = self.maskimages.keys().index(maskid) 

715 if len(circles) != 0: 

716 for key in circles: 

717 if (newformat and maskid==key) or \ 

718 (not newformat and maskid.split('_')[-1]==key): 

719 if len(circles[key])==1: 

720 incircles=circles[key][0] 

721 else: 

722 incircles=circles[key] 

723 # put in imagelist order 

724 if len(incircles)>1 and isinstance(incircles[0],list): 

725 updatedmaskobject[self.imagelist.values().index(maskid)].extend(incircles) 

726 else: 

727 updatedmaskobject[self.imagelist.values().index(maskid)].append(incircles) 

728 if len(boxes) != 0: 

729 for key in boxes: 

730 #try:  

731 # keyid=int(key) 

732 #except: 

733 # keyid=key 

734 if (newformat and maskid==key) or \ 

735 (not newformat and maskid.split('_')[-1]==key): 

736 if len(boxes[key])==1: 

737 inboxes=boxes[key][0] 

738 else: 

739 inboxes=boxes[key] 

740 # add to maskobject (extra list bracket taken out) 

741 # put in imagelist order 

742 # take out extra [] 

743 if len(inboxes)>1 and isinstance(inboxes[0],list): 

744 updatedmaskobject[self.imagelist.values().index(maskid)].extend(inboxes) 

745 else: 

746 updatedmaskobject[self.imagelist.values().index(maskid)].append(inboxes) 

747 # === boxfile handling ==== 

748 

749 # do maskimage creation (call makemaskimage) 

750 for maskid in range(len(self.maskimages)): 

751 if maskid < len(updatedmaskobject): 

752 self._casalog.post("Matched masks: maskid=%s mask=%s" % (maskid, updatedmaskobject[maskid]), 'DEBUG1') 

753 self.outputmask='' 

754 self.makemaskimage(outputmask=self.maskimages[self.imagelist[maskid]], 

755 imagename=self.imagelist[maskid], maskobject=updatedmaskobject[maskid], slice=slice) 

756# self._casalog.post("Matched masks: maskid=%s mask=%s" % (maskid, updatedmaskobject[maskid]), 'DEBUG1') 

757# self.outputmask='' 

758# self.makemaskimage(outputmask=self.maskimages[self.imagelist[maskid]],  

759# imagename=self.imagelist[maskid], maskobject=updatedmaskobject[maskid], slice=slice) 

760 

761 for key in self.maskimages.keys(): 

762 if(os.path.exists(self.maskimages[key])): 

763 ia.open(self.maskimages[key]) 

764 fsum=ia.statistics(verbose=False,list=False)['sum'] 

765 if(len(fsum)!=0 and fsum[0]==0.0): 

766 # make an empty mask 

767 ia.set(pixels=0.0) 

768 # should not remove empty mask for multifield case 

769 # interactive=F. 

770 # Otherwise makemaskimage later does not work 

771 # remove the empty mask 

772 if not interactive: 

773 ia.remove() 

774 ia.done(verbose=False) 

775 

776 

777 def make_mask_from_threshhold(self, imagename, thresh, outputmask=None): 

778 """ 

779 Makes a mask image with the same coords as imagename where each 

780 pixel is True if and only if the corresponding pixel in imagename 

781 is >= thresh. 

782 

783 The mask will be named outputmask (if provided) or imagename + 

784 '.thresh_mask'. The name is returned on success, or False on failure. 

785 """ 

786 if not outputmask: 

787 outputmask = imagename + '.thresh_mask' 

788 

789 # im.mask would be a lot shorter, but it (unnecessarily) needs im to be 

790 # open with an MS. 

791 # I am not convinced that im.mask should really be using Quantity. 

792 # qa.quantity(quantity) = quantity. 

793 self.im.mask(imagename, outputmask, qa.quantity(thresh)) 

794 

795 ## # Copy imagename to a safe name to avoid problems with /, +, -, and ia. 

796 ## ia.open(imagename) 

797 ## shp = ia.shape() 

798 ## ia.close() 

799 ## self.copymaskimage(imagename, shp, '__temp_mask') 

800 

801 ## self.copymaskimage(imagename, shp, outputmask) 

802 ## ia.open(outputmask) 

803 ## ###getchunk is a mem hog 

804 ## #arr=ia.getchunk() 

805 ## #arr[arr>0.01]=1 

806 ## #ia.putchunk(arr) 

807 ## #inpix="iif("+"'"+outputmask.replace('/','\/')+"'"+">0.01, 1, 0)" 

808 ## #ia.calc(pixels=inpix) 

809 ## ia.calc(pixels="iif(__temp_mask>" + str(thresh) + ", 1, 0)") 

810 ## ia.close() 

811 ## ia.removefile('__temp_mask') 

812 return outputmask 

813 

814 def makemaskimage(self, outputmask='', imagename='', maskobject=[], slice=-1): 

815 """ 

816 This function is an attempt to convert all the kind of 'masks' that 

817 people want to throw at it and convert it to a mask image to be used 

818 by imager...For now 'masks' include 

819  

820 a)set of previous mask images 

821 b)lists of blc trc's 

822 c)record output from rg tool for e.g 

823 

824 * for a single field  

825 """ 

826 if (not hasattr(maskobject, '__len__')) \ 

827 or (len(maskobject) == 0) or (maskobject == ['']): 

828 return 

829 maskimage=[] 

830 masklist=[] 

831 textreglist=[] 

832 masktext=[] 

833 maskrecord={} 

834 tablerecord=[] 

835 # clean up any left over temp files from previous clean runs 

836 if os.path.exists("__temp_mask"): 

837 shutil.rmtree("__temp_mask") 

838 if os.path.exists("__temp_mask2"): 

839 shutil.rmtree("__temp_mask2") 

840 

841 # relax to allow list input for imagename  

842 if(type(imagename)==list): 

843 imagename=imagename[0] 

844 

845 if(type(maskobject)==dict): 

846 maskrecord=maskobject 

847 maskobject=[] 

848 if(type(maskobject)==str): 

849 maskobject=[maskobject] 

850 

851 if(type(maskobject) != list): 

852 ##don't know what to do with this 

853 raise TypeError('Dont know how to deal with maskobject') 

854 if(numpy.issubdtype(type(maskobject[0]),numpy.int) or \ 

855 numpy.issubdtype(type(maskobject[0]),numpy.float)): 

856 # check and convert if list consist of python int or float  

857 maskobject_tmp = convert_numpydtype(maskobject) 

858 masklist.append(maskobject_tmp) 

859 else: 

860 for masklets in maskobject: 

861 if(type(masklets)==str): ## Can be a file name, or an explicit region-string 

862 if(os.path.exists(masklets)): 

863 if(subprocess.getoutput('file '+masklets).count('directory')): 

864 maskimage.append(masklets) 

865 elif(subprocess.getoutput('file '+masklets).count('text')): 

866 masktext.append(masklets) 

867 else: 

868 tablerecord.append(masklets) 

869 else: 

870 textreglist.append(masklets); 

871 #raise TypeError, masklets+' seems to be non-existant'  

872 if(type(masklets)==list): 

873 masklets_tmp = convert_numpydtype(masklets) 

874 masklist.append(masklets_tmp) 

875 if(type(masklets)==dict): 

876 maskrecord=masklets 

877 if(len(outputmask)==0): 

878 outputmask=imagename+'.mask' 

879 if(os.path.exists(outputmask)): 

880 # for multiple field  

881 # outputmask is always already defined 

882 # cannot use copymaskiamge since self.csys used in the code 

883 # fixed to that of main field 

884 if len(self.imagelist)>1: 

885 ia.fromimage('__temp_mask',outputmask,overwrite=True) 

886 ia.close() 

887 else: 

888 self.im.make('__temp_mask') 

889 ia.open('__temp_mask') 

890 shp=ia.shape() 

891 self.csys=ia.coordsys().torecord() 

892 ia.close() 

893 ia.removefile('__temp_mask') 

894 ia.open(outputmask) 

895 outim = ia.regrid(outfile='__temp_mask',shape=shp,axes=[3,0,1], csys=self.csys,overwrite=True, asvelocity=False) 

896 outim.done(verbose=False) 

897 ia.done(verbose=False) 

898 ia.removefile(outputmask) 

899 os.rename('__temp_mask',outputmask) 

900 else: 

901 self.im.make(outputmask) 

902 if len(self.imagelist)>1: 

903 raise Exception("Multifield case - requires initial mask images but undefined.") 

904 

905 # respect dataframe or outframe 

906 if self.usespecframe=='': 

907 maskframe=self.dataspecframe 

908 else: 

909 maskframe=self.usespecframe 

910 if len(self.vis)!=1: 

911 if not self.inframe: 

912 # for multi-ms case default output frame is default to LSRK 

913 # (set by baseframe in imager_cmt.cc)  

914 maskframe='LSRK' 

915 

916 ia.open(outputmask) 

917 # make output mask template unit less to avoid imagenalysis warning... 

918 if (ia.brightnessunit()!=""): 

919 ia.setbrightnessunit("") 

920 shp=ia.shape() 

921 self.csys=ia.coordsys().torecord() 

922 # keep this info for reading worldbox 

923 self.csysorder=ia.coordsys().coordinatetype() 

924# ia.close() 

925 

926# self.setReferenceFrameLSRK( outputmask ) 

927 

928 mycsys=ia.coordsys() 

929 if mycsys.torecord()['spectral2']['conversion']['system']!=maskframe: 

930 mycsys.setreferencecode(maskframe,'spectral',True) 

931 self.csys=mycsys.torecord() 

932 if self.csys['spectral2']['conversion']['system']!=maskframe: 

933 self.csys['spectral2']['conversion']['system']=maskframe 

934 ia.setcoordsys(self.csys) 

935 #ia.setcoordsys(mycsys.torecord()) 

936 ia.close() # close outputmask 

937 

938 if(len(maskimage) > 0): 

939 for ima in maskimage : 

940 ia.open(ima) 

941 maskshape = ia.shape() 

942 ia.close() 

943 if shp[3]>1 and maskshape[3]==1: 

944 self._casalog.post("Input mask,"+ima+" appears to be a continuum,"+ 

945 " it may not map to a cube correctly and will be"+ 

946 " ignored."+" Please use "+ 

947 "makemask to generate a proper mask.","WARN") 

948 if slice>-1: 

949 self.getchanimage(ima, ima+'chanim',slice) 

950 self.copymaskimage(ima+'chanim',shp,'__temp_mask') 

951 ia.removefile(ima+'chanim') 

952 else: 

953 self.copymaskimage(ima, shp, '__temp_mask') 

954 #ia.open(ima) 

955 #ia.regrid(outfile='__temp_mask',shape=shp,csys=self.csys, 

956 # overwrite=True) 

957 #ia.done(verbose=False) 

958 os.rename(outputmask,'__temp_mask2') 

959 outim = ia.imagecalc(outfile=outputmask, 

960 pixels='__temp_mask + __temp_mask2', 

961 overwrite=True) 

962 outim.done(verbose=False) 

963 ia.done(verbose=False) 

964 ia.removefile('__temp_mask') 

965 ia.removefile('__temp_mask2') 

966 if(not os.path.exists(outputmask)): 

967 outputmask = self.make_mask_from_threshhold(outputmask, 0.01, 

968 outputmask) 

969 #pdb.set_trace() 

970 #### This goes when those tablerecord goes 

971 ### Make masks from tablerecords 

972 if(len(tablerecord) > 0): 

973 reg={} 

974 for tabl in tablerecord: 

975 try: 

976 reg.update({tabl:rg.fromfiletorecord(filename=tabl, verbose=False)}) 

977 except: 

978 raise Exception('Region-file (binary) format not recognized. Please check. If box-file, please start the file with \'#boxfile\' on the first line') 

979 if(len(reg)==1): 

980 reg=reg[reg.keys()[0]] 

981 else: 

982 reg=rg.makeunion(reg) 

983 self.im.regiontoimagemask(mask=outputmask, region=reg) 

984 ############### 

985 ### Make masks from region dictionaries 

986 if((type(maskrecord)==dict) and (len(maskrecord) > 0)): 

987 self.im.regiontoimagemask(mask=outputmask, region=maskrecord) 

988 ### Make masks from text files 

989 if(len(masktext) >0): 

990 for textfile in masktext : 

991 # Read a box file 

992 polydic,listbox=self.readboxfile(textfile); 

993 

994 masklist.extend(listbox) 

995 if(len(polydic) > 0): 

996 ia.open(outputmask) 

997 ia.close() 

998 self.im.regiontoimagemask(mask=outputmask, region=polydic) 

999 # If box lists are empty, it may be a region format 

1000 if(len(polydic)==0 and len(listbox)==0): 

1001 # Read in a region file 

1002 try: 

1003 ia.open(outputmask); 

1004 mcsys = ia.coordsys(); 

1005 mshp = ia.shape(); 

1006 ia.close(); 

1007 mreg = rg.fromtextfile(filename=textfile,shape=mshp,csys=mcsys.torecord()); 

1008 self.im.regiontoimagemask(mask=outputmask, region=mreg); 

1009 except: 

1010 raise Exception('Region-file (text) format not recognized. Please check. If box-file, please start the file with \'#boxfile\' on the first line, and have at-least one valid box in it') 

1011 ### Make masks from inline lists of pixel coordinates 

1012 if((type(masklist)==list) and (len(masklist) > 0)): 

1013 self.im.regiontoimagemask(mask=outputmask, boxes=masklist) 

1014 ### Make masks from inline region-strings 

1015 if((type(textreglist)==list) and (len(textreglist)>0)): 

1016 ia.open(outputmask); 

1017 mcsys = ia.coordsys(); 

1018 mshp = ia.shape(); 

1019 ia.close(); 

1020 for textlet in textreglist: 

1021 try: 

1022 mreg = rg.fromtext(text=textlet,shape=mshp,csys=mcsys.torecord()); 

1023 self.im.regiontoimagemask(mask=outputmask, region=mreg); 

1024 except: 

1025 raise Exception('\''+textlet+'\' is not recognized as a text file on disk or as a region string') 

1026 ### Make mask from an image-mask 

1027 if(os.path.exists(imagename) and (len(rg.namesintable(imagename)) !=0)): 

1028 regs=rg.namesintable(imagename) 

1029 if(type(regs)==str): 

1030 regs=[regs] 

1031 for reg in regs: 

1032 elrec=rg.fromtabletorecord(imagename, reg) 

1033 self.im.regiontoimagemask(mask=outputmask, region=elrec) 

1034 

1035 self.outputmask=outputmask 

1036 

1037 ## CAS-5227 

1038 ia.open( outputmask ) 

1039 ia.calc('iif("'+outputmask+'"!=0.0,1.0,0.0)', False) 

1040 ia.close() 

1041 

1042 ## CAS-5221  

1043 #### CAS-6676 : Force frame to LSRK only if it's a fresh image being made. 

1044 #### If residual exists, then it's likely to not be in LSRK, so don't force the mask to be it. 

1045 #### The call to setFrameConversionForMasks() from task_clean.py would have set the 

1046 #### mask frame to match the ouput frame in the previous run. 

1047 if not os.path.exists(imagename+'.residual'): 

1048 self.setReferenceFrameLSRK( outputmask ) 

1049 #Done with making masks 

1050 

1051 

1052 def datselweightfilter(self, field, spw, timerange, uvrange, antenna,scan, 

1053 wgttype, robust, noise, npixels, mosweight, 

1054 innertaper, outertaper, usescratch, nchan=-1, start=0, width=1): 

1055 """ 

1056 Make data selection  

1057 (not in use, split into datsel and datweightfileter) 

1058 """ 

1059 rmode='none' 

1060 weighting='natural'; 

1061 if(wgttype=='briggsabs'): 

1062 weighting='briggs' 

1063 rmode='abs' 

1064 elif(wgttype=='briggs'): 

1065 weighting='briggs' 

1066 rmode='norm' 

1067 else: 

1068 weighting=wgttype 

1069 

1070 self.fieldindex=ms.msseltoindex(self.vis,field=field)['field'].tolist() 

1071 if(len(self.fieldindex)==0): 

1072 fieldtab=self.getsubtable(self.vis, 'FIELD') 

1073 tb.open(fieldtab) 

1074 self.fieldindex=range(tb.nrows()) 

1075 tb.close() 

1076 #weighting and tapering should be done together 

1077 if(weighting=='natural'): 

1078 mosweight=False 

1079 self.im.selectvis(nchan=nchan,start=start,step=width,field=field,spw=spw,time=timerange, 

1080 baseline=antenna, scan=scan, uvrange=uvrange, usescratch=usescratch) 

1081 self.im.weight(type=weighting,rmode=rmode,robust=robust, npixels=npixels, noise=qa.quantity(noise,'Jy'), mosaic=mosweight) 

1082 if((type(outertaper)==list) and (len(outertaper) > 0)): 

1083 if(len(outertaper)==1): 

1084 outertaper.append(outertaper[0]) 

1085 outertaper.append('0deg') 

1086 if(qa.quantity(outertaper[0])['value'] > 0.0): 

1087 self.im.filter(type='gaussian', bmaj=outertaper[0], 

1088 bmin=outertaper[1], bpa=outertaper[2]) 

1089 

1090 

1091 # split version of datselweightfilter 

1092 def datsel(self, field, spw, timerange, uvrange, antenna, scan, observation,intent, 

1093 usescratch, nchan=-1, start=0, width=1): 

1094 """ 

1095 Make selections in visibility data  

1096 """ 

1097 

1098 # for multi-MSes, if field,spw,timerage,uvrange,antenna,scan are not 

1099 # lists the same selection is applied to all the MSes. 

1100 self.fieldindex=[] 

1101 #nvislist=range(len(self.vis)) 

1102 vislist=self.sortedvisindx 

1103 self.paramlist={'field':field,'spw':spw,'timerange':timerange,'antenna':antenna, 

1104 'scan':scan, 'observation': observation, 'intent':intent, 'uvrange':uvrange} 

1105 for i in vislist: 

1106 selectedparams=self._selectlistinputs(len(vislist),i,self.paramlist) 

1107 tempfield=selectedparams['field'] 

1108# if type(field)==list: 

1109# if len(field)==nvislist: 

1110# tempfield=field[i] 

1111# else: 

1112# if len(field)==1: 

1113# tempfield=field[0] 

1114# else: 

1115# raise Exception, 'The number of field list does not match with the number of vis list' 

1116# else: 

1117# tempfield=field 

1118 

1119 if len(tempfield)==0: 

1120 tempfield='*' 

1121 self.fieldindex.append(ms.msseltoindex(self.vis[i],field=tempfield)['field'].tolist()) 

1122 

1123 ############################################################ 

1124 # Not sure I need this now.... Nov 15, 2010 

1125 vislist.reverse() 

1126 writeaccess=True 

1127 for i in vislist: 

1128 writeaccess=writeaccess and os.access(self.vis[i], os.W_OK) 

1129 #if any ms is readonly then no model will be stored, MSs will be in readmode only...but clean can proceed 

1130 for i in vislist: 

1131 # select apropriate parameters 

1132 selectedparams=self._selectlistinputs(len(vislist),i,self.paramlist) 

1133 inspw=selectedparams['spw'] 

1134 intimerange=selectedparams['timerange'] 

1135 inantenna=selectedparams['antenna'] 

1136 inscan=selectedparams['scan'] 

1137 inobs = selectedparams['observation'] 

1138 inintent = selectedparams['intent'] 

1139 inuvrange=selectedparams['uvrange'] 

1140 

1141 #if len(self.vis)==1: 

1142 #casalog.post("single ms case") 

1143 # self.im.selectvis(nchan=nchan,start=start,step=width,field=field, 

1144 # spw=inspw,time=intimerange, baseline=inantenna, 

1145 # scan=inscan, observation=inobs, intent=inintent, uvrange=inuvrange, 

1146 # usescratch=usescratch) 

1147 #else: 

1148 #casalog.post("multims case: selectvis for vis[",i,"]: spw,field=", inspw, self.fieldindex[i]) 

1149 self.im.selectvis(vis=self.vis[i],nchan=nchan,start=start,step=width, 

1150 field=self.fieldindex[i], spw=inspw,time=intimerange, 

1151 baseline=inantenna, scan=inscan, 

1152 observation=inobs, intent=inintent, 

1153 uvrange=inuvrange, usescratch=usescratch, writeaccess=writeaccess) 

1154 

1155 # private function for datsel and datweightfilter 

1156 def _selectlistinputs(self,nvis,indx,params): 

1157 """ 

1158 A little private function to do selection and checking for a parameter  

1159 given in list of strings. 

1160 It checks nelement in each param either match with nvis or nelement=1 

1161 (or a string) otherwise exception is thrown.  

1162 """ 

1163 outparams={} 

1164 if type(params)==dict: 

1165 for param,val in params.items(): 

1166 msg = 'The number of %s list given in list does not match with the number of vis list given.' % param 

1167 if type(val)==list: 

1168 if len(val)==nvis: 

1169 outval=val[indx] 

1170 else: 

1171 if len(val)==1: 

1172 outval=val[0] 

1173 else: 

1174 raise Exception(msg) 

1175 outparams[param]=outval 

1176 else: 

1177 #has to be a string 

1178 outparams[param]=val 

1179 return outparams 

1180 else: 

1181 raise Exception('params must be a dictionary') 

1182 

1183 # weighting/filtering part of datselweightfilter. 

1184 # The scan parameter is not actually used, so observation is not included 

1185 # as a parameter. Both are used via self._selectlistinputs(). 

1186 def datweightfilter(self, field, spw, timerange, uvrange, antenna,scan, 

1187 wgttype, robust, noise, npixels, mosweight, 

1188 uvtaper,innertaper, outertaper, usescratch, nchan=-1, start=0, width=1): 

1189 """ 

1190 Apply weighting and tapering  

1191 """ 

1192 rmode='none' 

1193 weighting='natural'; 

1194 if(wgttype=='briggsabs'): 

1195 weighting='briggs' 

1196 rmode='abs' 

1197 elif(wgttype=='briggs'): 

1198 weighting='briggs' 

1199 rmode='norm' 

1200 else: 

1201 weighting=wgttype 

1202 #weighting and tapering should be done together 

1203 if(weighting=='natural'): 

1204 mosweight=False 

1205# vislist=self.sortedvisindx 

1206 #nvislist.reverse() 

1207# for i in vislist: 

1208# # select apropriate parameters 

1209# selectedparams=self._selectlistinputs(len(vislist),i,self.paramlist) 

1210# inspw=selectedparams['spw']  

1211# intimerange=selectedparams['timerange']  

1212# inantenna=selectedparams['antenna']  

1213# inscan=selectedparams['scan']  

1214# inobs=selectedparams['observation']  

1215# inuvrange=selectedparams['uvrange']  

1216#  

1217# if len(self.vis) > 1: 

1218# casalog.post('from datwtfilter - multi';) 

1219# self.im.selectvis(vis=self.vis[i], field=self.fieldindex[i],spw=inspw,time=intimerange, 

1220# baseline=inantenna, scan=inscan, observation=inobs, 

1221# uvrange=inuvrange, usescratch=calready) 

1222# else:  

1223# casalog.post('from datwtfilter - single') 

1224# self.im.selectvis(field=field,spw=inspw,time=intimerange, 

1225# baseline=inantenna, scan=inscan, observation=inobs, 

1226# uvrange=inuvrange, usescratch=calready) 

1227# self.im.weight(type=weighting,rmode=rmode,robust=robust,  

1228# npixels=npixels, noise=qa.quantity(noise,'Jy'), mosaic=mosweight) 

1229 self.im.weight(type=weighting,rmode=rmode,robust=robust, 

1230 npixels=npixels, noise=qa.quantity(noise,'Jy'), mosaic=mosweight) 

1231 

1232 oktypes = (str,int,float) 

1233 

1234 if((uvtaper==True) and (type(outertaper) in oktypes)): 

1235 outertaper=[outertaper] 

1236 if((uvtaper==True) and (type(outertaper)==list) and (len(outertaper) > 0)): 

1237 if(len(outertaper)==1): 

1238 outertaper.append(outertaper[0]) 

1239 if(len(outertaper)==2): 

1240 outertaper.append('0deg') 

1241 if(qa.quantity(outertaper[0])['unit']==''): 

1242 outertaper[0]=qa.quantity(qa.quantity(outertaper[0])['value'],'lambda') 

1243 if(qa.quantity(outertaper[1])['unit']==''): 

1244 outertaper[1]=qa.quantity(qa.quantity(outertaper[1])['value'],'lambda') 

1245 if(qa.quantity(outertaper[0])['value'] > 0.0): 

1246 self.im.filter(type='gaussian', bmaj=outertaper[0], 

1247 bmin=outertaper[1], bpa=outertaper[2]) 

1248 

1249 

1250 def setrestoringbeam(self, restoringbeam): 

1251 """ 

1252 Set restoring beam 

1253 """ 

1254 if((restoringbeam == ['']) or (len(restoringbeam) ==0)): 

1255 return 

1256 resbmaj='' 

1257 resbmin='' 

1258 resbpa='0deg' 

1259 if((type(restoringbeam) == list) and len(restoringbeam)==1): 

1260 restoringbeam=restoringbeam[0] 

1261 if((type(restoringbeam)==str)): 

1262 if(qa.quantity(restoringbeam)['unit'] == ''): 

1263 restoringbeam=restoringbeam+'arcsec' 

1264 resbmaj=qa.quantity(restoringbeam, 'arcsec') 

1265 resbmin=qa.quantity(restoringbeam, 'arcsec') 

1266 if(type(restoringbeam)==list): 

1267 resbmaj=qa.quantity(restoringbeam[0], 'arcsec') 

1268 resbmin=qa.quantity(restoringbeam[1], 'arcsec') 

1269 if(resbmaj['unit']==''): 

1270 resbmaj=restoringbeam[0]+'arcsec' 

1271 if(resbmin['unit']==''): 

1272 resbmin=restoringbeam[1]+'arcsec' 

1273 if(len(restoringbeam)==3): 

1274 resbpa=qa.quantity(restoringbeam[2], 'deg') 

1275 if(resbpa['unit']==''): 

1276 resbpa=restoringbeam[2]+'deg' 

1277 if((resbmaj != '') and (resbmin != '')): 

1278 self.im.setbeam(bmaj=resbmaj, bmin=resbmin, bpa=resbpa) 

1279 

1280 def convertmodelimage(self, modelimages=[], outputmodel='',imindex=0): 

1281 """ 

1282 Convert model inputs to a model image 

1283 

1284 Keyword arguments: 

1285 modleimages -- input model list 

1286 outputmodel -- outout modelimage name 

1287 imindex -- image name index (corresponding to imagelist)  

1288 for multi field hanlding 

1289 """ 

1290 modelos=[] 

1291 maskelos=[] 

1292 if((modelimages=='') or (modelimages==[]) or (modelimages==[''])): 

1293 #if((modelimages=='') or (modelimages==[])): 

1294 return 

1295 if(type(modelimages)==str): 

1296 modelimages=[modelimages] 

1297 k=0 

1298 for modim in modelimages: 

1299 if not os.path.exists(modim): 

1300 raise Exception("Model image file name="+modim+" does not exist.") 

1301 

1302 ia.open(modim) 

1303 modelosname='modelos_'+str(k) 

1304 

1305 # clean up any temp files left from preveous incomplete run 

1306 if os.path.exists(modelosname): 

1307 ia.removefile(modelosname) 

1308 if os.path.exists('__temp_model2'): 

1309 ia.removefile('__temp_model2') 

1310 

1311 modelos.append(modelosname) 

1312 

1313 

1314 if( (ia.brightnessunit().count('/beam')) > 0): 

1315 ##single dish-style model 

1316 maskelos.append(modelos[k]+'.sdmask') 

1317 self.im.makemodelfromsd(sdimage=modim,modelimage=modelos[k],maskimage=maskelos[k]) 

1318 ia.open(maskelos[k]) 

1319 ##sd mask cover whole image...delete it as it is not needed 

1320 if((ia.statistics(verbose=False,list=False)['min']) >0): 

1321 ia.remove(done=True, verbose=False) 

1322 maskelos.remove(maskelos[k]) 

1323 ia.done() 

1324 else: 

1325 ##assuming its a model image already then just regrid it 

1326 #self.im.make(modelos[k]) 

1327 shutil.copytree(self.imagelist[imindex],modelos[k]) 

1328 ia.open(modelos[k]) 

1329 newcsys=ia.coordsys() 

1330 newshape=ia.shape() 

1331 ia.open(modim) 

1332 ib=ia.regrid(outfile=modelos[k], shape=newshape, axes=[0,1,3], csys=newcsys.torecord(), overwrite=True, asvelocity=False) 

1333 ib.done(verbose=False) 

1334 

1335 k=k+1 

1336 if ia.isopen(): ia.close() 

1337 ######### 

1338 if((len(maskelos)==1) and (self.outputmask == '')): 

1339 self.outputmask=modelimages[0]+'.mask' 

1340 if(os.path.exists(self.outputmask)): 

1341 ia.removefile(self.outputmask) 

1342 os.rename(maskelos[0],self.outputmask) 

1343 elif(len(maskelos) > 0): 

1344 if(self.outputmask == ''): 

1345 self.outputmask=modelimages[0]+'.mask' 

1346 

1347 else: 

1348 outputmask=self.outputmask 

1349 ##okay if outputmask exists then we need to do an "and" with 

1350 ##the sdmask one 

1351 doAnd=False; 

1352 if(os.path.exists(outputmask)): 

1353 ia.open(outputmask) 

1354 if((ia.statistics(verbose=False, list=False)['max'].max()) > 0.00001): 

1355 doAnd=True 

1356 ia.close() 

1357 if(doAnd): 

1358 tmpomask='__temp_o_mask' 

1359 self.makemaskimage(outputmask=tmpomask, maskobject=maskelos) 

1360 os.rename(outputmask, '__temp_i_mask') 

1361 outim = ia.imagecalc(outfile=outputmask, pixels='__temp_o_mask * __temp_i_mask', overwrite=True) 

1362 outim.done(verbose=False) 

1363 ia.removefile('__temp_o_mask') 

1364 ia.removefile('__temp_i_mask') 

1365 self.outputmask=outputmask 

1366 else: 

1367 self.makemaskimage(outputmask=outputmask, maskobject=maskelos) 

1368 for ima in maskelos: 

1369 if(os.path.exists(ima)): 

1370 ia.removefile(ima) 

1371 if(not (os.path.exists(outputmodel))): 

1372 # im.make uses the main field coord. so it does 

1373 # not make correct coord. for outlier fields 

1374 if len(self.imagelist)>1: 

1375 ia.fromimage(outputmodel, self.imagelist[imindex]) 

1376 else: 

1377 self.im.make(outputmodel) 

1378 #ia.open(outputmodel) 

1379 #ia.close() 

1380 for k in range(len(modelos)): 

1381 # if os.rename() or shutil.move() is used here, 

1382 # for k=1 and at image.imagecalc, it seems to cause  

1383 # casapy to crash...  

1384 #os.rename(outputmodel,'__temp_model2') 

1385 shutil.copytree(outputmodel,'__temp_model2') 

1386 

1387 outim = ia.imagecalc(outfile=outputmodel, 

1388 pixels=modelos[k]+' + '+'__temp_model2', 

1389 overwrite=True) 

1390 outim.done(verbose=False) 

1391 ia.removefile('__temp_model2') 

1392 ia.removefile(modelos[k]); 

1393 

1394 def readboxfile(self, boxfile): 

1395 """ Read a file containing clean boxes (compliant with AIPS BOXFILE) 

1396 

1397 Format is: 

1398 #FIELDID BLC-X BLC-Y TRC-X TRC-Y 

1399 0 110 110 150 150  

1400 or 

1401 0 hh:mm:ss.s dd.mm.ss.s hh:mm:ss.s dd.mm.ss.s 

1402  

1403 Note all lines beginning with '#' are ignored. 

1404  

1405 """ 

1406 union=[] 

1407 polyg={} 

1408 f=open(boxfile) 

1409 temprec={} 

1410 counter=0 

1411 while 1: 

1412 try: 

1413 counter=counter+1 

1414 line=f.readline() 

1415 if(len(line)==0): 

1416 raise Exception 

1417 if (line.find('#')!=0): 

1418 if(line.count('[')==2): 

1419 ##its an output from qtclean 

1420 line=line.replace('\n','') 

1421 line=line.replace('\t',' ') 

1422 line=line.replace('[',' ') 

1423 line=line.replace(']',' ') 

1424 line=line.replace(',',' ') 

1425 splitline=line.split() 

1426 if(len(splitline)==5): 

1427 ##its box 

1428 if(int(splitline[4]) > 0): 

1429 ##it was a "mask" region not "erase" 

1430 boxlist=[int(splitline[0]),int(splitline[1]), 

1431 int(splitline[2]),int(splitline[3])] 

1432 union.append(boxlist) 

1433 else: 

1434 #its a polygon 

1435 x=[] 

1436 y=[] 

1437 if(int(splitline[len(splitline)-1]) > 0): 

1438 ###ignore erase regions 

1439 nnodes=(len(splitline)-1)/2 

1440 for kk in range(nnodes): 

1441 x.append(splitline[kk]+'pix') 

1442 y.append(splitline[kk+nnodes]+'pix') 

1443 elreg=rg.wpolygon(x=x, y=y, csys=self.csys) 

1444 temprec.update({counter:elreg}) 

1445 

1446 elif(line.count('worldbox')==1): 

1447 self._casalog.post('\'worldbox\' is deprecated please use CRTF format','WARN') 

1448 #ascii box file from viewer or boxit 

1449 # expected foramt: 'worldbox' pos_ref [lat 

1450 line=line.replace('[',' ') 

1451 line=line.replace(']',' ') 

1452 line=line.replace(',',' ') 

1453 line=line.replace('\'',' ') 

1454 splitline=line.split() 

1455 if len(splitline) != 13: 

1456 raise TypeError('Error reading worldbox file') 

1457 # 

1458 refframe=self.csys['direction0']['conversionSystem'] 

1459 if refframe.find('_VLA')>0: 

1460 refframe=refframe[0:refframe.find('_VLA')] 

1461 ra =[splitline[2],splitline[3]] 

1462 dec = [splitline[4],splitline[5]] 

1463 #set frames 

1464 obsdate=self.csys['obsdate'] 

1465 me.doframe(me.epoch(obsdate['refer'], str(obsdate['m0']['value'])+obsdate['m0']['unit'])) 

1466 me.doframe(me.observatory(self.csys['telescope'])) 

1467 # 

1468 if splitline[1]!=refframe: 

1469 # coversion between different epoch (and to/from AZEL also) 

1470 radec0 = me.measure(me.direction(splitline[1],ra[0],dec[0]), refframe) 

1471 radec1 = me.measure(me.direction(splitline[1],ra[1],dec[1]), refframe) 

1472 ra=[str(radec0['m0']['value'])+radec0['m0']['unit'],\ 

1473 str(radec1['m0']['value'])+radec1['m0']['unit']] 

1474 dec=[str(radec0['m1']['value'])+radec0['m1']['unit'],\ 

1475 str(radec1['m1']['value'])+radec1['m1']['unit']] 

1476 # check for stokes  

1477 stokes=[] 

1478 imstokes = self.csys['stokes1']['stokes'] 

1479 for st in [splitline[10],splitline[11]]: 

1480 prevlen = len(stokes) 

1481 for i in range(len(imstokes)): 

1482 if st==imstokes[i]: 

1483 stokes.append(str(i)+'pix') 

1484 elif st.count('pix') > 0: 

1485 stokes.append(st) 

1486 if len(stokes)<=prevlen: 

1487 #raise TypeError, "Stokes %s for the box boundaries is outside image" % st  

1488 self._casalog.post('Stokes %s for the box boundaries is outside image, -ignored' % st, 'WARN') 

1489 # frequency 

1490 freqs=[splitline[7].replace('s-1','Hz'), splitline[9].replace('s-1','Hz')] 

1491 fframes=[splitline[6],splitline[8]] 

1492 #imframe = self.csys['spectral2']['system'] 

1493 imframe = self.csys['spectral2']['conversion']['system'] 

1494 #casalog.post("imframe=" + imframe + " system frame =" + self.csys['spectral2']['system'] + " frame in boxfile=" + fframes[0]) 

1495 # the worldbox file created viewer's "box in file" 

1496 # currently says TOPO in frequency axis but seems to 

1497 # wrong (the freuencies look like in the image's base 

1498 # frame).  

1499 for k in [0,1]: 

1500 if fframes[k]!=imframe and freqs[k].count('pix')==0: 

1501 #do frame conversion 

1502 #self._casalog.post('Ignoring the frequency frame of the box for now', 'WARN')  

1503 # uncomment the following when box file correctly labeled the frequency frame 

1504 me.doframe(me.direction(splitline[1],ra[k],dec[k])) 

1505 mf=me.measure(me.frequency(fframes[k],freqs[k]),imframe) 

1506 freqs[k]=str(mf['m0']['value'])+mf['m0']['unit'] 

1507 coordorder=self.csysorder 

1508 wblc = [] 

1509 wtrc = [] 

1510 for type in coordorder: 

1511 if type=='Direction': 

1512 wblc.append(ra[0]) 

1513 wblc.append(dec[0]) 

1514 wtrc.append(ra[1]) 

1515 wtrc.append(dec[1]) 

1516 if type=='Stokes': 

1517 wblc.append(stokes[0]) 

1518 wtrc.append(stokes[1]) 

1519 if type=='Spectral': 

1520 wblc.append(freqs[0]) 

1521 wtrc.append(freqs[1]) 

1522 

1523 #wblc = [ra[0], dec[0], stokes[0], freqs[0]] 

1524 #wtrc = [ra[1], dec[1], stokes[1], freqs[1]] 

1525 #wblc = ra[0]+" "+dec[0] 

1526 #wtrc = ra[1]+" "+dec[1] 

1527 #casalog.post... "wblc=",wblc," wtrc=",wtrc," using system frame=",self.csys['spectral2']['system'], " convertion frame=",self.csys['spectral2']['conversion']['system'] 

1528 wboxreg = rg.wbox(blc=wblc,trc=wtrc,csys=self.csys) 

1529 temprec.update({counter:wboxreg}) 

1530 

1531 else: 

1532 ### its an AIPS boxfile 

1533 splitline=line.split('\n') 

1534 splitline2=splitline[0].split() 

1535 if (len(splitline2)<6): 

1536 if(int(splitline2[1])<0): 

1537 ##circle 

1538 #circlelist=[int(splitline2[2]), 

1539 # int(splitline2[3]),int(splitline2[4])] 

1540 #circles[splitline2[0]].append(circlelist) 

1541 continue 

1542 else: 

1543 boxlist=[int(splitline2[1]),int(splitline2[2]), 

1544 int(splitline2[3]),int(splitline2[4])] 

1545 union.append(boxlist) 

1546 else: 

1547 ## Don't know what that is 

1548 ## might be a facet definition  

1549 continue 

1550 

1551 except: 

1552 break 

1553 

1554 f.close() 

1555 if(len(temprec)==1): 

1556 polyg=temprec[temprec.keys()[0]] 

1557 elif (len(temprec) > 1): 

1558 #polyg=rg.dounion(temprec) 

1559 polyg=rg.makeunion(temprec) 

1560 

1561 return polyg,union 

1562 

1563 def readmultifieldboxfile(self, boxfiles): 

1564 """  

1565 Read boxes and circles in text files in the  

1566 AIPS clean boxfile format. 

1567 

1568 Keyword arguments: 

1569 boxfiles -- text files in boxfile format 

1570 

1571 returns: 

1572 circles -- dictionary containing circles  

1573 boxes -- dictionary conatining boxes ([blc, trc]) 

1574 oldfileformats -- a list of boolean if the input textfiles 

1575 are boxfile format.  

1576 """ 

1577 circles={} 

1578 boxes={} 

1579 oldfilefmts={} 

1580 for k in range(len(self.imageids)): 

1581 circles[self.imageids[k]]=[] 

1582 boxes[self.imageids[k]]=[] 

1583 for boxfile in boxfiles: 

1584 f=open(boxfile) 

1585 setonce=False 

1586 oldfilefmts[boxfile]=False 

1587 while 1: 

1588 try: 

1589 line=f.readline() 

1590 if(len(line)==0): 

1591 raise Exception 

1592 if line.find('#')==0: 

1593 if not setonce and line.find('boxfile')>0: 

1594 oldfilefmts[boxfile]=True 

1595 setonce=True 

1596 self._casalog.post(boxfile+" is in a deprecated boxfile format,"+\ 

1597 " will not be supported in the future releases","WARN") 

1598 #raise Exception 

1599 else: 

1600 ### its an AIPS boxfile 

1601 splitline=line.split('\n') 

1602 splitline2=splitline[0].split() 

1603 if (len(splitline2)<6): 

1604 ##circles 

1605 if(int(splitline2[1]) <0): 

1606 circlelist=[int(splitline2[2]), 

1607 int(splitline2[3]),int(splitline2[4])] 

1608 #circles[splitline2[0]].append(circlelist) 

1609 circles[self.imageids[int(splitline2[0])]].append(circlelist) 

1610 else: 

1611 #boxes 

1612 if(len(splitline2)==5): 

1613 boxlist=[int(splitline2[1]),int(splitline2[2]), 

1614 int(splitline2[3]),int(splitline2[4])] 

1615 #boxes[splitline2[0]].append(boxlist) 

1616 boxes[self.imageids[int(splitline2[0])]].append(boxlist) 

1617 else: 

1618 ## Don't know what that is 

1619 ## might be a facet definition  

1620 continue 

1621 

1622 

1623 

1624 except: 

1625 break 

1626 

1627 f.close() 

1628 ###clean up the records 

1629 for k in range(len(self.imageids)): 

1630 if(circles[self.imageids[k]]==[]): 

1631 circles.pop(self.imageids[k]) 

1632 if(boxes[self.imageids[k]]==[]): 

1633 boxes.pop(self.imageids[k]) 

1634 

1635 return circles,boxes,oldfilefmts 

1636 

1637 

1638 def readoutlier(self, outlierfile): 

1639 """ Read a file containing clean boxes (kind of 

1640 compliant with AIPS FACET FILE) 

1641  

1642 Format is: 

1643 col0 col1 col2 col3 col4 col5 col6 col7 col8 col9 

1644 C FIELDID SIZEX SIZEY RAHH RAMM RASS DECDD DECMM DECSS  

1645 why first column has to have C ... because its should 

1646 not to be A or B ...now D would be a totally different thing. 

1647  

1648 'C' as in AIPS BOXFILE format indicates the file specify the coordiates 

1649 for field center(s).  

1650 

1651 Note all lines beginning with '#' are ignored. 

1652 (* Lines with first column other than C or c are also ignored) 

1653  

1654 """ 

1655 imsizes=[] 

1656 phasecenters=[] 

1657 imageids=[] 

1658 f=open(outlierfile) 

1659 while 1: 

1660 try: 

1661 line=f.readline() 

1662 

1663 if(len(line)==0): 

1664 raise Exception 

1665 if (line.find('#')!=0): 

1666 splitline=line.split('\n') 

1667 splitline2=splitline[0].split() 

1668 if (len(splitline2)==10): 

1669 if(splitline2[0].upper()=='C'): 

1670 imageids.append(splitline2[1]) 

1671 imsizes.append((int(splitline2[2]),int(splitline2[3]))) 

1672 mydir='J2000 '+splitline2[4]+'h'+splitline2[5]+'m'+splitline2[6]+' '+splitline2[7]+'d'+splitline2[8]+'m'+splitline2[9] 

1673 phasecenters.append(mydir) 

1674 

1675 except: 

1676 break 

1677 

1678 f.close() 

1679 return imsizes,phasecenters,imageids 

1680 

1681 def newreadoutlier(self, outlierfile): 

1682 """ 

1683 Read a outlier file (both old and new format)  

1684  

1685 The new format consists of a set of task parameter inputs. 

1686 imagename="outlier1" imsize=[128,128] phasecenter="J2000 hhmmss.s ddmmss.s"  

1687 imagename="outlier2" imsize=[128,128] phasecenter="J2000 hhmmss.s ddmmss.s" 

1688 mask=['viewermask.rgn','box[[50,60],[50,60]]'] ... 

1689 

1690 Currently supported paramters are: 

1691 imagename (required: used to delinate a paramater set for each field) 

1692 imsize (required) 

1693 phasecenter (required) 

1694 mask (optional) 

1695 modelimage (optional)  

1696 * other parameters can be included in the file but not parsed 

1697 

1698 For the old format, readoutlier() is called internally currently. But 

1699 the support will be removed by CASA3.4.  

1700 

1701 Returns: 

1702 lists of imageids, imsizes, phasecenters, masks,  

1703 and modelimages, and a dictionary contains all the parameters, 

1704 and a boolean to indicate read file is in the new format.  

1705 """ 

1706 import ast 

1707 import re 

1708 

1709 imsizes=[] 

1710 phasecenters=[] 

1711 imageids=[] 

1712 masks=[] 

1713 modelimages=[] 

1714 keywd = "imagename" 

1715 oldformat=False 

1716 nchar= len(keywd) 

1717 content0='' 

1718 # set this to True to disallow old outlier file 

1719 noOldOutlierFileSupport=False; 

1720 

1721 with open(outlierfile) as f: 

1722 for line in f: 

1723 try: 

1724 if len(line)!=0 and line.split()!=[]: 

1725 if line.split()[0]=='C' or line.split()[0]=='c': 

1726 oldformat=True 

1727 elif line.split()[0]!='#': 

1728 content0+=line 

1729 except: 

1730 casalog.post("Unkown error while reading the file: " + outlierfile) 

1731 break 

1732 if oldformat: 

1733 if noOldOutlierFileSupport: 

1734 self._casalog.post("You are using the old outlier file format no longer supported. Please use the new format (see help).","SEVERE") 

1735 raise Exception 

1736 else: 

1737 self._casalog.post("This file format is deprecated. Use of a new format is encouraged.","WARN") 

1738 # do old to new data format conversion....(watch out for different order of return parameters...) 

1739 (imsizes,phasecenters,imageids)=self.readoutlier(outlierfile) 

1740 for i in range(len(imageids)): 

1741 modelimages.append('') 

1742 #f.seek(0) 

1743 #content0 = f.read() 

1744 #f.close() 

1745 content=content0.replace('\n',' ') 

1746 last = len(content) 

1747 # split the content using imagename as a key  

1748 # and store each parameter set in pars dict 

1749 pars={} 

1750 initi = content.find(keywd) 

1751 if initi > -1: 

1752 i = 0 

1753 prevstart=initi 

1754 while True: 

1755 #step = nchar*(i+1) 

1756 step = nchar+1 

1757 start = prevstart+step 

1758 nexti = content[start:].find(keywd) 

1759 #casalog.post... ("With start=",start, " found next one at(nexti)=",nexti, " step used =",step, " prevstart=",prevstart) 

1760 

1761 if nexti == -1: 

1762 pars[i]=content[prevstart:] 

1763 # casalog.post("range=" + prevstart + " to the end") 

1764 break 

1765 pars[i]=content[prevstart:prevstart+nexti+step] 

1766 #casalog.post("pars[",i,"]=" + pars[i]) 

1767 #casalog.post("range=" + prevstart + " to" + prevstart+nexti+step-1) 

1768 prevstart=prevstart+nexti+step 

1769 i+=1 

1770 

1771 # for parsing of indiviual par (per field) 

1772 #casalog.post("pars=" + pars) 

1773 dparm ={} 

1774 indx=0 

1775 for key in pars.keys(): 

1776 # do parsing 

1777 parstr = pars[key] 

1778 # clean up extra white spaces 

1779 parm=' '.join(parstr.split()) 

1780 # more clean up 

1781 parm=parm.replace("[ ","[") 

1782 parm=parm.replace(" ]","]") 

1783 parm=parm.replace(" ,",",") 

1784 parm=parm.replace(", ",",") 

1785 parm=parm.replace(" =","=") 

1786 parm=parm.replace("= ","=") 

1787 #casalog.post("parm=" + parm) 

1788 subdic={} 

1789 # final parameter sets  

1790 values=re.compile('\w+=').split(parm) 

1791 values=values[1:len(values)] 

1792 

1793 ipar = 0 

1794 for pv in parm.split(): 

1795 if pv.find('=') != -1: 

1796 if ipar >= len(values): 

1797 raise TypeError("mismath in no. parameters in parsing outlier file.") 

1798 (k,v) = pv.split('=') 

1799 # fix a string to proper litral value 

1800 # take out any commas at end which will 

1801 # confuse literal_eval function 

1802 pat = re.compile(',+$') 

1803 subdic[k]=ast.literal_eval(pat.sub('',values[ipar])) 

1804 ipar += 1 

1805 dparm[indx]=subdic 

1806 indx+=1 

1807 #casalog.post("DONE for parsing parm for each field") 

1808 # put into list of parameters 

1809 # imsizes, phasecenters, imagenames(imageids) 

1810 # mask is passed to other function for forther processing 

1811 if not oldformat: 

1812 #pack them by parameter name 

1813 for fld in dparm.keys(): 

1814 # before process, check if it contains all required keys 

1815 # namely, imagename, phasecenter, imsize 

1816 #casalog.post("dparm[",fld,"]=" + dparm[fld]) 

1817 if not ("imagename" in dparm[fld] and \ 

1818 "phasecenter" in dparm[fld] and \ 

1819 "imsize" in dparm[fld]): 

1820 raise TypeError("Missing one or more of the required parameters: \ 

1821 imagename, phasecenter, and imsize in the outlier file. Please check the input outlier file.") 

1822 for key in dparm[fld].keys(): 

1823 if key == "imagename": 

1824 imageids.append(dparm[fld][key]) 

1825 if key == "phasecenter": 

1826 phasecenters.append(dparm[fld][key]) 

1827 if key == "imsize": 

1828 imsizes.append(dparm[fld][key]) 

1829 if key == "mask": 

1830 if type(dparm[fld][key])==str: 

1831 masks.append([dparm[fld][key]]) 

1832 else: 

1833 masks.append(dparm[fld][key]) 

1834 if key == "modelimage": 

1835 if type(dparm[fld][key])==str: 

1836 modelimages.append([dparm[fld][key]]) 

1837 else: 

1838 modelimages.append(dparm[fld][key]) 

1839 if "mask" not in dparm[fld]: 

1840 masks.append([]) 

1841 if "modelimage" not in dparm[fld]: 

1842 modelimages.append('') 

1843 

1844 

1845 return (imageids,imsizes,phasecenters,masks,modelimages,dparm, not oldformat) 

1846 

1847 

1848 def copymaskimage(self, maskimage, shp, outfile): 

1849 """ 

1850 Copy mask image 

1851  

1852 Keyword arguments: 

1853 maskimage -- input maskimage  

1854 shp -- shape of output image  

1855 outfile -- output image name 

1856 """ 

1857 if outfile == maskimage: # Make it a no-op, 

1858 return # this is more than just peace of mind. 

1859 #pdb.set_trace()  

1860 ia.open(maskimage) 

1861 oldshp=ia.shape() 

1862 if((len(oldshp) < 4) or (shp[2] != oldshp[2]) or (shp[3] != oldshp[3])): 

1863 #take the first plane of mask 

1864 tmpshp=oldshp 

1865 tmpshp[0]=shp[0] 

1866 tmpshp[1]=shp[1] 

1867 if len(oldshp)==4: # include spectral axis for regrid 

1868 tmpshp[3]=shp[3] 

1869 ib=ia.regrid(outfile='__looloo', shape=tmpshp, axes=[3,0,1], csys=self.csys, overwrite=True, asvelocity=False) 

1870 else: 

1871 ib=ia.regrid(outfile='__looloo', shape=tmpshp, axes=[0,1], csys=self.csys, overwrite=True, asvelocity=False) 

1872 

1873 #dat=ib.getchunk() 

1874 ib.done(verbose=False) 

1875 ia.fromshape(outfile=outfile, shape=shp, csys=self.csys, overwrite=True) 

1876 ##getchunk is a massive memory hog 

1877 ###so going round in a funny fashion 

1878 #arr=ia.getchunk() 

1879 #for k in range(shp[2]): 

1880 # for j in range(shp[3]): 

1881 # if(len(dat.shape)==2): 

1882 # arr[:,:,k,j]=dat 

1883 # elif(len(dat.shape)==3): 

1884 # arr[:,:,k,j]=dat[:,:,0] 

1885 # else: 

1886 # arr[:,:,k,j]=dat[:,:,0,0] 

1887 #ia.putchunk(arr) 

1888 ia.calc(outfile+'[index3 in [0]]+__looloo') 

1889 ia.calcmask('mask(__looloo)') 

1890 ia.done(verbose=False) 

1891 ia.removefile('__looloo') 

1892 else: 

1893 ib=ia.regrid(outfile=outfile ,shape=shp, axes=[0,1], csys=self.csys, overwrite=True, asvelocity=False) 

1894 ia.done(verbose=False) 

1895 ib.done(verbose=False) 

1896 

1897 

1898 def flatten(self,l): 

1899 """ 

1900 A utility function to flatten nested lists  

1901 but allow nesting of [[elm1,elm2,elm3],[elm4,elm5],[elm6,elm7]] 

1902 to handle multifield masks. 

1903 This does not flatten if an element is a list of int or float.  

1904 And also leave empty list as is. 

1905 """ 

1906 retlist = [] 

1907 l = list(l) 

1908 #casalog.post('l='+l) 

1909 for i in range(len(l)): 

1910 #casalog.post("ith l="+i+ l[i] ) 

1911 if isinstance(l[i],list) and l[i]: 

1912 # and (not isinstance(l[i][0],(int,float))): 

1913 #casalog.post("recursive l="+l) 

1914 if isinstance(l[i][0],list) and isinstance(l[i][0][0],list): 

1915 retlist.extend(self.flatten(l[i])) 

1916 else: 

1917 retlist.append(l[i]) 

1918 else: 

1919 retlist.append(l[i]) 

1920 return retlist 

1921 

1922 def getchanimage(self,cubeimage,outim,chan): 

1923 """ 

1924 Create a slice of channel image from cubeimage 

1925 

1926 Keyword arguments: 

1927 cubeimage -- input image cube 

1928 outim -- output sliced image 

1929 chan -- nth channel 

1930 """ 

1931 #pdb.set_trace() 

1932 ia.open(cubeimage) 

1933 modshape=ia.shape() 

1934 if modshape[3]==1: 

1935 return False 

1936 if modshape[3]-1 < chan: 

1937 return False 

1938 blc=[0,0,modshape[2]-1,chan] 

1939 trc=[modshape[0]-1,modshape[1]-1,modshape[2]-1,chan] 

1940 sbim=ia.subimage(outfile=outim, region=rg.box(blc,trc), overwrite=True) 

1941 sbim.close() 

1942 ia.close() 

1943 return True 

1944 

1945 def putchanimage(self,cubimage,inim,chan): 

1946 """ 

1947 Put channel image back to a pre-exisiting cubeimage 

1948  

1949 Keyword arguments: 

1950 cubimage -- image cube 

1951 inim -- input channel image  

1952 chan -- nth channel 

1953 """ 

1954 ia.open(inim) 

1955 inimshape=ia.shape() 

1956 imdata=ia.getchunk() 

1957 immask=ia.getchunk(getmask=True) 

1958 ia.close() 

1959 blc=[0,0,inimshape[2]-1,chan] 

1960 trc=[inimshape[0]-1,inimshape[1]-1,inimshape[2]-1,chan] 

1961 ia.open(cubimage) 

1962 cubeshape=ia.shape() 

1963 if not (cubeshape[3] > (chan+inimshape[3]-1)): 

1964 return False 

1965 #rg0=ia.setboxregion(blc=blc,trc=trc) 

1966 rg0=rg.box(blc=blc,trc=trc) 

1967 if inimshape[0:3]!=cubeshape[0:3]: 

1968 return False 

1969 #ia.putchunk(pixels=imdata,blc=blc) 

1970 ia.putregion(pixels=imdata,pixelmask=immask, region=rg0) 

1971 ia.close() 

1972 return True 

1973 

1974 def qatostring(self,q): 

1975 """ 

1976 A utility function to return a quantity in string 

1977 (currently only used in setChannelization which is deprecated) 

1978 """ 

1979 if 'unit' not in q: 

1980 raise TypeError("Does not seems to be quantity") 

1981 return str(q['value'])+q['unit'] 

1982 

1983 def convertvf(self,vf,frame,field,restf,veltype='radio'): 

1984 """ 

1985 returns doppler(velocity) or frequency in string 

1986 currently use first rest frequency 

1987 Assume input vf (velocity or fequency in a string) and  

1988 output are the same 'frame'. 

1989 """ 

1990 #pdb.set_trace() 

1991 docalcf=False 

1992 #if(frame==''): frame='LSRK'  

1993 #Use datasepcframe, it is cleanhelper initialized to set 

1994 #to LSRK 

1995 if(frame==''): frame=self.dataspecframe 

1996 if(qa.quantity(vf)['unit'].find('m/s') > -1): 

1997 docalcf=True 

1998 elif(qa.quantity(vf)['unit'].find('Hz') > -1): 

1999 docalcf=False 

2000 else: 

2001 if vf !=0: 

2002 raise TypeError("Unrecognized unit for the velocity or frequency parameter") 

2003 ##fldinds=ms.msseltoindex(self.vis, field=field)['field'].tolist() 

2004 fldinds=ms.msseltoindex(self.vis[self.sortedvisindx[0]], field=field)['field'].tolist() 

2005 if(len(fldinds) == 0): 

2006 fldid0=0 

2007 else: 

2008 fldid0=fldinds[0] 

2009 if restf=='': 

2010 #tb.open(self.vis+'/FIELD') 

2011 fldtab=self.getsubtable(self.vis[self.sortedvisindx[0]],'FIELD') 

2012 tb.open(fldtab) 

2013 nfld = tb.nrows() 

2014 if nfld >= fldid0: 

2015 srcid=tb.getcell('SOURCE_ID',fldid0) 

2016 else: 

2017 raise TypeError( "Cannot set REST_FREQUENCY from the data: " + 

2018 "no SOURCE corresponding field ID=%s, please supply restfreq" % fldid0 ) 

2019 tb.close() 

2020 # SOUECE_ID in FIELD table = -1 if no SOURCE table 

2021 if srcid==-1: 

2022 raise TypeError("Rest frequency info is not supplied") 

2023 #tb.open(self.vis+'/SOURCE') 

2024 sourcetab=self.getsubtable(self.vis[self.sortedvisindx[0]], 'SOURCE') 

2025 tb.open(sourcetab) 

2026 tb2=tb.query('SOURCE_ID==%s' % srcid) 

2027 tb.close() 

2028 nsrc = tb2.nrows() 

2029 if nsrc > 0: 

2030 rfreq=tb2.getcell('REST_FREQUENCY',0) 

2031 else: 

2032 raise TypeError( "Cannot set REST_FREQUENCY from the data: "+ 

2033 " no SOURCE corresponding field ID=%s, please supply restfreq" % fldid0 ) 

2034 tb2.close() 

2035 if(rfreq<=0): 

2036 raise TypeError("Rest frequency does not seems to be properly set, check the data") 

2037 else: 

2038 if type(restf)==str: restf=[restf] 

2039 if(qa.quantity(restf[0])['unit'].find('Hz') > -1): 

2040 rfreq=[qa.convert(qa.quantity(restf[0]),'Hz')['value']] 

2041 #casalog.post("using user input rest freq=" + rfreq) 

2042 else: 

2043 raise TypeError("Unrecognized unit or type for restfreq") 

2044 if(vf==0): 

2045 # assume just want to get a restfrequecy from the data 

2046 ret=str(rfreq[0])+'Hz' 

2047 else: 

2048 if(docalcf): 

2049 dop=me.doppler(veltype, qa.quantity(vf)) 

2050 rvf=me.tofrequency(frame, dop, qa.quantity(rfreq[0],'Hz')) 

2051 else: 

2052 frq=me.frequency(frame, qa.quantity(vf)) 

2053 rvf=me.todoppler(veltype, frq, qa.quantity(rfreq[0],'Hz')) 

2054 ret=str(rvf['m0']['value'])+rvf['m0']['unit'] 

2055 return ret 

2056 

2057 

2058 def getfreqs(self,nchan,spw,start,width, dummy=False): 

2059 """ 

2060 (not in used - currently commented out in its caller, initChaniter())  

2061 returns a list of frequencies to be used in output clean image 

2062 if width = -1, start is actually end (max) freq  

2063 """ 

2064 #pdb.set_trace() 

2065 freqlist=[] 

2066 finc=1 

2067 loc_nchan=0 

2068 

2069 if spw in (-1, '-1', '*', '', ' '): 

2070 spwinds = -1 

2071 else: 

2072 #spwinds=ms.msseltoindex(self.vis, spw=spw)['spw'].tolist() 

2073 spwinds=ms.msseltoindex(self.vis[self.sortedvisindx[0]], spw=spw)['spw'].tolist() 

2074 if(len(spwinds) == 0): 

2075 spwinds = -1 

2076 

2077 if(spwinds==-1): 

2078 # first row 

2079 spw0=0 

2080 else: 

2081 spw0=spwinds[0] 

2082 #tb.open(self.vis+'/SPECTRAL_WINDOW') 

2083 spectable=self.getsubtable(self.vis[self.sortedvisindx[0]], "SPECTRAL_WINDOW") 

2084 tb.open(spectable) 

2085 chanfreqscol=tb.getvarcol('CHAN_FREQ') 

2086 chanwidcol=tb.getvarcol('CHAN_WIDTH') 

2087 spwframe=tb.getcol('MEAS_FREQ_REF'); 

2088 tb.close() 

2089 # assume spw[0]  

2090 elspecframe=["REST", 

2091 "LSRK", 

2092 "LSRD", 

2093 "BARY", 

2094 "GEO", 

2095 "TOPO", 

2096 "GALACTO", 

2097 "LGROUP", 

2098 "CMB"] 

2099 self.dataspecframe=elspecframe[spwframe[spw0]]; 

2100 if(dummy): 

2101 return freqlist, finc 

2102 #DP extract array from dictionary returned by getvarcol 

2103 chanfreqs1dx = numpy.array([]) 

2104 chanfreqs=chanfreqscol['r'+str(spw0+1)].transpose() 

2105 chanfreqs1dx = chanfreqs[0] 

2106 if(spwinds!=-1): 

2107 for ispw in range(1,len(spwinds)): 

2108 chanfreqs=chanfreqscol['r'+str(spwinds[ispw]+1)].transpose() 

2109 chanfreqs1dx = numpy.concatenate((chanfreqs1dx, chanfreqs[0])) 

2110 chanfreqs1d = chanfreqs1dx.flatten() 

2111 #RI this is woefully inadequate assuming the first chan's width 

2112 #applies to everything selected, but we're going to replace all 

2113 #this with MSSelect.. 

2114 chanwids=chanwidcol['r'+str(spw0+1)].transpose() 

2115 chanfreqwidth=chanwids[0][0] 

2116 

2117 if(type(start)==int or type(start)==float): 

2118 if(start > len(chanfreqs1d)): 

2119 raise TypeError("Start channel is outside the data range") 

2120 startf = chanfreqs1d[start] 

2121 elif(type(start)==str): 

2122 if(qa.quantity(start)['unit'].find('Hz') > -1): 

2123 startf=qa.convert(qa.quantity(start),'Hz')['value'] 

2124 else: 

2125 raise TypeError("Unrecognized start parameter") 

2126 if(type(width)==int or type(width)==float): 

2127 if(type(start)==int or type(start)==float): 

2128 #finc=(chanfreqs1d[start+1]-chanfreqs1d[start])*width 

2129 finc=(chanfreqwidth)*width 

2130 # still need to convert to target reference frame! 

2131 elif(type(start)==str): 

2132 if(qa.quantity(start)['unit'].find('Hz') > -1): 

2133 # assume called from setChannelization with local width=1 

2134 # for the default width(of clean task parameter)='' for 

2135 # velocity and frequency modes. This case set width to  

2136 # first channel width (for freq) and last one (for vel)  

2137 if width==-1: 

2138 finc=chanfreqs1d[-1]-chanfreqs1d[-2] 

2139 else: 

2140 finc=chanfreqs1d[1]-chanfreqs1d[0] 

2141 

2142 # still need to convert to target reference frame! 

2143 elif(type(width)==str): 

2144 if(qa.quantity(width)['unit'].find('Hz') > -1): 

2145 finc=qa.convert(qa.quantity(width),'Hz')['value'] 

2146 if(nchan ==-1): 

2147 if(qa.quantity(start)['unit'].find('Hz') > -1): 

2148 if width==-1: # must be in velocity order (i.e. startf is max) 

2149 bw=startf-chanfreqs1d[0] 

2150 else: 

2151 bw=chanfreqs1d[-1]-startf 

2152 else: 

2153 bw=chanfreqs1d[-1]-chanfreqs1d[start] 

2154 if(bw < 0): 

2155 raise TypeError("Start parameter is outside the data range") 

2156 if(qa.quantity(width)['unit'].find('Hz') > -1): 

2157 qnchan=qa.convert(qa.div(qa.quantity(bw,'Hz'),qa.quantity(width))) 

2158 #DP loc_nchan=int(math.ceil(qnchan['value']))+1 

2159 loc_nchan=int(round(qnchan['value']))+1 

2160 else: 

2161 #DP loc_nchan=int(math.ceil(bw/finc))+1 

2162 loc_nchan=int(round(bw/finc))+1 

2163 else: 

2164 loc_nchan=nchan 

2165 for i in range(int(loc_nchan)): 

2166 if(i==0): 

2167 freqlist.append(startf) 

2168 else: 

2169 freqlist.append(freqlist[-1]+finc) 

2170 return freqlist, finc 

2171 

2172 

2173 def setChannelizeDefault(self,mode,spw,field,nchan,start,width,frame,veltype,phasec, restf,obstime=''): 

2174 """ 

2175 Determine appropriate values for channelization 

2176 parameters when default values are used 

2177 for mode='velocity' or 'frequency' or 'channel' 

2178 This makes use of ms.cvelfreqs. 

2179 """ 

2180 ############### 

2181 # for debugging 

2182 ############### 

2183 debug=False 

2184 ############### 

2185 spectable=self.getsubtable(self.vis[self.sortedvisindx[0]], "SPECTRAL_WINDOW") 

2186 tb.open(spectable) 

2187 chanfreqscol=tb.getvarcol('CHAN_FREQ') 

2188 chanwidcol=tb.getvarcol('CHAN_WIDTH') 

2189 spwframe=tb.getcol('MEAS_FREQ_REF'); 

2190 tb.close() 

2191 # first parse spw parameter: 

2192 # use MSSelect if possible 

2193 if len(self.sortedvislist) > 0: 

2194 invis = self.sortedvislist[0] 

2195 inspw = self.vis.index(self.sortedvislist[0]) 

2196 else: 

2197 invis = self.vis[0] 

2198 inspw = 0 

2199 ms.open(invis) 

2200 if type(spw)==list: 

2201 spw=spw[inspw] 

2202 if spw in ('-1', '*', '', ' '): 

2203 spw='*' 

2204 if field=='': 

2205 field='*' 

2206 mssel=ms.msseltoindex(vis=invis, spw=spw, field=field) 

2207 selspw=mssel['spw'] 

2208 selfield=mssel['field'] 

2209 chaninds=mssel['channel'].tolist() 

2210 chanst0 = chaninds[0][1] 

2211 

2212 # frame 

2213 spw0=selspw[0] 

2214 chanfreqs=chanfreqscol['r'+str(spw0+1)].transpose()[0] 

2215 chanres = chanwidcol['r'+str(spw0+1)].transpose()[0] 

2216 

2217 # ascending or desending data frequencies? 

2218 # based on selected first spw's first CHANNEL WIDTH  

2219 # ==> some MS data may have positive chan width 

2220 # so changed to look at first two channels of chanfreq (TT) 

2221 #if chanres[0] < 0: 

2222 descending = False 

2223 if len(chanfreqs) > 1 : 

2224 if chanfreqs[1]-chanfreqs[0] < 0: 

2225 descending = True 

2226 else: 

2227 if chanres[0] < 0: 

2228 descending = True 

2229 

2230 # set dataspecframe: 

2231 elspecframe=["REST", 

2232 "LSRK", 

2233 "LSRD", 

2234 "BARY", 

2235 "GEO", 

2236 "TOPO", 

2237 "GALACTO", 

2238 "LGROUP", 

2239 "CMB"] 

2240 self.dataspecframe=elspecframe[spwframe[spw0]]; 

2241 

2242 # set usespecframe: user's frame if set, otherwise data's frame 

2243 if(frame != ''): 

2244 self.usespecframe=frame 

2245 self.inframe=True 

2246 else: 

2247 self.usespecframe=self.dataspecframe 

2248 

2249 # some start and width default handling 

2250 if mode!='channel': 

2251 if width==1: 

2252 width='' 

2253 if start==0: 

2254 start='' 

2255 

2256 #get restfreq 

2257 if restf=='': 

2258 fldtab=self.getsubtable(invis,'FIELD') 

2259 tb.open(fldtab) 

2260 nfld=tb.nrows() 

2261 try: 

2262 if nfld >= selfield[0]: 

2263 srcid=tb.getcell('SOURCE_ID',selfield[0]) 

2264 else: 

2265 if mode=='velocity': 

2266 raise TypeError( "Cannot set REST_FREQUENCY from the data: " + 

2267 "no SOURCE corresponding field ID=%s, please supply restfreq" % selfield[0] ) 

2268 finally: 

2269 tb.close() 

2270 #SOUECE_ID in FIELD table = -1 if no SOURCE table 

2271 if srcid==-1: 

2272 if mode=='velocity': 

2273 raise TypeError("Rest frequency info is not supplied") 

2274 try: 

2275 srctab=self.getsubtable(invis, 'SOURCE') 

2276 tb.open(srctab) 

2277 tb2=tb.query('SOURCE_ID==%s' % srcid) 

2278 nsrc = tb2.nrows() 

2279 if nsrc > 0 and tb2.iscelldefined('REST_FREQUENCY',0): 

2280 rfqs = tb2.getcell('REST_FREQUENCY',0) 

2281 if len(rfqs)>0: 

2282 restf=str(rfqs[0])+'Hz' 

2283 else: 

2284 if mode=='velocity': 

2285 raise TypeError( "Cannot set REST_FREQUENCY from the data: " + 

2286 "REST_FREQUENCY entry for ID %s in SOURCE table is empty, please supply restfreq" % srcid ) 

2287 else: 

2288 if mode=='velocity': 

2289 raise TypeError( "Cannot set REST_FREQUENCY from the data: " + 

2290 "no SOURCE corresponding field ID=%s, please supply restfreq" % selfield[0] ) 

2291 finally: 

2292 tb.close() 

2293 tb2.close() 

2294 

2295 if type(phasec)==list: 

2296 inphasec=phasec[0] 

2297 else: 

2298 inphasec=phasec 

2299 if type(inphasec)==str and inphasec.isdigit(): 

2300 inphasec=int(inphasec) 

2301 #if nchan==1: 

2302 # use data chan freqs 

2303 # newfreqs=chanfreqs 

2304 #else: 

2305 # obstime not included here 

2306 if debug: casalog.post("before ms.cvelfreqs (start,width,nchan)===> {} {} {}". 

2307 format(start, width, nchan)) 

2308 try: 

2309 newfreqs=ms.cvelfreqs(spwids=selspw,fieldids=selfield,mode=mode,nchan=nchan, 

2310 start=start,width=width,phasec=inphasec, restfreq=restf, 

2311 outframe=self.usespecframe,veltype=veltype).tolist() 

2312 except: 

2313 # ms must be closed here if ms.cvelfreqs failed with an exception 

2314 ms.close() 

2315 raise 

2316 ms.close() 

2317 

2318 #casalog.post(newfreqs) 

2319 descendingnewfreqs=False 

2320 if len(newfreqs)>1: 

2321 if newfreqs[1]-newfreqs[0] < 0: 

2322 descendingnewfreqs=True 

2323 

2324 

2325 try: 

2326 if((nchan in [-1, "-1", "", " "]) or (start in [-1, "-1", "", " "])): 

2327 frange=im.advisechansel(msname=invis, spwselection=spw, fieldid=selfield[0], getfreqrange=True) 

2328 startchan=0 

2329 endchan=len(newfreqs)-1 

2330 if(descendingnewfreqs): 

2331 startchan=numpy.min(numpy.where(frange['freqend'] < numpy.array(newfreqs))) 

2332 endchan=numpy.min(numpy.where(frange['freqstart'] < numpy.array(newfreqs))) 

2333 else: 

2334 startchan=numpy.max(numpy.where(frange['freqstart'] > numpy.array(newfreqs))) 

2335 endchan=numpy.max(numpy.where(frange['freqend'] > numpy.array(newfreqs))) 

2336 if((start not in [-1, "-1", "", " "]) and (mode=="channel")): 

2337 startchan=start 

2338 if(nchan not in [-1, "-1", "", " "]): 

2339 endchan=startchan+nchan-1 

2340 newfreqs=(numpy.array(newfreqs)[startchan:endchan]).tolist() 

2341 except: 

2342 pass 

2343 if debug: casalog.post("Mode, Start, width after cvelfreqs = {} {} {}". 

2344 format(mode, start, width)) 

2345 if type(newfreqs)==list and len(newfreqs) ==0: 

2346 raise TypeError( "Output frequency grid cannot be calculated: " + 

2347 " please check start and width parameters" ) 

2348 if debug: 

2349 if len(newfreqs)>1: 

2350 casalog.post("FRAME=" + self.usespecframe) 

2351 casalog.post("newfreqs[0]===>" + newfreqs[0]) 

2352 casalog.post("newfreqs[1]===>" + newfreqs[1]) 

2353 casalog.post("newfreqs[-1]===>" + newfreqs[-1]) 

2354 casalog.post("len(newfreqs)===>" + len(newfreqs)) 

2355 else: 

2356 casalog.post("newfreqs=" + newfreqs) 

2357 

2358 # set output number of channels 

2359 if nchan ==1: 

2360 retnchan=1 

2361 else: 

2362 if len(newfreqs)>1: 

2363 retnchan=len(newfreqs) 

2364 else: 

2365 retnchan=nchan 

2366 newfreqs=chanfreqs.tolist() 

2367 

2368 # set start parameter 

2369 # first analyze data order etc 

2370 reverse=False 

2371 negativew=False 

2372 if descending: 

2373 # channel mode case (width always >0)  

2374 if width!="" and (type(width)==int or type(width)==float): 

2375 if descendingnewfreqs: 

2376 reverse=False 

2377 else: 

2378 reverse=True 

2379 elif width=="": #default width 

2380 if descendingnewfreqs and mode=="frequency": 

2381 reverse=False 

2382 else: 

2383 reverse=True 

2384 

2385 elif type(width)==str: 

2386 if width.lstrip().find('-')==0: 

2387 negativew=True 

2388 if descendingnewfreqs: 

2389 if negativew: 

2390 reverse=False 

2391 else: 

2392 reverse=True 

2393 else: 

2394 if negativew: 

2395 reverse=True 

2396 else: 

2397 reverse=False 

2398 else: #ascending data 

2399 # depends on sign of width only 

2400 # with CAS-3117 latest change(rev.15179), velocity start 

2401 # means lowest velocity for default width 

2402 if width=="" and mode=="velocity": #default width 

2403 # ms.cvelfreqs returns correct order so no reversing 

2404 reverse=False 

2405 elif type(width)==str: 

2406 if width.lstrip().find('-')==0: 

2407 reverse=True 

2408 else: 

2409 reverse=False 

2410 

2411 if reverse: 

2412 newfreqs.reverse() 

2413 #if (start!="" and mode=='channel') or \ 

2414 # (start!="" and type(start)!=int and mode!='channel'): 

2415 # for now to avoid inconsistency later in imagecoordinates2 call 

2416 # user's start parameter is preserved for channel mode only. 

2417 # (i.e. the current code may adjust start parameter for other modes but 

2418 # this probably needs to be changed, especially for multiple ms handling.) 

2419 if ((start not in [-1, "", " "]) and mode=='channel'): 

2420 retstart=start 

2421 else: 

2422 # default cases 

2423 if mode=="frequency": 

2424 retstart=str(newfreqs[0])+'Hz' 

2425 elif mode=="velocity": 

2426 #startfreq=str(newfreqs[-1])+'Hz' 

2427 startfreq=(str(max(newfreqs))+'Hz') if(start=="") else (str(newfreqs[-1])+'Hz') 

2428 retstart=self.convertvf(startfreq,frame,field,restf,veltype) 

2429 elif mode=="channel": 

2430 # default start case, use channel selection from spw 

2431 retstart=chanst0 

2432 

2433 # set width parameter 

2434 if width!="": 

2435 retwidth=width 

2436 else: 

2437 if nchan==1: 

2438 finc = chanres[0] 

2439 else: 

2440 finc = newfreqs[1]-newfreqs[0] 

2441 if debug: casalog.post("finc(newfreqs1-newfreqs0)=" + finc) 

2442 if mode=="frequency": 

2443 # It seems that this is no longer necessary... TT 2013-08-12 

2444 #if descendingnewfreqs: 

2445 # finc = -finc 

2446 retwidth=str(finc)+'Hz' 

2447 elif mode=="velocity": 

2448 # for default width assume it is vel<0 (incresing in freq) 

2449 if descendingnewfreqs: 

2450 ind1=-2 

2451 ind0=-1 

2452 else: 

2453 ind1=-1 

2454 ind0=-2 

2455 v1 = self.convertvf(str(newfreqs[ind1])+'Hz',frame,field,restf,veltype=veltype) 

2456 v0 = self.convertvf(str(newfreqs[ind0])+'Hz',frame,field,restf,veltype=veltype) 

2457 ##v1 = self.convertvf(str(newfreqs[-1])+'Hz',frame,field,restf,veltype=veltype) 

2458 ##v0 = self.convertvf(str(newfreqs[-2])+'Hz',frame,field,restf,veltype=veltype) 

2459 #v1 = self.convertvf(str(newfreqs[1])+'Hz',frame,field,restf,veltype=veltype) 

2460 #v0 = self.convertvf(str(newfreqs[0])+'Hz',frame,field,restf,veltype=veltype) 

2461 if(qa.lt(v0, v1) and start==""): 

2462 ###user used "" as start make sure step is +ve in vel as start is min vel possible for freqs selected 

2463 retwidth=qa.tos(qa.sub(v1, v0)) 

2464 else: 

2465 retwidth = qa.tos(qa.sub(v0, v1)) 

2466 else: 

2467 retwidth=1 

2468 if debug: casalog.post("setChan retwidth=" + retwidth) 

2469 return retnchan, retstart, retwidth 

2470 

2471 def setChannelizeNonDefault(self, mode,spw,field,nchan,start,width,frame, 

2472 veltype,phasec, restf): 

2473 """ 

2474 Determine appropriate values for channelization 

2475 parameters when default values are used 

2476 for mode='velocity' or 'frequency' or 'channel' 

2477 This does not replaces setChannelization and make no use of ms.cvelfreqs. 

2478 """ 

2479 

2480 

2481 #spw='0:1~4^2;10~12, ,1~3:3~10^3,4~6,*:7' 

2482 #vis='ngc5921/ngc5921.demo.ms' 

2483 

2484 if type(spw)!=str: 

2485 spw='' 

2486 

2487 if spw.strip()=='': 

2488 spw='*' 

2489 

2490 freqs=set() 

2491 wset=[] 

2492 chunk=spw.split(',') 

2493 for i in range(len(chunk)): 

2494 #casalog.post(chunk[i] + '------') 

2495 ck=chunk[i].strip() 

2496 if len(ck)==0: 

2497 continue 

2498 

2499 wc=ck.split(':') 

2500 window=wc[0].strip() 

2501 

2502 if len(wc)==2: 

2503 sec=wc[1].split(';') 

2504 for k in range(len(sec)): 

2505 chans=sec[k].strip() 

2506 sep=chans.split('^') 

2507 se=sep[0].strip() 

2508 t=1 

2509 if len(sep)==2: 

2510 t=sep[1].strip() 

2511 se=se.split('~') 

2512 s=se[0].strip() 

2513 if len(se)==2: 

2514 e=se[1].strip() 

2515 else: 

2516 e=-1 

2517 wd=window.split('~') 

2518 if len(wd)==2: 

2519 wds=int(wd[0]) 

2520 wde=int(wd[1]) 

2521 for l in range(wds, wde): 

2522 #casalog.post... (l, s, e, t) 

2523 wset.append([l, s, e, t]) 

2524 else: 

2525 #casalog.post ...(wd[0], s, e, t) 

2526 if e==-1: 

2527 try: 

2528 e=int(s)+1 

2529 except: 

2530 e=s 

2531 wset.append([wd[0], s, e, t]) 

2532 else: 

2533 win=window.split('~') 

2534 if len(win)==2: 

2535 wds=int(win[0]) 

2536 wde=int(win[1]) 

2537 for l in range(wds, wde): 

2538 #casalog.post... (l, 0, -1, 1) 

2539 wset.append([l, 0, -1, 1]) 

2540 else: 

2541 #casalog.post...(win[0], 0, -1, 1) 

2542 wset.append([win[0], 0, -1, 1]) 

2543 

2544 #casalog.post(wset) 

2545 for i in range(len(wset)): 

2546 for j in range(4): 

2547 try: 

2548 wset[i][j]=int(wset[i][j]) 

2549 except: 

2550 wset[i][j]=-1 

2551 #casalog.post(wset) 

2552 spectable=self.getsubtable(self.vis[self.sortedvisindx[0]], "SPECTRAL_WINDOW") 

2553 tb.open(spectable) 

2554 nr=tb.nrows() 

2555 for i in range(len(wset)): 

2556 if wset[i][0]==-1: 

2557 w=range(nr) 

2558 elif wset[i][0]<nr: 

2559 w=[wset[i][0]] 

2560 else: 

2561 w=range(0) 

2562 for j in w: 

2563 chanfreqs=tb.getcell('CHAN_FREQ', j) 

2564 if wset[i][2]==-1: 

2565 wset[i][2]=len(chanfreqs) 

2566 if wset[i][2]>len(chanfreqs): 

2567 wset[i][2]=len(chanfreqs) 

2568 #casalog.post...(wset[i][1], wset[i][2], len(chanfreqs), wset[i][3]) 

2569 for k in range(wset[i][1], wset[i][2], wset[i][3]): 

2570 #casalog.post(k) 

2571 freqs.add(chanfreqs[k]) 

2572 tb.close() 

2573 freqs=list(freqs) 

2574 freqs.sort() 

2575 #casalog.post...(freqs[0], freqs[-1]) 

2576 

2577 if mode=='channel': 

2578 star=0 

2579 if type(start)==str: 

2580 try: 

2581 star=int(start) 

2582 except: 

2583 star=0 

2584 if type(start)==int: 

2585 star=start 

2586 if star>len(freqs) or star<0: 

2587 star=0 

2588 

2589 if nchan==-1: 

2590 nchan=len(freqs) 

2591 

2592 widt=1 

2593 if type(width)==str: 

2594 try: 

2595 widt=int(width) 

2596 except: 

2597 widt=1 

2598 if type(width)==int: 

2599 widt=width 

2600 if widt==0: 

2601 widt=1 

2602 if widt>0: 

2603 nchan=max(min(int((len(freqs)-star)/widt), nchan), 1) 

2604 else: 

2605 nchan=max(min(int((-star)/widt), nchan), 1) 

2606 widt=-widt 

2607 star=max(star-nchan*widt, 0) 

2608 

2609 if mode=='frequency': 

2610 star=freqs[0] 

2611 if type(start)!=str: 

2612 star=freqs[0] 

2613 else: 

2614 star=max(qa.quantity(start)['value'], freqs[0]) 

2615 

2616 if nchan==-1: 

2617 nchan=len(freqs) 

2618 

2619 widt=freqs[-1] 

2620 if len(freqs)>1: 

2621 for k in range(len(freqs)-1): 

2622 widt=min(widt, freqs[k+1]-freqs[k]) 

2623 if type(width)==str and width.strip()!='': 

2624 widt=qa.quantity(width)['value'] 

2625 

2626 if widt>0: 

2627 #casalog.post...(star, widt, (freqs[-1]-star)//widt) 

2628 nchan=max(min(int((freqs[-1]-star)//widt), nchan), 1) 

2629 else: 

2630 nchan=max(min(int(freqs[0]-star)//widt, nchan), 1) 

2631 widt=-widt 

2632 star=max(star-nchan*widt, freqs[0]) 

2633 

2634 widt=str(widt)+'Hz' 

2635 star=str(star)+'Hz' 

2636 

2637 if mode=='velocity': 

2638 beg1=self.convertvf(str(freqs[0])+'Hz',frame,field,restf,veltype=veltype) 

2639 beg1=qa.quantity(beg1)['value'] 

2640 end0=self.convertvf(str(freqs[-1])+'Hz',frame,field,restf,veltype=veltype) 

2641 end0=qa.quantity(end0)['value'] 

2642 star=beg1 

2643 if type(start)==str and start.strip()!='': 

2644 star=min(qa.quantity(start)['value'], star) 

2645 star=min(star, end0) 

2646 

2647 #casalog.post...(beg1, star, end0) 

2648 

2649 widt=-end0+beg1 

2650 if len(freqs)>1: 

2651 for k in range(len(freqs)-1): 

2652 st=self.convertvf(str(freqs[k])+'Hz',frame,field,restf,veltype=veltype) 

2653 en=self.convertvf(str(freqs[k+1])+'Hz',frame,field,restf,veltype=veltype) 

2654 widt=min(widt, qa.quantity(en)['value']-qa.quantity(st)['value']) 

2655 widt=-abs(widt) 

2656 

2657 if type(width)==str and width.strip()!='': 

2658 widt=qa.quantity(width)['value'] 

2659 

2660 #casalog.post(widt) 

2661 if widt>0: 

2662 nchan=max(min(int((beg1-star)/widt), nchan), 1) 

2663 #star=0 

2664 else: 

2665 nchan=max(min(int((end0-star)/widt), nchan), 1) 

2666 #widt=-widt 

2667 

2668 widt=str(widt)+'m/s' 

2669 star=str(star)+'m/s' 

2670 

2671 return nchan, star, widt 

2672 

2673 def convertframe(self,fin,frame,field): 

2674 """ 

2675 (not in use: its caller is setChannelization...) 

2676 convert freq frame in dataframe to specfied frame, assume fin in Hz 

2677 retruns converted freq in Hz (value only) 

2678 """ 

2679 # assume set to phasecenter before initChanelization is called 

2680 pc=self.srcdir 

2681 if(type(pc)==str): 

2682 if (pc==''): 

2683 fieldused = field 

2684 if (fieldused ==''): 

2685 fieldused ='0' 

2686 #dir = int(ms.msseltoindex(self.vis,field=fieldused)['field'][0]) 

2687 dir = int(ms.msseltoindex(self.vis[self.sortedvisindx[0]],field=fieldused)['field'][0]) 

2688 else: 

2689 tmpdir = phasecenter 

2690 try: 

2691 #if(len(ms.msseltoindex(self.vis, field=pc)['field']) > 0): 

2692 if(len(ms.msseltoindex(self.vis[self.sortedvisindx[0]], field=pc)['field']) > 0): 

2693 #tmpdir = int(ms.msseltoindex(self.vis,field=pc)['field'][0]) 

2694 tmpdir = int(ms.msseltoindex(self.vis[self.sortedvisindx[0]],field=pc)['field'][0]) 

2695 except Exception as instance: 

2696 tmpdir = pc 

2697 dir = tmpdir 

2698 if type(dir)==str: 

2699 try: 

2700 mrf, ra, dec = dir.split() 

2701 except Exception as instance: 

2702 raise TypeError("Error in a string format for phasecenter") 

2703 mdir = me.direction(mrf, ra, dec) 

2704 else: 

2705 #tb.open(self.vis+'/FIELD') 

2706 fldtab=self.getsubtable(self.vis[self.sortedvisindx[0]],'FIELD') 

2707 tb.open(fldtab) 

2708 srcdir=tb.getcell('DELAY_DIR',dir) 

2709 mrf=tb.getcolkeywords('DELAY_DIR')['MEASINFO']['Ref'] 

2710 tb.close() 

2711 mdir = me.direction(mrf,str(srcdir[0][0])+'rad',str(srcdir[1][0])+'rad') 

2712 #tb.open(self.vis+'/OBSERVATION') 

2713 obstab=self.getsubtable(self.vis[self.sortedvisindx[0]],'OBSERVATION') 

2714 tb.open(obstab) 

2715 telname=tb.getcell('TELESCOPE_NAME',0) 

2716 # use time in main table instead? 

2717 tmr=tb.getcell('TIME_RANGE',0) 

2718 tb.close() 

2719 #casalog.post...("direction=", me.direction(mrf,str(srcdir[0][0])+'rad',str(srcdir[1][0])+'rad')) 

2720 #casalog.post("tmr[1]=" + tmr[1]) 

2721 #caalog.post...("epoch=", me.epoch('utc',qa.convert(qa.quantity(str(tmr[1])+'s'),'d'))) 

2722 me.doframe(me.epoch('utc',qa.convert(qa.quantity(str(tmr[0])+'s'),'d'))) 

2723 me.doframe(me.observatory(telname)) 

2724 me.doframe(mdir) 

2725 f0 = me.frequency(self.dataspecframe, str(fin)+'Hz') 

2726 #casalog.post...("frame=", frame, ' f0=',f0) 

2727 fout = me.measure(f0,frame)['m0']['value'] 

2728 return fout 

2729 

2730 def setspecframe(self,spw): 

2731 """ 

2732 set spectral frame for mfs to data frame based 

2733 on spw selection  

2734 (part copied from setChannelization) 

2735 """ 

2736 #tb.open(self.vis+'/SPECTRAL_WINDOW') 

2737 spectable=self.getsubtable(self.vis[self.sortedvisindx[0]], "SPECTRAL_WINDOW") 

2738 tb.open(spectable) 

2739 spwframe=tb.getcol('MEAS_FREQ_REF'); 

2740 tb.close() 

2741 

2742 # first parse spw parameter: 

2743 

2744 # use MSSelect if possible 

2745 if type(spw)==list: 

2746 spw=spw[self.sortedvisindx[0]] 

2747 

2748 if spw in (-1, '-1', '*', '', ' '): 

2749 spw="*" 

2750 

2751 sel=ms.msseltoindex(self.vis[self.sortedvisindx[0]], spw=spw) 

2752 # spw returned by msseletoindex, spw='0:5~10;10~20'  

2753 # will give spw=[0] and len(spw) not equal to len(chanids) 

2754 # so get spwids from chaninds instead. 

2755 chaninds=sel['channel'].tolist() 

2756 spwinds=[] 

2757 for k in range(len(chaninds)): 

2758 spwinds.append(chaninds[k][0]) 

2759 if(len(spwinds) == 0): 

2760 raise Exception('unable to parse spw parameter '+spw) 

2761 

2762 # the first selected spw  

2763 spw0=spwinds[0] 

2764 

2765 # set dataspecframe: 

2766 elspecframe=["REST", 

2767 "LSRK", 

2768 "LSRD", 

2769 "BARY", 

2770 "GEO", 

2771 "TOPO", 

2772 "GALACTO", 

2773 "LGROUP", 

2774 "CMB"] 

2775 self.dataspecframe=elspecframe[spwframe[spw0]]; 

2776 return 

2777 

2778 def initChaniter(self,nchan,spw,start,width,imagename,mode,tmpdir='_tmpimdir/'): 

2779 """ 

2780 initialize for channel iteration in interactive clean 

2781 --- create a temporary directory, get frequencies for 

2782 mode='channel' 

2783  

2784 Keyword arguments: 

2785 nchan -- no. channels 

2786 spw -- spw  

2787 start -- start modified after channelization function  

2788 width -- width modified after channelization function 

2789 imagename -- from task input  

2790 mode -- from task input 

2791 tmpdir -- temporary directory name to store channel images 

2792  

2793 returns:  

2794 frequencies in a list 

2795 frequency increment 

2796 newmode -- force to set mode to frequency 

2797 tmppath -- path for the temporary directory 

2798 """ 

2799 # create a temporary directory to put channel images 

2800 tmppath=[] 

2801 freqs=[] 

2802 finc=0 

2803 newmode=mode 

2804 for imname in imagename: 

2805 if os.path.dirname(imname)=='': 

2806 tmppath.append(tmpdir) 

2807 else: 

2808 tmppath.append(os.path.dirname(imname)+'/'+tmpdir) 

2809 # clean up old directory 

2810 if os.path.isdir(tmppath[-1]): 

2811 shutil.rmtree(tmppath[-1]) 

2812 os.mkdir(tmppath[-1]) 

2813 #internally converted to frequency mode for mode='channel' 

2814 #to ensure correct frequency axis for output image 

2815 #if mode == 'channel': 

2816 # freqs, finc = self.getfreqs(nchan, spw, start, width) 

2817 # newmode = 'frequency' 

2818 if mode == 'channel': 

2819 # get spectral axis info from the dirty image 

2820 ia.open(imagename[0]+'.image') 

2821 imcsys=ia.coordsys().torecord() 

2822 ia.close() 

2823 # for optical velocity mode, the image will be in tabular form. 

2824 if 'tabular' in imcsys['spectral2']: 

2825 key='tabular' 

2826 else: 

2827 key='wcs' 

2828 cdelt=imcsys['spectral2'][key]['cdelt'] 

2829 crval=imcsys['spectral2'][key]['crval'] 

2830 #cdelt=imcsys['spectral2']['wcs']['cdelt'] 

2831 #crval=imcsys['spectral2']['wcs']['crval'] 

2832 for i in range(nchan): 

2833 if i==0: freqs.append(crval) 

2834 freqs.append(freqs[-1]+cdelt) 

2835 finc = cdelt 

2836 newmode = 'frequency' 

2837 return freqs,finc,newmode,tmppath 

2838 

2839 

2840 def makeTemplateCubes(self, imagename,outlierfile, field, spw, selectdata, timerange, 

2841 uvrange, antenna, scan, observation, intent, mode, facets, cfcache, interpolation, 

2842 imagermode, localFTMachine, mosweight, locnchan, locstart, locwidth, outframe, 

2843 veltype, imsize, cell, phasecenter, restfreq, stokes, weighting, 

2844 robust, uvtaper, outertaper, innertaper, modelimage, restoringbeam, 

2845 usescratch, noise, npixels, padding): 

2846 """ 

2847 make template cubes to be used for chaniter=T interactive clean 

2848 """ 

2849 imageids=[] 

2850 imsizes=[] 

2851 phasecenters=[] 

2852 rootname='' 

2853 multifield=False 

2854 loc_modelimage=modelimage 

2855 newformat=False 

2856 

2857 if len(outlierfile) != 0: 

2858 f_imageids,f_imsizes,f_phasecenters,f_masks,f_modelimages,parms,newformat=self.newreadoutlier(outlierfile) 

2859 if type(imagename) == list or newformat: 

2860 rootname = '' 

2861 else: 

2862 rootname = imagename 

2863 

2864 # combine with the task parameter input 

2865 if type(imagename) == str: 

2866 if newformat: 

2867 imageids.append(imagename) 

2868 imsizes.append(imsize) 

2869 phasecenters.append(phasecenter) 

2870 else: 

2871 imageids=imagename 

2872 imsizes=imsize 

2873 phasecenters=phasecenter 

2874 

2875 #if type(mask) != list: 

2876 # mask=[mask] 

2877 #elif type(mask[0]) != list: 

2878 # mask=[mask] 

2879 if type(loc_modelimage) != list: 

2880 loc_modelimage=[loc_modelimage] 

2881 

2882 #elif type(loc_modelimage[0]) != list and type(imagename) != str: 

2883 #if type(loc_modelimage[0]) != list and \ 

2884 # (type(imagename) != str or (type(imageids)==list and len(imageids)=1)): 

2885 # loc_modelimage=[loc_modelimage] 

2886 if type(loc_modelimage[0]) != list: 

2887 loc_modelimage=[loc_modelimage] 

2888 

2889 # now append readoutlier content 

2890 for indx, name in enumerate(f_imageids): 

2891 imageids.append(name) 

2892 imsizes.append(f_imsizes[indx]) 

2893 phasecenters.append(f_phasecenters[indx]) 

2894 

2895 if newformat: 

2896 #mask.append(f_masks[indx]) 

2897 loc_modelimage.append([f_modelimages[indx]]) 

2898 else: 

2899 if indx!=0: 

2900 loc_modelimage.append([f_modelimages[indx]]) 

2901 

2902 ##if len(imageids) > 1: 

2903 # multifield=True 

2904 else: 

2905 imsizes=imsize 

2906 phasecenters=phasecenter 

2907 imageids=imagename 

2908 

2909 if len(imageids) > 1: 

2910 multifield=True 

2911 

2912 self.imageids=imageids 

2913 # readoutlier need to be run first.... 

2914 self.datsel(field=field, spw=spw, timerange=timerange, uvrange=uvrange, 

2915 antenna=antenna,scan=scan, observation=observation, intent=intent, 

2916 usescratch=usescratch, 

2917 nchan=-1, start=0, width=1) 

2918 

2919 self.definemultiimages(rootname=rootname,imsizes=imsizes,cell=cell, 

2920 stokes=stokes,mode=mode, 

2921 spw=spw, nchan=locnchan, start=locstart, 

2922 width=locwidth, restfreq=restfreq, 

2923 field=field, phasecenters=phasecenters, 

2924 names=imageids, facets=facets, 

2925 outframe=outframe, veltype=veltype, 

2926 makepbim=False, checkpsf=False) 

2927 

2928 self.datweightfilter(field=field, spw=spw, timerange=timerange, 

2929 uvrange=uvrange, antenna=antenna,scan=scan, 

2930 wgttype=weighting, robust=robust, noise=noise, 

2931 npixels=npixels, mosweight=mosweight, 

2932 uvtaper=uvtaper, innertaper=innertaper, outertaper=outertaper, 

2933 usescratch=usescratch, nchan=-1, start=0, width=1) 

2934 # split this  

2935 #self.datselweightfilter(field=field, spw=spw, 

2936 # timerange=timerange, uvrange=uvrange, 

2937 # antenna=antenna, scan=scan, 

2938 # wgttype=weighting, robust=robust, 

2939 # noise=noise, npixels=npixels, 

2940 # mosweight=mosweight, 

2941 # innertaper=innertaper, 

2942 # outertaper=outertaper, 

2943 # calready=calready, nchan=-1, 

2944 # start=0, width=1) 

2945 

2946 #localAlgorithm = getAlgorithm(psfmode, imagermode, gridmode, mode, 

2947 # multiscale, multifield, facets, nterms, 

2948 # 'clark'); 

2949 

2950 #localAlgorithm = 'clark' 

2951 #casalog.post("localAlogrithm=" + localAlgorithm) 

2952 

2953 #self.im.setoptions(ftmachine=localFTMachine, 

2954 # wprojplanes=wprojplanes, 

2955 # freqinterp=interpolation, padding=padding, 

2956 # cfcachedirname=cfcache, pastep=painc, 

2957 # epjtablename=epjtable, 

2958 # applypointingoffsets=False, 

2959 # dopbgriddingcorrections=True) 

2960 self.im.setoptions(ftmachine=localFTMachine, 

2961 freqinterp=interpolation, padding=padding, 

2962 cfcachedirname=cfcache) 

2963 

2964 modelimages=[] 

2965 restoredimage=[] 

2966 residualimage=[] 

2967 psfimage=[] 

2968 fluximage=[] 

2969 for k in range(len(self.imagelist)): 

2970 ia.open(self.imagelist[k]) 

2971 #if (modelimage =='' or modelimage==[]) and multifield: 

2972 # ia.rename(self.imagelist[k]+'.model',overwrite=True) 

2973 #else: 

2974 # ia.remove(verbose=False) 

2975 if ((loc_modelimage =='' or loc_modelimage==[]) or \ 

2976 (type(loc_modelimage)==list and \ 

2977 (loc_modelimage[k]=='' or loc_modelimage[k]==[''] or loc_modelimage[k]==[]))) and multifield: 

2978 ia.rename(self.imagelist[k]+'.model',overwrite=True) 

2979 else: 

2980 modlist=[] 

2981 if type(modelimage)==str: 

2982 modlist=[modelimage] 

2983 # make sure input model image is not removed 

2984 if (not any([inmodel == self.imagelist[k] for inmodel in modlist])) and \ 

2985 (not any([inmodel == self.imagelist[k]+'.model' for inmodel in modlist])): 

2986 # ia.remove(verbose=False) 

2987 ia.rename(self.imagelist[k]+'.model',overwrite=True) 

2988 ia.close() 

2989 

2990 modelimages.append(self.imagelist[k]+'.model') 

2991 restoredimage.append(self.imagelist[k]+'.image') 

2992 residualimage.append(self.imagelist[k]+'.residual') 

2993 psfimage.append(self.imagelist[k]+'.psf') 

2994 if(imagermode=='mosaic'): 

2995 fluximage.append(self.imagelist[k]+'.flux') 

2996 

2997 # make dirty image cube 

2998 if multifield: 

2999 alg='mfclark' 

3000 else: 

3001 alg='clark' 

3002 

3003 self.im.clean(algorithm=alg, niter=0, 

3004 model=modelimages, residual=residualimage, 

3005 image=restoredimage, psfimage=psfimage, 

3006 mask='', interactive=False) 

3007 

3008 

3009 def setChaniterParms(self,finalimagename, spw,chan,start,width,freqs,finc,tmppath): 

3010 """ 

3011 Set parameters for channel by channel iterations 

3012 returns: 

3013 start and width to define each channel image plane 

3014 """ 

3015 retparms={} 

3016 self.maskimages={} 

3017 retparms['imagename']=[tmppath[indx]+os.path.basename(imn)+'.ch'+str(chan) 

3018 for indx, imn in enumerate(finalimagename)] 

3019 

3020 #casalog.post("Processing channel %s " % chan) 

3021 #self._casalog.post("Processing channel %s "% chan) 

3022 

3023 # Select only subset of vis data if possible. 

3024 # It does not work well for multi-spw so need 

3025 # to select with nchan=-1 

3026 retparms['imnchan']=1 

3027 retparms['chanslice']=chan 

3028 

3029 q = qa.quantity 

3030 

3031 # 2010-08-18 note: disable this. Has the problem  

3032 # getting imaging weights correctly when the beginning  

3033 # channels were flagged. 

3034 #if type(spw)==int or len(spw)==1: 

3035 # if width>1: 

3036 # visnchan=width 

3037 # else: 

3038 # visnchan=1 

3039 #else: 

3040 # visnchan=-1 

3041 

3042 visnchan=-1 

3043 retparms['visnchan']=visnchan 

3044 visstart=0 

3045 

3046 if type(start)==int: 

3047 # need to convert to frequencies 

3048 # to ensure correct frequencies in 

3049 # output images(especially for multi-spw) 

3050 # Use freq list instead generated in initChaniter 

3051 imstart=q(freqs[chan],'Hz') 

3052 width=q(finc,'Hz') 

3053 elif start.find('m/s')>0: 

3054 imstart=qat.add(q(start),qat.mul(chan,q(width))) 

3055 elif start.find('Hz')>0: 

3056 imstart=qat.add(q(start),qat.mul(chan,q(width))) 

3057 retparms['width']=width 

3058 retparms['imstart']=imstart 

3059 retparms['visstart']=visstart 

3060 

3061 # 

3062 return retparms 

3063 

3064 def defineChaniterModelimages(self,modelimage,chan,tmppath): 

3065 """ 

3066 chaniter=T specific function to convert input models  

3067 to a model image  

3068 """ 

3069 chanmodimg=[] 

3070 if type(modelimage)==str: 

3071 modelimage=[modelimage] 

3072 indx=0 

3073 for modimg in modelimage: 

3074 if modimg=='': 

3075 return 

3076 if type(modimg)==list: 

3077 chanmodimg=[] 

3078 for img in modimg: 

3079 if img!='': 

3080 if os.path.dirname(img) != '': 

3081 chanmodimg.append(tmppath[0] + '_tmp.' + 

3082 os.path.basename(img)) 

3083 else: 

3084 chanmodimg.append(tmppath[0] + '_tmp.' + img) 

3085 self.getchanimage(cubeimage=img, outim=chanmodimg[-1], chan=chan) 

3086 #self.convertmodelimage(modelimages=chanmodimg, 

3087 # outputmodel=self.imagelist.values()[0]+'.model') 

3088 self.convertmodelimage(modelimages=chanmodimg, 

3089 outputmodel=self.imagelist.values()[indx]+'.model', imindex=indx) 

3090 chanmodimg=[] 

3091 indx+=1 

3092 else: 

3093 if os.path.dirname(modimg) != '': 

3094 chanmodimg.append(tmppath[0] + '_tmp.' + os.path.basename(modimg)) 

3095 else: 

3096 chanmodimg.append(tmppath[0] + '_tmp.' + modimg) 

3097 self.getchanimage(cubeimage=modimg, outim=chanmodimg[-1],chan=chan) 

3098 

3099 #self.convertmodelimage(modelimages=chanmodimg, 

3100 # outputmodel=self.imagelist.values()[0]+'.model') 

3101 self.convertmodelimage(modelimages=chanmodimg, 

3102 outputmodel=self.imagelist.values()[indx]+'.model',imindex=indx) 

3103 # clean up temporary channel model image 

3104 self.cleanupTempFiles(chanmodimg) 

3105 

3106 def convertAllModelImages_old(self,modelimage, mode, nterms, dochaniter, chan, tmppath): 

3107 """ 

3108 wrapper function for convertmodelimage for all different cases 

3109 """ 

3110 if (type(modelimage)!=str and type(modelimage)!=list): 

3111 raise Exception('modelimage must be a string or a list of strings') 

3112 #spectralline modes 

3113 if (not mode=='mfs') or (mode=='mfs' and nterms==1): 

3114 if (not all(img=='' or img==[] or img==[''] for img in modelimage)): 

3115 if dochaniter: 

3116 self.defineChaniterModelimages(modelimage,chan,tmppath) 

3117 else: 

3118 if type(modelimage)== str or \ 

3119 (type(modelimage)==list and len(self.imagelist)==1 and len(modelimage)>1): 

3120 modelimage=[modelimage] 

3121 

3122 #casalog.post("Run convertmodelimage for this list : " + self.imagelist + " with these models : " + modelimage;) 

3123 for j in range(len(self.imagelist)): 

3124 self._casalog.post("Use modelimages: "+str(modelimage[j])+" to create a combined modelimage: " \ 

3125 +self.imagelist.values()[j]+".model", 'DEBUG1') 

3126 if modelimage[j] != '' and modelimage[j] != []: 

3127 self.convertmodelimage(modelimages=modelimage[j], 

3128 outputmodel=self.imagelist.values()[j]+'.model',imindex=j) 

3129 

3130 # elif ....... 

3131 # put mfs with nterms>1 case here 

3132 

3133 ########################################################## 

3134 # Multiple models for one field : [ [ 'm0', 'm1' ] ] 

3135 # Multiple taylor terms and one field : [ [ 't0','t1'] ] 

3136 # Multiple models per field : [ [ 'm0f0', 'm1f0' ] , [ 'm0f1', 'm1f1' ] ] 

3137 # Multiple taylor terms per field : [ [ 't0f0','t1f0' ] , [ 't0f1','t1f1' ] ] 

3138 ########################################################## 

3139 # Cannot do multiple models per taylor term and per field for now. 

3140 # ....... later... [ [ ['m0t0f0','m1t0f0'],['m0t1f0','m1t1f0'] ] , [ [ ['t0f1'] ],[ ['t1f1'] ] ] ] 

3141 ########################################################## 

3142 def convertAllModelImages(self,modelimage, mode, nterms, dochaniter, chan, tmppath): 

3143 """ 

3144 wrapper function for convertmodelimage for all different cases 

3145 """ 

3146 if (type(modelimage)!=str and type(modelimage)!=list): 

3147 raise Exception('modelimage must be a string or a list of strings') 

3148 if (not all(img=='' or img==[] or img==[''] for img in modelimage)): 

3149 if dochaniter: 

3150 self.defineChaniterModelimages(modelimage,chan,tmppath) 

3151 else: 

3152 if type(modelimage)== str or \ 

3153 (type(modelimage)==list and len(self.imagelist)==1 and len(modelimage)>1): 

3154 modelimage=[modelimage] 

3155 

3156 #casalog.post convertmodelimage for this list : " + self.imagelist + " with these models : " + modelimage;) 

3157 #spectralline modes + basic mfs 

3158# if (not mode=='mfs') or (mode=='mfs' and nterms==1): 

3159# for j in range(len(self.imagelist)): # = nfield 

3160# self._casalog.post("Use modelimages: "+str(modelimage[j])+" to create a combined modelimage: " \ 

3161# +self.imagelist.values()[j]+".model", 'DEBUG1') 

3162# if modelimage[j] != '' and modelimage[j] != []: 

3163# self.convertmodelimage(modelimages=modelimage[j], 

3164# outputmodel=self.imagelist.values()[j]+'.model',imindex=j) 

3165 

3166# else: # mfs and nterms>1 

3167 if 1: 

3168 nfld = len(self.imagelist); 

3169 # if only one field, then modelimage must be a list of strings. convert to list of list of str 

3170 # if multiple fields, then model image : list of list of strings 

3171 if nfld != len(modelimage): 

3172 raise Exception('Model images must be same length as fields : '+ str(nfld) + str(modelimage)) 

3173 

3174 for fld in range(nfld): 

3175 modsforfield = modelimage[fld]; # a list 

3176 if type(modsforfield)==str: 

3177 modsforfield = [modsforfield]; 

3178 if nterms==1: 

3179 nimages = len(modsforfield); 

3180 else: 

3181 nimages = min( len(modsforfield), nterms ); ## one model per term 

3182 for tt in range(0,nimages): 

3183 if nterms==1: 

3184 modname = self.imagelist[fld]+'.model'; 

3185 else: 

3186 modname = self.imagelist[fld]+'.model.tt'+str(tt) ; 

3187 if( os.path.exists(modsforfield[tt]) ): 

3188# casalog.post("Found user-specified model image : "+modsforfield[tt]+" . Adding to starting model : "+modname;) 

3189 self._casalog.post("Found user-specified model image : "+modsforfield[tt]+" . Adding to starting model : "+modname); 

3190 self.convertmodelimage(modelimages=modsforfield[tt],outputmodel=modname, imindex=fld); 

3191 else: 

3192 self._casalog.post("Cannot find user-specified model image : "+modsforfield[tt]+" . Continuing with current model : "+modname); 

3193 

3194 

3195 

3196 

3197 

3198 def storeCubeImages(self,cubeimageroot,chanimageroot,chan,imagermode): 

3199 """ 

3200 Put channel images back into CubeImages for chaniter=T mode 

3201  

3202 Keyword arguments: 

3203 cubeimageroot -- root name for output cube image 

3204 chanimageroot -- root name for channel image 

3205 chan -- channel plane index 

3206 imagermode -- imagermode  

3207 """ 

3208 imagext = ['.image','.model','.flux','.residual','.psf','.mask'] 

3209 if imagermode=='mosaic': 

3210 imagext.append('.flux.pbcoverage') 

3211 lerange=range(self.nimages) 

3212 for n in lerange: 

3213 cubeimagerootname=cubeimageroot[n] 

3214 chanimagerootname=chanimageroot[n] 

3215 for ext in imagext: 

3216 nomaskim=False 

3217 cubeimage=cubeimagerootname+ext 

3218 chanimage=chanimagerootname+ext 

3219 if not os.path.exists(cubeimage): 

3220 if os.path.exists(chanimage): 

3221 outim=ia.newimagefromimage(cubeimagerootname+'.model',cubeimage) 

3222 outim.done(verbose=False) 

3223 elif ext=='.mask': 

3224 # unless mask image is given or in interactive mode 

3225 # there is no mask image 

3226 nomaskim=True 

3227 if not nomaskim: 

3228 self.putchanimage(cubeimage, chanimage,chan) 

3229 

3230 def cleanupTempFiles(self, tmppath): 

3231 """ 

3232 Remove the directories listed by tmppath. 

3233 """ 

3234 # Created to deal with temporary dirs created by chaniter=T clean, 

3235 # now used elsewhere too. 

3236 for dir in tmppath: 

3237 if os.path.exists(dir): 

3238 shutil.rmtree(dir) 

3239 

3240 def convertImageFreqFrame(self,imlist): 

3241 """ 

3242 Convert output images to proper output frame 

3243 (after im.clean() executed) 

3244 """ 

3245 if type(imlist)==str: 

3246 imlist=[imlist] 

3247 if self.usespecframe.lower() != 'lsrk': 

3248 if self.usespecframe=='': 

3249 inspectral=self.dataspecframe 

3250 else: 

3251 inspectral=self.usespecframe 

3252 for img in imlist: 

3253 if os.path.exists(img): 

3254 ia.open(img) 

3255 csys=ia.coordsys() 

3256 csys.setconversiontype(spectral=inspectral) 

3257 #casalog.post("csys.torecord spectral2=" + csys.torecord()['spectral2']) 

3258 ia.setcoordsys(csys.torecord()) 

3259 ia.close() 

3260 

3261 def setFrameConversionForMasks(self): 

3262 ''' To be called at the end of clean, so that the output csys can be 

3263 read and set for the mask. This will have the users desired  

3264 conversion layer ''' 

3265 if self.usespecframe=='': 

3266 useframe=self.dataspecframe 

3267 else: 

3268 useframe=self.usespecframe 

3269 

3270 #casalog.post('maskimages.keys : ' + self.maskimages.keys()) 

3271 #casalog.post('imagelist : ' + self.imagelist) 

3272 

3273 for key in self.imagelist.keys(): 

3274 imgmask = self.imagelist[key]+'.mask' 

3275 img = self.imagelist[key]+'.image' 

3276 if not os.path.exists(img): 

3277 img = img+'.tt0' 

3278 # casalog.post('Converting frame for ' + imgmask + ' to ' + useframe) 

3279 if os.path.exists(imgmask) and os.path.exists(img): 

3280 ia.open(img) 

3281 imcsys = ia.coordsys() 

3282 ia.close() 

3283 ia.open(imgmask) 

3284# csys=ia.coordsys() 

3285# csys.setreferencecode('LSRK','spectral',True) 

3286# val = csys.setconversiontype(spectral=useframe) 

3287# casalog.post('Ret val : ' + val + csys.getconversiontype('spectral')) 

3288# ia.setcoordsys(csys.torecord()) 

3289# casalog.post('conv type : '+ imcsys.getconversiontype('spectral')) 

3290 ia.setcoordsys( imcsys.torecord() ) 

3291 ia.close() 

3292 else: 

3293 self._casalog.post('Not converting spectral reference frame for mask image','DEBUG1') 

3294 

3295 

3296 def setReferenceFrameLSRK(self, img = ''): 

3297 ''' To be called to reset reference code and conversion layer to LSRK ''' 

3298 if os.path.exists( img ): 

3299 ia.open( img ) 

3300 mycsys=ia.coordsys() 

3301 if (mycsys.torecord()['spectral2']['conversion']['system']=='REST') : 

3302 ia.close() 

3303 return 

3304 if (mycsys.torecord()['spectral2']['conversion']['system']!='LSRK') : 

3305 mycsys.setreferencecode('LSRK','spectral',True) 

3306 mycsys.setconversiontype(spectral='LSRK') 

3307 ia.setcoordsys( mycsys.torecord() ) 

3308 ia.close() 

3309 

3310 def resmooth(self, model, residual, restored, minOrMax): 

3311 if(minOrMax=="common"): 

3312 ia.open(restored) 

3313 beam=ia.restoringbeam(); 

3314 if('nChannels' not in beam): 

3315 return 

3316 combeam=ia.commonbeam() 

3317 ia.done() 

3318 ia.fromimage(outfile='__restored-copy', infile=restored, overwrite=True) 

3319 ia.open('__restored-copy') 

3320 ib=ia.convolve2d(outfile=restored, major='', minor='', pa='', targetres=True, beam=combeam, overwrite=True) 

3321 ib.done() 

3322 ia.remove() 

3323 ia.done() 

3324 ia.fromimage(outfile='__residual-copy', infile=residual, overwrite=True) 

3325 ia.open('__residual-copy') 

3326 ###need to set a beam first to go around CAS-5433 and then loop 

3327 ia.setrestoringbeam(major=beam['beams']['*0']['*0']['major'], minor=beam['beams']['*0']['*0']['minor'], pa=beam['beams']['*0']['*0']['positionangle'], channel=0, polarization=0) 

3328 nchan=beam['nChannels'] 

3329 for k in range(nchan): 

3330 chstr='*'+str(k) 

3331 ia.setrestoringbeam(beam=beam['beams'][chstr]['*0'], channel=k, polarization=0) 

3332 ib=ia.convolve2d(outfile=residual, major='', minor='', pa='', targetres=True, beam=combeam, overwrite=True) 

3333 ib.done() 

3334 ia.remove() 

3335 ia.done() 

3336 return 

3337 

3338 ###############for min or max 

3339 ia.open(restored) 

3340 beams=ia.restoringbeam() 

3341 if('beams' not in beams): 

3342 ########already has one beam only 

3343 ia.done() 

3344 return 

3345 minArea=1e37 

3346 maxArea=-1e37 

3347 maxchan=-1 

3348 minchan=-1 

3349 theArea=numpy.zeros(beams['nChannels']) 

3350 for k in range(beams['nChannels']): 

3351 ##it must have been really hard to provide proper indices 

3352 theArea[k]=qa.convert(beams['beams']['*'+str(k)]['*0']['major'], 'arcsec')['value'] * qa.convert(beams['beams']['*'+str(k)]['*0']['minor'], 'arcsec')['value'] 

3353 if(theArea[k] > maxArea): 

3354 maxArea=theArea[k] 

3355 maxchan=k 

3356 if(theArea[k] < minArea): 

3357 minArea=theArea[k] 

3358 minchan=k 

3359 maxbeam=[beams['beams']['*'+str(maxchan)]['*0']['major'], beams['beams']['*'+str(maxchan)]['*0']['minor'], beams['beams']['*'+str(maxchan)]['*0']['positionangle']] 

3360 minbeam=[beams['beams']['*'+str(minchan)]['*0']['major'], beams['beams']['*'+str(minchan)]['*0']['minor'], beams['beams']['*'+str(minchan)]['*0']['positionangle']] 

3361 thebeam=minbeam 

3362 tobeDiv=theArea[minchan] 

3363 if(minOrMax=='max'): 

3364 thebeam=maxbeam 

3365 tobeDiv=theArea[maxchan] 

3366 ia.open(residual) 

3367 shp=ia.shape() 

3368 for k in range(beams['nChannels']): 

3369 reg=rg.box(blc=[0,0,0,k], trc=[shp[0]-1, shp[1]-1, shp[2]-1, k]) 

3370 pix=ia.getregion(region=reg) 

3371 pix=pix*theArea[k]/tobeDiv 

3372 ia.putregion(pixels=pix, region=reg) 

3373 ia.done() 

3374 ia.open(model) 

3375 ib=ia.convolve2d(outfile=restored, axes=[0,1], major=thebeam[0], minor=thebeam[1], pa=thebeam[2], overwrite=True) 

3376 ib.calc('"'+restored+'" + '+'"'+residual+'"') 

3377 ib.done() 

3378 ia.done() 

3379 

3380 

3381 

3382 

3383 

3384 @staticmethod 

3385 def getOptimumSize(size): 

3386 ''' 

3387 This returns the next largest even composite of 2, 3, 5, 7 

3388 ''' 

3389 def prime_factors(n, douniq=True): 

3390 """ Return the prime factors of the given number. """ 

3391 factors = [] 

3392 lastresult = n 

3393 sqlast=int(numpy.sqrt(n))+1 

3394 # 1 pixel must a single dish user 

3395 if n == 1: 

3396 return [1] 

3397 c=2 

3398 while 1: 

3399 if (lastresult == 1) or (c > sqlast): 

3400 break 

3401 sqlast=int(numpy.sqrt(lastresult))+1 

3402 while 1: 

3403 if(c > sqlast): 

3404 c=lastresult 

3405 break 

3406 if lastresult % c == 0: 

3407 break 

3408 c += 1 

3409 

3410 factors.append(c) 

3411 lastresult //= c 

3412 if(factors==[]): factors=[n] 

3413 return numpy.unique(factors).tolist() if douniq else factors 

3414 n=size 

3415 if(n%2 != 0): 

3416 n+=1 

3417 fac=prime_factors(n, False) 

3418 for k in range(len(fac)): 

3419 if(fac[k] > 7): 

3420 val=fac[k] 

3421 while(numpy.max(prime_factors(val)) > 7): 

3422 val +=1 

3423 fac[k]=val 

3424 newlarge=numpy.product(fac) 

3425 for k in range(n, newlarge, 2): 

3426 if((numpy.max(prime_factors(k)) < 8)): 

3427 return k 

3428 return newlarge 

3429 

3430 

3431def getFTMachine(gridmode, imagermode, mode, wprojplanes, userftm): 

3432 """ 

3433 A utility function which implements the logic to determine the 

3434 ftmachine name to be used in the under-laying tool. 

3435 """ 

3436# ftm = userftm; 

3437 ftm='ft'; 

3438 if((gridmode != '') and (imagermode=='mosaic')): 

3439 raise Exception(pwd.getpwuid(os.getuid())[4].split()[0]+ " gridmode='"+gridmode + "' combined with " + "imagermode='"+imagermode + "' is not supported yet") 

3440 if ((gridmode == 'widefield') and(wprojplanes > 1 or wprojplanes==-1)): ftm = 'wproject'; 

3441 elif (gridmode == 'aprojection'): ftm = 'awproject'; 

3442 elif (gridmode == 'advancedaprojection'): ftm = 'awproject'; 

3443 elif (imagermode == 'csclean'): ftm = 'ft'; 

3444 elif (imagermode == 'mosaic'): ftm = userftm; 

3445 return ftm; 

3446 

3447def getAlgorithm(psfmode, imagermode, gridmode, mode, 

3448 multiscale, multifield, facets, nterms, useralg): 

3449 """ 

3450 A utility function which implements the logic to determine the 

3451 deconvolution algorithm to be used in the under-laying tool. 

3452 """ 

3453 alg=useralg 

3454 addMultiField=False; 

3455 

3456 if((type(multiscale)==list) and 

3457 (len(multiscale) > 0) and 

3458 (sum(multiscale) > 0)): alg = 'multiscale'; 

3459 elif ((psfmode == 'clark') or (psfmode == 'clarkstokes') or (psfmode == 'hogbom')): alg=psfmode; 

3460 

3461 if ((imagermode == '') and (multifield)): addMultiField=True; 

3462 if (imagermode == 'mosaic'): addMultiField=True; 

3463 if (imagermode == 'csclean'): addMultiField = True; #!!!! 

3464 

3465 if ((mode == 'mfs') and (nterms > 1)): 

3466 alg = 'msmfs'; 

3467 if(imagermode == 'mosaic'): 

3468 ##casalog.post('Multi-Term MFS with a mosaic is experimental') 

3469 raise Exception('msmfs (nterms>1) not allowed with imagermode=' + imagermode + '. For now, msmfs automatically performs cs-clean type iterations') 

3470 if (multifield): 

3471 addMultiField = True; 

3472 if facets > 1: 

3473 raise Exception('msmfs (nterms>1) with facets>1 is not yet available') 

3474 if( (mode=='mfs') and (nterms<1) ): 

3475 raise Exception('nterms must be > 0') 

3476 

3477# if (gridmode == 'widefield'): alg='mfclark'; 

3478 

3479 if (gridmode == 'widefield'): 

3480 addMultiField=True; 

3481 if (facets > 1): 

3482 if(alg.count('multiscale') > 0): 

3483 raise Exception('multiscale with facets > 1 not allowed for now') 

3484 if (psfmode==''): psfmode='clark'; 

3485 if((psfmode == 'clark') or (psfmode == 'hogbom')): 

3486 alg='wf'+psfmode; 

3487 addMultiField=False; 

3488 else: 

3489 addMultiField=True; 

3490# addMultiField=False; 

3491 

3492# 

3493# if facets > 1 && mutliscale ==> fail 

3494 

3495 

3496 if (addMultiField and (alg[0:2] != 'mf') and (alg != 'msmfs')): alg = 'mf' + alg; 

3497 return alg; 

3498 

3499def convert_numpydtype(listobj): 

3500 """ 

3501 utility function to covert list with elements in numpy.int or 

3502 numpy.float types to python int/float 

3503 """ 

3504 import array as pyarr 

3505 floatarr=False 

3506 intarr=False 

3507 for elm in listobj: 

3508 if numpy.issubdtype(type(elm), numpy.float): 

3509 floatarr = True 

3510 elif numpy.issubdtype(type(elm), numpy.int): 

3511 intarr = True 

3512 if floatarr or (floatarr and intarr): 

3513 temparr=pyarr.array('f', listobj) 

3514 elif intarr: 

3515 temparr=pyarr.array('i', listobj) 

3516 else: 

3517 temparr = listobj 

3518 return temparr 

3519 return temparr.tolist() 

3520 

3521def get_func_params(func, loc_vars): 

3522 """ returns a dictionary of parameter name:vale for all the parameters of a function 

3523 

3524 :param func: function object (for example a task function) 

3525 :param loc_vars: locals() from inside the function. 

3526 """ 

3527 param_names = func.__code__.co_varnames[:func.__code__.co_argcount] 

3528 params = [(name, loc_vars[name]) for name in param_names] 

3529 return params 

3530 

3531def write_task_history(images, tname, params, clog): 

3532 """ 

3533 Update image/logtable with the taskname, CASA version and all task parameters 

3534 CASR-571. Replicates the same format as mstools.write_history. 

3535 

3536 :param images: list of images to write the history to 

3537 :param tname: task name to use as origin of the history 

3538 :param params: list of task parameters as a tuple (name, value) 

3539 :param clog: casa log object 

3540 """ 

3541 iat = iatool() 

3542 

3543 history = ['taskname={0}'.format(tname)] 

3544 history.append(_casa_version_string()) 

3545 # Add all task arguments. 

3546 for name, val in params: 

3547 msg = "%-11s = " % name 

3548 if type(val) == str: 

3549 msg += '"' 

3550 msg += str(val) 

3551 if type(val) == str: 

3552 msg += '"' 

3553 history.append(msg) 

3554 

3555 for img in images: 

3556 iat_open = False 

3557 try: 

3558 iat.open(img) 

3559 iat_open = True 

3560 iat.sethistory(origin=tname, history=history) 

3561 except RuntimeError: 

3562 clog.post('Could not open this directory as an image to write history: {}'. 

3563 format(img), 'DEBUG') 

3564 finally: 

3565 if iat_open: 

3566 iat.close() 

3567 iat.done() 

3568 

3569def write_tclean_history(imagename, tname, params, clog): 

3570 """ 

3571 Update image/logtable with the taskname, CASA version and all task parameters 

3572 CASR-571. Replicates the same format as mstools.write_history. 

3573 

3574 :param imagename: imagename prefi as used in tclean 

3575 :param tname: task name to use as origin of the history 

3576 :param params: list of task parameters as a tuple (name, value) 

3577 :param clog: casa log object 

3578 """ 

3579 

3580 def filter_img_names(img_exts): 

3581 """ 

3582 Applies name (extension) exclusions to not try to open tclean outputs files 

3583 and/or leftovers that are not images (even if they share the same name as the 

3584 proper images). 

3585 

3586 Some of the files excluded here can cause spurious messages (image tool will 

3587 print a SEVERE error to the log when open fails) if for example while running 

3588 several test cases one of them fails or misbehaves leaving temporary files 

3589 behind. 

3590 

3591 :param img_exts: list of image names (different extensions) 

3592 :returns: list of image names after filtering out undesired ones 

3593 """ 

3594 accept = [] 

3595 regex = re.compile('^' + re.escape(imagename) + '[0-9]*_?[0-9]*\..+') 

3596 for img in img_exts: 

3597 if img.endswith(('.cf', '.cfcache', '.workdirectory', '.work.temp', '.txt')): 

3598 continue 

3599 

3600 # ensure only 'imgname' + optional integer + .* 

3601 res = re.match(regex, img) 

3602 if res: 

3603 accept.append(img) 

3604 return accept 

3605 

3606 def filter_obvious_nonimages(img_exts): 

3607 """ 

3608 Try to filter out files that are not images but have been placed in the same 

3609 directory and share the same prefix name as the images. 

3610 For example, images have to be directories. All non-dir files can be filtered 

3611 out. It also checks for a logtable subdirectory with a table.info file, which 

3612 is expected in CASA images. 

3613 

3614 This is to not even try to open them (with the iatool or similar). 

3615 See CAS-13464 for additional complications around tclean output image names. 

3616 

3617 :param img_exts: list of image names (different extensions) 

3618 :returns: list of image names after filtering out the ones that do not seem 

3619 to be images. 

3620 """ 

3621 path_check = ['logtable', 'table.info'] 

3622 accept = [img for img in img_exts if 

3623 os.path.isdir(img) and os.path.isfile(os.path.join(img, *path_check))] 

3624 return accept 

3625 

3626 img_exts = glob.glob(imagename + '*.*') 

3627 img_exts = filter_img_names(img_exts) 

3628 img_exts = filter_obvious_nonimages(img_exts) 

3629 clog.post("Searching for images with prefix '{}'... Found these, writing history " 

3630 "into them: {}".format(imagename, img_exts)) 

3631 write_task_history(img_exts, tname, params, clog)