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

606 statements  

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

1import os 

2import shutil 

3import time 

4import copy 

5import numpy as np 

6import functools 

7 

8from casatools import image as _image, table as _table 

9from casatools import quanta, ms 

10from casatasks import casalog 

11from casatools import synthesisutils as su 

12from .imager_base import PySynthesisImager 

13from .input_parameters import ImagerParameters 

14from typing import Tuple, List, Union, Optional 

15import pdb 

16_ia = _image() 

17_tb = _table() 

18_qa = quanta() 

19_ms = ms() 

20_su = su() 

21 

22SW=True 

23 

24############################################# 

25def time_func(func): 

26 @functools.wraps(func) 

27 def wrap_time(*args, **kwargs): 

28 t0 = time.time() 

29 result = func(*args, **kwargs) 

30 t1 = time.time() 

31 ####print(f'#######Function {func.__name__!r} took {(t1-t0)}s') 

32 return result 

33 return wrap_time 

34 

35class PyMtmfsViaCubeSynthesisImager(PySynthesisImager): 

36 """A subclass of PySynthesisImager, for specmode='mvc' 

37 

38 The idea is to do the major cycle with cube imaging, then convert the cube images 

39 to taylor term ".ttN" images, then do the minor cycle, then convert back to cubes. 

40 """ 

41 @time_func 

42 def __init__(self, params: ImagerParameters) -> None: 

43 # Set up the mfs part for deconv 

44 mfsparams = copy.deepcopy(params) 

45 mfsparams.allimpars["0"]["specmode"] = "mfs" 

46 mfsparams.alldecpars["0"]["specmode"] = "mfs" 

47 # if there is a startmodel make the model 

48 if ( 

49 len(mfsparams.alldecpars["0"]["startmodel"]) 

50 == mfsparams.alldecpars["0"]["nterms"] 

51 ): 

52 self.copy_startmodel( 

53 mfsparams.alldecpars["0"], 

54 mfsparams.allimpars["0"], 

55 mfsparams.allnormpars["0"], 

56 ) 

57 mfsparams.alldecpars["0"]["startmodel"] = "" 

58 mfsparams.allimpars["0"]["startmodel"] = "" 

59 params.alldecpars["0"]["startmodel"] = "" 

60 params.allimpars["0"]["startmodel"] = "" 

61 

62 

63 ################################# 

64 super().__init__(params) 

65 ## print(f'self all impars {self.allimpars}, \n allvars={vars(self)}') 

66 if self.allimpars["0"]["specmode"] != "mvc": 

67 raise RuntimeError( 

68 f"Can't use specmode {self.allimpars['0']['specmode']} with imager helper {self.__class__.__name__}!" 

69 ) 

70 

71 ### Set up and check nchan and reffreq settings.  

72 nchan = self.allimpars["0"]["nchan"] 

73 freqbeg, freqwidth = self.determineFreqRange() 

74 if nchan < 1 : 

75 nchan=int((freqwidth)/(0.1*freqbeg)) #gives around 10 channel for 2:1 BW 

76 if nchan < 5: 

77 nchan=mfsparams.alldecpars["0"]["nterms"] + 1 

78 casalog.post('Calculating nchan from the data range to be '+str(nchan),'INFO') 

79 

80 ## If nchan < nterms, complain. 

81 in_nterms = mfsparams.alldecpars["0"]["nterms"] 

82 if nchan<in_nterms: 

83 raise RuntimeError( 

84 f"nchan (={nchan}) should be >= nterms ( {in_nterms} ) for valid polynomial fits to be feasible. " 

85 ) 

86 

87 if nchan>50: 

88 casalog.post('For mvc (mtmfs_via_cube), one usually needs only about 10 channels across the freq range, to fit Taylor polynomials of a low order','WARN') 

89 

90 in_reffreq = mfsparams.allimpars["0"]["reffreq"] ##### NEED TO MAKE THIS WORK FOR MULTIFIELD... 

91 if in_reffreq == "": ## User has not set it. Calculate default 

92 midfreq = freqbeg + 0.5*freqwidth # midpoint of the freq range found by "determineFreqRange()" in Hz 

93 

94 for k in mfsparams.allimpars: 

95 mfsparams.allimpars[k]["reffreq"] = str(midfreq) + "Hz" 

96 params.allimpars[k]["reffreq"] = str(midfreq)+"Hz" 

97 

98 

99 #print("params.impars", mfsparams.allimpars) 

100 

101 rfreq = _qa.convert(mfsparams.allimpars["0"]["reffreq"] , "Hz")["value"] 

102 #print("REFFREQ = ",rfreq, " ----" , mfsparams.allimpars["0"]["reffreq"]) 

103 if rfreq < freqbeg or rfreq > freqbeg+freqwidth: 

104 casalog.post('The reffreq of ' + mfsparams.allimpars["0"]["reffreq"] + ' is outside the selected frequency range of ' + str(freqbeg) + ' Hz - ' + str(freqbeg+freqwidth) + ' Hz','WARN') 

105 

106 self.mfsImager = PySynthesisImager(mfsparams) 

107 

108 

109 freqwidth = freqwidth / nchan 

110 #print(f"#####freqbeg={freqbeg}, freqwidth={freqwidth}, nchan={nchan} for cube") 

111 # Update some settings: 

112 # - specmode to cube so that we run a cube major cycle 

113 # - deconvolver to hogbom so that major cycle doesn't get confused TODO is this necessary? 

114 for k in self.allimpars: 

115 self.allimpars[k]["specmode"] = "cube" 

116 self.allimpars[k]["start"] = f"{freqbeg}Hz" 

117 self.allimpars[k]["width"] = f"{freqwidth}Hz" 

118 # self.alldecpars[k]['specmode']='cube' 

119 # this is needed for basic check...it is not used 

120 self.allimpars[k]["deconvolver"] = "hogbom" 

121 for k in self.allgridpars: 

122 self.allgridpars[k]["deconvolver"] = "hogbom" 

123 self.allgridpars[k]["interpolation"] = "nearest" 

124 self.allgridpars[k]["conjbeams"]=False 

125 self.allgridpars[k]["wbawp"]=True 

126 for k in self.allnormpars: 

127 self.allnormpars[k]["deconvolver"] = "hogbom" 

128 self.weightpars['usecubebriggs']=False 

129 self.fresh_images: List[str] = [] 

130 self.verify_dec_pars() 

131 ####################################### 

132 @time_func 

133 def determineFreqRange(self) -> Tuple[np.double, np.double]: 

134 minFreq = 1.0e20 

135 maxFreq = 0.0 

136 #pdb.set_trace() 

137 for msid in self.allselpars: 

138 msname = self.allselpars[msid]["msname"] 

139 spwsel = ( 

140 self.allselpars[msid]["spw"] if (self.allselpars[msid]["spw"]) else "*" 

141 ) 

142 fieldsel = ( 

143 self.allselpars[msid]["field"] 

144 if (self.allselpars[msid]["field"]) 

145 else "*" 

146 ) 

147 fieldid = _ms.msseltoindex(vis=msname, spw=spwsel, field=fieldsel)["field"][0] 

148 _tb.open(msname) 

149 fieldids=_tb.getcol("FIELD_ID") 

150 _tb.done() 

151 # have to do this because advisechansel does not work for fieldids not in main 

152 if fieldid not in fieldids: 

153 fieldid=fieldids[0] 

154 frange = _su.advisechansel( 

155 msname=msname, getfreqrange=True, fieldid=fieldid, spwselection=spwsel 

156 ) 

157 if minFreq > _qa.convert(frange["freqstart"], "Hz")["value"]: 

158 minFreq = _qa.convert(frange["freqstart"], "Hz")["value"] 

159 if maxFreq < _qa.convert(frange["freqend"], "Hz")["value"]: 

160 maxFreq = _qa.convert(frange["freqend"], "Hz")["value"] 

161 if(minFreq > maxFreq): 

162 raise Exception("Failed to determine the frequency range to build the cube from the field and spw selection") 

163 

164 #print(f"@@@@@@@MinFreq and MaxFreq = {minFreq}, {maxFreq}") 

165 freqwidth = maxFreq - minFreq 

166 return (minFreq, freqwidth) 

167 

168 ############################################# 

169 @time_func 

170 def verify_dec_pars(self) -> bool: 

171 for immod in range(0, self.NF): 

172 pars = self.alldecpars[str(immod)] 

173 if pars["specmode"] != "mvc": 

174 raise RuntimeError( 

175 f"Creating instance of class {type(self).__name__} with the wrong specmode! Expected 'mvc' but instead got '{pars['specmode']}'!" 

176 ) 

177 if pars["deconvolver"] != "mtmfs": 

178 raise RuntimeError( 

179 f"specmode {pars['specmode']} requires 'mtmfs' deconvolver but instead got '{pars['deconvolver']}'!" 

180 ) 

181 if pars["nterms"] < 2: 

182 raise RuntimeError( 

183 f"specmode {pars['specmode']} requires nterms >1 !" 

184 ) 

185 return True 

186 ############################################## 

187 def get_dec_pars_for_immod(self, immod: int) -> dict: 

188 pars = self.alldecpars[str(immod)] 

189 # Do not do these sneaky things here ...let the user change the parameters themselves 

190 # pars['specmode'] = 'mfs' 

191 return pars 

192 

193 @time_func 

194 def initializeNormalizers(self): 

195 super().initializeNormalizers() 

196 self.mfsImager.initializeNormalizers() 

197 @time_func 

198 def initializeDeconvolvers(self): 

199 # for immod in range(0,self.NF): 

200 # self.SDtools.append(synthesisdeconvolver()) 

201 # self.SDtools[immod].setupdeconvolution(decpars=self.get_dec_pars_for_immod(immod)) 

202 # should initialize mfs deconvolvers 

203 self.mfsImager.initializeDeconvolvers() 

204 

205 ############################################# 

206 @time_func 

207 def check_psf(self, immod): 

208 self.cube2tt(immod, suffixes=["psf", "sumwt"]) 

209 return super().check_psf(immod) 

210 

211 ################################################## 

212 @time_func 

213 def copy_startmodel(self, decpars: dict, impars: dict, normpars: dict) -> None: 

214 """ 

215 As tclean provides capacity for startmodel to be for field 0 only we don't 

216 need to deal with outlier fields 

217 """ 

218 # decpars = self.get_dec_pars_for_immod(0) 

219 # print(f"DECPARS {decpars}") 

220 imagename = decpars["imagename"] 

221 basemod = imagename + ".model" 

222 if len(decpars["startmodel"]) == decpars["nterms"]: 

223 if not os.path.exists(basemod + ".tt0"): 

224 refImage = imagename + ".psf.tt0" 

225 if not os.path.exists(refImage): 

226 self.copy_image(imagename + ".psf", refImage) 

227 for k in range(decpars["nterms"]): 

228 self.regrid_image( 

229 refImage, f"{basemod}.tt{k}", decpars["startmodel"][k] 

230 ) 

231 # As this is being called before __init__ temporarily assign alldecpars 

232 self.alldecpars = {"0": decpars} 

233 self.allimpars = {"0": impars} 

234 self.tt2cube(0) 

235 inpcube = self.get_image_name(0, "model") 

236 pbcube = self.get_image_name(0, "pb") 

237 pblimit = normpars["pblimit"] 

238 if SW==False: 

239 self.modify_cubemodel_with_pb( 

240 modcube=inpcube, pbcube=pbcube, pbtt0=pbcube + ".tt0", pblimit=np.fabs(pblimit) 

241 ) 

242 else: 

243 imname = self.get_dec_pars_for_immod(0)['imagename'] 

244 t0 = time.time() 

245 _su.apply_freq_dep_pb(cubename=imname,mtname=imname,pblimit=np.fabs(pblimit)) 

246 t1 = time.time() 

247 #print(f'#######---- Function apply_freq_dep_pb took {(t1-t0)}s') 

248 

249 del self.alldecpars 

250 del self.allimpars 

251 

252 ################################################## 

253 

254 def get_image_name(self, immod: int, suffix: str, ttN: Optional[int] = None): 

255 decpars = self.get_dec_pars_for_immod(immod) 

256 imagename = decpars["imagename"] 

257 basename = lambda img: f"{img}.{suffix}" 

258 

259 bn = basename(imagename) 

260 if ttN is not None: 

261 return f"{bn}.tt{ttN}" 

262 return bn 

263 

264 def hasConverged(self) -> bool: 

265 # create .ttN taylor term images for the mtmfs deconvolver 

266 # for immod in range(0,self.NF): 

267 # suffixes = ["residual", "sumwt"] 

268 # only need to create the psf taylor term images once (shouldn't change after check_psf) 

269 # self.cube2tt(immod, suffixes=suffixes) 

270 return self.mfsImager.hasConverged() 

271 

272 ############################################# 

273 

274 def initializeIterationControl(self) -> None: 

275 self.mfsImager.initializeIterationControl() 

276 

277 ############################################# 

278 @time_func 

279 def runMajorCycle(self, isCleanCycle: bool = True) -> None: 

280 # hopefully this carries all info for writing last model 

281 self.IBtool = self.mfsImager.IBtool 

282 #time0 = time.time() 

283 super().runMajorCycle(isCleanCycle) 

284 time1 = time.time() 

285 suffixes = ["residual"] #, "sumwt"] 

286 for immod in range(0, self.NF): 

287 inpcube = self.get_image_name(immod, "residual") 

288 pbcube = self.get_image_name(immod, "pb") 

289 cubewt = self.get_image_name(immod, "sumwt") 

290 pblimit = self.allnormpars[str(immod)]["pblimit"] 

291 

292 ##print("USING PB2TTPB from runMajor") 

293 ##self.cubePB2ttPB(pbcube, pbcube + ".tt0", cubewt, np.fabs(pblimit)) 

294 ##self.cube2tt(immod, suffixes=["pb"]) 

295 

296 # self.modify_with_pb(inpcube=inpcube, pbcube=pbcube, cubewt=cubewt, action='div', pblimit=pblimit, freqdep=True) 

297 # self.modify_with_pb(inpcube=inpcube, pbcube=pbcube, cubewt=cubewt, action='mult', pblimit=pblimit, freqdep=False) 

298 if SW==False: 

299 self.removePBSpectralIndex(inpcube, pbcube, pbcube + ".tt0", np.fabs(pblimit)) 

300 else: 

301 imname = self.get_dec_pars_for_immod(immod)['imagename'] 

302 t0 = time.time() 

303 _su.remove_freq_dep_pb(cubename=imname,mtname=imname,pblimit=np.fabs(pblimit)) 

304 t1 = time.time() 

305 #print(f'#######---- Function remove_freq_dep_pb took {(t1-t0)}s') 

306 

307 self.cube2tt(immod, suffixes=suffixes) 

308 #time2 = time.time() 

309 #print(f"MAKE RESidual time, core={time1-time0} s, cube2tt={time2-time1}") 

310 

311 ############################################## 

312 @time_func 

313 def makePSF(self) -> None: 

314 # pdb.set_trace() 

315 time0 = time.time() 

316 super().makePSFCore() 

317 time1 = time.time() 

318 #####have to ensure the pb is made 

319 super().makePB() 

320 pblimit = self.allnormpars['0']["pblimit"] 

321 cubewt = self.get_image_name(0, "sumwt") 

322 pbcube = self.get_image_name(0, "pb") 

323 

324 #print("USING PB2TTPB from makePSF") 

325 #self.cubePB2ttPB(pbcube, pbcube + ".tt0", cubewt, np.fabs(pblimit)) 

326 #suffixes = ["psf", "sumwt", "weight"] 

327 

328 suffixes = ["pb","psf", "sumwt"] 

329 for immod in range(0, self.NF): 

330 self.cube2tt(immod, suffixes=suffixes) 

331 #now that we donot call dividepsfbyweight which did the fitting 

332 #we have to do it now explicitly 

333 self.mfsImager.PStools[immod].makepsfbeamset() 

334 

335# for immod in range(0, self.NF): 

336# self.mfsImager.PStools[immod].gatherpsfweight() 

337# self.mfsImager.PStools[immod].dividepsfbyweight() 

338 time2 = time.time() 

339 #print(f"MAKE psf time, core={time1-time0} s, cube2tt={time2-time1}") 

340 

341 ############################################### 

342 @time_func 

343 def runMinorCycle(self) -> bool: 

344 # convert from cube to .ttN taylor term images for the mtmfs deconvolver 

345 time0 = time.time() 

346 # for immod in range(0,self.NF): 

347 # Before minorcycle : Divide out the frequency-dependent PB, multiply by a common PB. 

348 # inpcube = self.get_image_name(immod, "residual") 

349 # pbcube = self.get_image_name(immod, "pb") 

350 # cubewt = self.get_image_name(immod, "sumwt") 

351 # pblimit = self.allnormpars[str(immod)]['pblimit'] 

352 # self.modify_with_pb(inpcube=inpcube, pbcube=pbcube, cubewt=cubewt, action='div', pblimit=pblimit, freqdep=True) 

353 # self.modify_with_pb(inpcube=inpcube, pbcube=pbcube, cubewt=cubewt, action='mult', pblimit=pblimit, freqdep=False) 

354 

355 # suffixes = ["residual", "psf", "sumwt", "model"] 

356 # only need to create the psf taylor term images once (shouldn't change after check_psf) 

357 # suffixes.remove('psf') 

358 # suffixes=['model'] 

359 # self.cube2tt(immod, suffixes=suffixes) 

360 

361 # run the mtmfs deconvolver 

362 ret = self.mfsImager.runMinorCycle() 

363 time1 = time.time() 

364 # convert back to cube images for the cube major cycle 

365 for immod in range(0, self.NF): 

366 self.tt2cube(immod) 

367 

368 # After minorcycle : Divide out the common PB, Multiply by frequency-dependent PB. 

369 inpcube = self.get_image_name(immod, "model") 

370 pbcube = self.get_image_name(immod, "pb") 

371 # cubewt = self.get_image_name(immod, "sumwt") 

372 pblimit = self.allnormpars[str(immod)]["pblimit"] 

373 # self.modify_with_pb(inpcube=inpcube, pbcube=pbcube, cubewt=cubewt, action='div', pblimit=pblimit, freqdep=False) 

374 # self.modify_with_pb(inpcube=inpcube, pbcube=pbcube, cubewt=cubewt, action='mult', pblimit=pblimit, freqdep=True) 

375 if SW==False: 

376 self.modify_cubemodel_with_pb( 

377 modcube=inpcube, pbcube=pbcube, pbtt0=pbcube + ".tt0", pblimit=np.fabs(pblimit) 

378 ) 

379 else: 

380 imname = self.get_dec_pars_for_immod(immod)['imagename'] 

381 t0 = time.time() 

382 _su.apply_freq_dep_pb(cubename=imname,mtname=imname,pblimit=np.fabs(pblimit)) 

383 t1 = time.time() 

384 #print(f'#######---- Function apply_freq_dep_pb took {(t1-t0)}s') 

385 

386 time2 = time.time() 

387 #print(f"Minorcycle time, minor={time1-time0} s, tt2cube={time2-time1}") 

388 return ret 

389 

390 ############################################################# 

391 @time_func 

392 def updateMask(self) -> None: 

393 return self.mfsImager.updateMask() 

394 

395 ########################################################### 

396 def getSummary(self, fignum : int =1) -> dict: 

397 return self.mfsImager.getSummary(fignum) 

398 

399 ########################################################## 

400 @time_func 

401 def restoreImages(self) -> None: 

402 self.mfsImager.restoreImages() 

403 

404 #################################################### 

405 @time_func 

406 def pbcorImages(self) -> None: 

407 self.mfsImager.pbcorImages() 

408 

409 #################################### 

410 @time_func 

411 def cube2tt(self, immod: int = 0, suffixes: Optional[List[str]] = None) -> None: 

412 """Creates the necessary taylor term images. 

413 

414 Args: 

415 immod: which image facet/outlier field to convert 

416 suffixes: list of images to convert, can include any of ["residual", "psf", "sumwt"] 

417 

418 Outputs: 

419 pb.tt0 

420 residual.tt0..residual.tt(N-1), model.tt0..model.tt(N-1) 

421 psf.tt0..psf.tt(2*N-2) 

422 

423 If incompatible images already exist with the same name, replace them.""" 

424 time0 = time.time() 

425 if suffixes is None: 

426 suffixes = ["pb", "residual", "psf", "sumwt"] 

427 decpars = self.get_dec_pars_for_immod(immod) 

428 nterms = decpars["nterms"] 

429 pblimit = self.allnormpars[str(immod)]["pblimit"] 

430 # determine which images are being converted 

431 imgs = [ 

432 ("pb",1), 

433 ("residual", nterms), 

434 ("psf", nterms * 2 - 1), 

435 ("sumwt", nterms * 2 - 1) 

436 # ("weight", 1), 

437 ] # , ('model',nterms)] 

438 tmp_imgs = [] 

439 for suffix, num_terms in imgs: 

440 if suffix not in suffixes: 

441 continue 

442 if os.path.exists(self.get_image_name(immod, suffix)): 

443 tmp_imgs.append((suffix, num_terms)) 

444 imgs = tmp_imgs 

445 

446 # create the .ttN images 

447 for suffix, num_terms in imgs: 

448 basename = self.get_image_name(immod, suffix) 

449 for N in range(num_terms): 

450 ttname = self.get_image_name(immod, suffix, ttN=N) 

451 

452 # remove the existing image, if any 

453 if os.path.exists(ttname): 

454 # only create the images once per execution 

455 if ttname in self.fresh_images: 

456 continue 

457 # TODO possible optimization where all the data is set to 0 instead 

458 shutil.rmtree(ttname) 

459 

460 # create a new, blank image based off the template baseimage 

461 self.copy_image(template_img=basename, output_img=ttname) 

462 self.copy_nonexistant_keywords(template_img=basename, output_img=ttname) 

463 dopsf = suffix == "psf" or suffix == "sumwt" 

464 if not dopsf and pblimit>0.0: 

465 self.add_mask( 

466 ttname, self.get_image_name(immod, "pb", ttN=0), np.fabs(pblimit) 

467 ) 

468 self.fresh_images.append(ttname) 

469 

470 # convert them images! 

471 cubewt = self.get_image_name(immod, "sumwt") 

472 chanweight = None 

473 if not os.path.exists(cubewt): 

474 cubewt = "" 

475 else: 

476 _ia.open(cubewt) 

477 # nchan = _ia.shape()[3] 

478 chanweight = _ia.getchunk()[0, 0, 0, :] 

479 _ia.done() 

480 # print(f'IMGS={imgs}') 

481 for suffix, num_terms in imgs: 

482 basename = self.get_image_name(immod, suffix) 

483 reffreq = self.allimpars[str(immod)]["reffreq"] 

484 dopsf = suffix == "psf" or suffix == "sumwt" 

485 chwgt = None if suffix != "weight" else chanweight 

486 if SW==False: 

487 self.cube_to_taylor_sum( 

488 cubename=basename, 

489 cubewt=cubewt, 

490 chanwt=chwgt, 

491 mtname=basename, 

492 reffreq=reffreq, 

493 nterms=num_terms, 

494 dopsf=dopsf, 

495 ) 

496 else: 

497 imname = self.get_dec_pars_for_immod(immod)['imagename'] 

498 if suffix == "psf": 

499 imtype=0 ## num_terms should be 2*nterms-1 

500 if suffix == "residual": 

501 imtype=1 ## num_terms should be nterms 

502 if suffix == 'pb': ## may not be used.....  

503 imtype=2 ## num_terms is 1 (for now) 

504 if suffix == "sumwt": 

505 imtype=3 

506 t0=time.time() 

507 _su.cube_to_taylor_sum(cubename=imname,mtname=imname,nterms=nterms,reffreq=reffreq,imtype=imtype,pblimit=np.fabs(pblimit)) 

508 #print(f"Imname : {imname} , suffix : {suffix} and type : {imtype} with pblimit : {pblimit}") 

509 t1 = time.time() 

510 #print(f'#######---- Function cube_to_taylor_sum took {(t1-t0)}s') 

511 

512 

513 if not dopsf and pblimit>0.0: 

514 for theTerm in range(num_terms): 

515 ttname = self.get_image_name(immod, suffix, ttN=theTerm) 

516 # print(f'Adding masks to {ttname}') 

517 self.add_mask( 

518 ttname, self.get_image_name(immod, "pb", ttN=0), np.fabs(pblimit) 

519 ) 

520 time1 = time.time() 

521 #print(f"Time taken in cube2tt={time1-time0}") 

522 # special case: just copy pb 

523 # basename = self.get_image_name(immod, "pb") 

524 # ttname = self.get_image_name(immod, "pb", ttN=0) 

525 # if ((not os.path.exists(ttname)) and os.path.exists(basename)): 

526 # self.copy_image(template_img=basename, output_img=ttname) 

527 # self.copy_nonexistant_keywords(template_img=basename, output_img=ttname) 

528 # #shutil.rmtree(ttname) 

529 # #shutil.copytree(basename, ttname) 

530 # self.cube_to_taylor_sum(cubename=basename, cubewt=cubewt, mtname=basename, reffreq=reffreq, nterms=1, dopsf=False) 

531 # _ia.open(ttname) 

532 # _ia.calc(pixels="'"+ttname+"'/max('"+ttname+"')") 

533 # _ia.done() 

534 

535 # end 

536 @time_func 

537 def tt2cube(self, immod: int =0) -> None: 

538 """Creates or updates the .model image with all new data obtained 

539 from the .model.ttN images. 

540 """ 

541 time0 = time.time() 

542 decpars = self.get_dec_pars_for_immod(immod) 

543 nterms = decpars["nterms"] 

544 imagename = decpars["imagename"] 

545 reffreq = self.allimpars[str(immod)]["reffreq"] 

546 

547 # run the conversion 

548 if SW==False: 

549 self.taylor_model_to_cube( 

550 cubename=imagename, mtname=imagename, reffreq=reffreq, nterms=nterms 

551 ) 

552 else: 

553 t0=time.time() 

554 _su.taylor_coeffs_to_cube(cubename=imagename,mtname=imagename,reffreq=reffreq,nterms=nterms) 

555 t1 = time.time() 

556 #print(f'#######---- Function taylor_coeffs_to_cube took {(t1-t0)}s') 

557 

558 time1 = time.time() 

559 #print(f"Time taken in tt2cube {time1-time0}") 

560 

561 ######################################################################### 

562 @time_func 

563 def regrid_image(self, template_image: str ="", output_image: str ="", input_image: str ="") -> None: 

564 """ 

565 template_image provides the coordinatesystem and shape onto which the 

566 input_image is regridded to and named output_image. 

567 if output_image exists on disk it gets overwritten 

568 """ 

569 _ia.open(template_image) 

570 csys = _ia.coordsys() 

571 shp = _ia.shape() 

572 _ia.done() 

573 _ia.open(input_image) 

574 _ia.regrid( 

575 outfile=output_image, 

576 shape=shp, 

577 csys=csys.torecord(), 

578 axes=[0, 1], 

579 overwrite=True, 

580 force=False, 

581 ) 

582 _ia.done() 

583 

584 ###################################################################### 

585 @time_func 

586 def copy_image(self, template_img: str ="try.psf", output_img: str ="try.zeros.psf") -> None: 

587 # get the shape 

588 _ia.open(template_img) 

589 shape = _ia.shape() 

590 nchan = _ia.shape()[3] 

591 csys = _ia.coordsys() 

592 pixeltype = _ia.pixeltype() 

593 _ia.close() 

594 _ia.done() 

595 

596 # get the data type 

597 dtype = np.single 

598 pixelprefix = pixeltype[0] # for 'f'loat, 'd'ouble, or 'c'omplex 

599 if pixeltype == "double": 

600 dtype = np.double 

601 elif pixeltype == "complex": 

602 dtype = np.csingle 

603 elif pixeltype == "dcomplex": 

604 dtype = np.cdouble 

605 pixelprefix = "cd" 

606 # Get the frequency and BW correct 

607 minfreq = csys.toworld([0, 0, 0, 0])["numeric"][3] 

608 maxfreq = csys.toworld([0, 0, 0, nchan - 1])["numeric"][3] 

609 a = csys.increment(type="spectral") 

610 a["numeric"] *= nchan 

611 csys.setincrement(a, type="spectral") 

612 b = csys.referencevalue(type="spectral") 

613 b["numeric"] = (minfreq + maxfreq) / 2.0 

614 csys.setreferencevalue(b, type="spectral") 

615 csys.setreferencepixel(0.0, "spectral") 

616 # populate some pixels 

617 shape[3] = 1 # taylor term images don't use channels 

618 pixels = np.zeros(shape, dtype=dtype) 

619 

620 # create the new outputmask 

621 _ia.fromarray(output_img, csys=csys.torecord(), pixels=pixels, type=pixelprefix) 

622 _ia.close() 

623 _ia.done() 

624 

625 ################################################ 

626 @time_func 

627 def copy_nonexistant_keywords( 

628 self, template_img: str ="try.psf", output_img: str ="try.zeros.psf" 

629 ) -> None : 

630 _tb.open(template_img) 

631 new_ii = _tb.getkeyword("imageinfo") 

632 _tb.close() 

633 if "perplanebeams" in new_ii: 

634 del new_ii["perplanebeams"] 

635 old_ii = {} 

636 _tb.open(output_img, nomodify=False) 

637 kws = _tb.keywordnames() 

638 if "imageinfo" in kws: 

639 old_ii = _tb.getkeyword("imageinfo") 

640 old_ii.update(new_ii) 

641 # for kw in old_kws: 

642 # del new_kws[kw] 

643 # for kw in new_kws: 

644 # old_kws[kw]=new_kws[kw] 

645 # casalog.post(f"{template_img} to {output_img} imageinfo: {old_ii}\n\n\n", "WARN") 

646 _tb.putkeyword("imageinfo", old_ii) 

647 _tb.close() 

648 _ia.open(template_img) 

649 miscinf = _ia.miscinfo() 

650 _ia.done() 

651 _ia.open(output_img) 

652 newmiscinf = _ia.miscinfo() 

653 newmiscinf.update(miscinf) 

654 _ia.setmiscinfo(newmiscinf) 

655 _ia.done() 

656 

657 ################################################ 

658 def get_freq_list(self, imname=""): 

659 """Get the list of frequencies for the given image, one for each channel. 

660 

661 Returns: 

662 list[float] The frequencies for each channel in the image, in Hz. 

663 

664 From: 

665 sdint_helper.py 

666 """ 

667 

668 _ia.open(imname) 

669 csys = _ia.coordsys() 

670 shp = _ia.shape() 

671 _ia.close() 

672 

673 if csys.axiscoordinatetypes()[3] == "Spectral": 

674 restfreq = csys.referencevalue()["numeric"][ 

675 3 

676 ] # /1.0e+09; # convert more generally.. 

677 freqincrement = csys.increment()["numeric"][3] # /1.0e+09; 

678 freqlist = [] 

679 for chan in range(0, shp[3]): 

680 freqlist.append(restfreq + chan * freqincrement) 

681 elif csys.axiscoordinatetypes()[3] == "Tabular": 

682 freqlist = csys.torecord()["tabular2"]["worldvalues"] # /1.0e+09; 

683 else: 

684 casalog.post("Unknown frequency axis. Exiting.", "SEVERE") 

685 return False 

686 

687 csys.done() 

688 return freqlist 

689 

690 ####################################################### 

691 @time_func 

692 def cubePB2ttPB(self, cubePB="", ttPB="", sumwt="", pblimit=0.2): 

693 """ 

694 convert the cube PB to an average PB 

695 """ 

696 time0 = time.time() 

697 # special case: just copy pb 

698 if (not os.path.exists(ttPB)) and os.path.exists(cubePB): 

699 self.copy_image(template_img=cubePB, output_img=ttPB) 

700 self.copy_nonexistant_keywords(template_img=cubePB, output_img=ttPB) 

701 # shutil.rmtree(ttname) 

702 # shutil.copytree(basename, ttname) 

703 # self.cube_to_taylor_sum(cubename=basename, cubewt=cubewt, mtname=basename, reffreq=reffreq, nterms=1, dopsf=False) 

704 _ia.open(ttPB) 

705 pix = np.zeros(_ia.shape(), dtype=np.float64) 

706 _ia.done() 

707 _ia.open(cubePB) 

708 #print(f"STATS of cube pb {_ia.statistics()}") 

709 shp = _ia.shape() 

710 cwt = np.ones((shp[3])) 

711 if os.path.exists(sumwt): 

712 _ib = _image() 

713 _ib.open(sumwt) 

714 if _ib.shape()[2] == shp[3]: 

715 cwt = _ib.getchunk(blc=[0, 0, 0, 0], trc=[0, 0, 0, shp[3] - 1]) 

716 _ib.done() 

717 

718 for k in range(shp[3]): 

719 # print(f'chan {k}, max {np.max(pix)}, {np.min(pix)}') 

720 pix += ( 

721 _ia.getchunk( 

722 blc=[0, 0, 0, k], trc=[shp[0] - 1, shp[1] - 1, shp[2] - 1, k] 

723 ) 

724 * cwt[k] 

725 ) 

726 _ia.done() 

727 

728 _ia.open(ttPB) 

729 _ia.putchunk(pix) 

730 _ia.done() 

731 _ia.open(ttPB) 

732 _ia.calc(pixels="'" + ttPB + "'/max('" + ttPB + "')") 

733 _ia.calcmask(mask="'" + ttPB + "' > " + str(pblimit)) 

734 _ia.done() 

735 time1 = time.time() 

736 #print(f"Time taken in cubePB2ttPB={time1-time0}") 

737 

738 ################################################ 

739 @time_func 

740 def cube_to_taylor_sum( 

741 self, 

742 cubename="", 

743 cubewt="", 

744 chanwt=None, 

745 mtname="", 

746 reffreq="1.5GHz", 

747 nterms=2, 

748 dopsf=False, 

749 ): 

750 """ 

751 Convert Cubes (output of major cycle) to Taylor weighted averages (inputs to the minor cycle) 

752 Input : Cube image <cubename>, with channels weighted by image <cubewt> 

753 Output : Set of images : <mtname>.tt0, <mtname>.tt1, etc... 

754 Algorithm: I_ttN = sum([ I_v * ((f-ref)/ref)**N for f in freqs ]) 

755 

756 Args: 

757 cubename: Name of a cube image to interpret into a set of taylor term .ttN images, eg "try.residual", "joint.cube.psf". 

758 cubewt: Name of a .sumwt image that contains the per-channel weighting for the interferometer image. 

759 chanwt: List of 0s and 1s, one per channel, to effectively disable the effect of a channel on the resulting images. 

760 mtname: The prefix output name, to be concatenated with ".ttN" strings, eg "try_mt.residual", "joint.multiterm.psf" 

761 These images should already exist by the time this function is called. 

762 It's suggested that this have the same suffix as cubename. 

763 reffreq: reference frequency, like for tclean 

764 nterms: number of taylor terms to fit the spectral index to 

765 dopsf: Signals that cubename represents a point source function, should be true if cubename ends with ".psf" or ".sumwt". 

766 If true, then output 2*nterms-1 ttN images. 

767 

768 From: 

769 sdint_helper.py 

770 """ 

771# if dopsf is True: 

772# nterms = 2 * nterms - 1 

773 

774 pix = [] 

775 for tt in range(0, nterms): 

776 _ia.open(mtname + ".tt" + str(tt)) 

777 pix.append(_ia.getchunk()) 

778 _ia.close() 

779 pix[tt].fill(0.0) 

780 

781 _ia.open(cubename) 

782 shp = _ia.shape() 

783 _ia.close() 

784 

785 _ia.open(cubewt) 

786 cwt = _ia.getchunk()[0, 0, 0, :] 

787 _ia.close() 

788 # This is a problem for mosaics cwt has no meaning one should use 

789 # the weightimage as a sensitivity weight 

790 # cwt_weight = copy.deepcopy(cwt) 

791 cwt.fill(1.0) 

792 

793 ########## 

794 

795 freqlist = self.get_freq_list(cubename) 

796 if reffreq == "": 

797 # from task_sdintimaging.py 

798 reffreq = str((freqlist[0] + freqlist[len(freqlist) - 1]) / 2.0) + "Hz" 

799 refnu = _qa.convert(_qa.quantity(reffreq), "Hz")["value"] 

800 # print(f'REFNU={refnu}') 

801 if shp[3] != len(cwt) or len(freqlist) != len(cwt): 

802 raise Exception("Nchan shape mismatch between cube and sumwt.") 

803 

804 if isinstance(chanwt, type(None)): 

805 chanwt = np.ones(len(freqlist), "float") 

806 cwt = cwt * chanwt # Merge the weights and flags. 

807 

808 sumchanwt = np.sum(cwt) # This is a weight 

809 if sumchanwt == 0: 

810 raise Exception("Weights are all zero ! ") 

811 

812 for i in range(len(freqlist)): 

813 wt = (freqlist[i] - refnu) / refnu 

814 _ia.open(cubename) 

815 implane = _ia.getchunk(blc=[0, 0, 0, i], trc=[shp[0], shp[1], 0, i]) 

816 _ia.close() 

817 for tt in range(0, nterms): 

818 pix[tt] = pix[tt] + (wt**tt) * implane * cwt[i] 

819 

820 for tt in range(0, nterms): 

821 pix[tt] = pix[tt] / sumchanwt 

822 

823 for tt in range(0, nterms): 

824 _ia.open(mtname + ".tt" + str(tt)) 

825 _ia.putchunk(pix[tt]) 

826 _ia.close() 

827 

828 ################################################ 

829 @time_func 

830 def taylor_model_to_cube(self, cubename="", mtname="", reffreq="1.5GHz", nterms=2): 

831 """ 

832 Convert Taylor coefficients (output of minor cycle) to cube (input to major cycle) 

833 Input : Set of images with suffix : .model.tt0, .model.tt1, etc... 

834 Output : Cube .model image 

835 Algorithm: I_v = sum([ I_ttN * ((f-ref)/ref)**N for f in freqs ]) 

836 

837 Args: 

838 cubename: Name of a cube image, to be conconcatenated with ".model" or ".psf", eg "try" 

839 This image will be updated with the data from the set of taylor term .ttN images from mtname. 

840 The "<cubename>.model" image should already exist by the time this function is called, or 

841 else the "<cubename>.psf" image will be copied and used in its place. 

842 mtname: The prefix input name, to be concatenated with ".model.ttN" strings, eg "try" 

843 These images should already exist by the time this function is called. 

844 It's suggested that this have same suffix as cubename. 

845 reffreq: reference frequency, like for tclean 

846 nterms: number of taylor terms to fit the spectral index to 

847 

848 From: 

849 sdint_helper.py 

850 """ 

851 if not os.path.exists(cubename + ".model"): 

852 shutil.copytree(cubename + ".psf", cubename + ".model") 

853 _ia.open(cubename + ".model") 

854 _ia.set(0.0) 

855 _ia.setrestoringbeam(remove=True) 

856 _ia.setbrightnessunit("Jy/pixel") 

857 _ia.close() 

858 

859 freqlist = self.get_freq_list(cubename + ".psf") 

860 if reffreq == "": 

861 # from task_sdintimaging.py 

862 reffreq = str((freqlist[0] + freqlist[len(freqlist) - 1]) / 2.0) + "Hz" 

863 refnu = _qa.convert(_qa.quantity(reffreq), "Hz")["value"] 

864 

865 # print(f'modelREFNU= {refnu}') 

866 pix = [] 

867 

868 for tt in range(0, nterms): 

869 _ia.open(mtname + ".model.tt" + str(tt)) 

870 pix.append(_ia.getchunk()) 

871 _ia.close() 

872 

873 _ia.open(cubename + ".model") 

874 # shp = _ia.shape() 

875 _ia.close() 

876 

877 implane = np.zeros(pix[0].shape, dtype=type(pix[0][0, 0, 0, 0])) 

878 

879 for i in range(len(freqlist)): 

880 wt = (freqlist[i] - refnu) / refnu 

881 implane.fill(0.0) 

882 for tt in range(0, nterms): 

883 implane = implane + (wt**tt) * pix[tt] 

884 _ia.open(cubename + ".model") 

885 _ia.putchunk(implane, blc=[0, 0, 0, i]) 

886 _ia.close() 

887 

888 ############################################# 

889 @time_func 

890 def modify_cubemodel_with_pb(self, modcube="", pbcube="", pbtt0="", pblimit=0.2): 

891 """ 

892 divide channel model by the common average beam and multiply it back by the channel beam 

893 

894 """ 

895 time0 = time.time() 

896 _ia.open(modcube) 

897 shp = _ia.shape() 

898 nchan = shp[3] 

899 _ib = _image() 

900 _ib.open(pbtt0) 

901 avPB = _ib.getchunk() 

902 if (avPB.shape[0] != shp[0]) or (avPB.shape[1] != shp[1]): 

903 _ia.done() 

904 _ib.done() 

905 raise Exception( 

906 f"Modify model : shape of {pbtt0} is not the same as {modcube}" 

907 ) 

908 _ib.done() 

909 _ib.open(pbcube) 

910 if nchan != _ib.shape()[3]: 

911 _ia.done() 

912 _ib.done() 

913 raise Exception( 

914 f"Modify model: number of channels of {modcube} is not the same as {pbcube}" 

915 ) 

916 for k in range(nchan): 

917 fac = _ib.getchunk(blc=[0, 0, 0, k], trc=[shp[0] - 1, shp[1] - 1, 0, k]) 

918 fac[avPB >= pblimit] /= avPB[avPB >= pblimit] 

919 fac[avPB < pblimit] = 0.0 

920 chandat = _ia.getchunk(blc=[0, 0, 0, k], trc=[shp[0] - 1, shp[1] - 1, 0, k]) 

921 # print(f'Shapes fac={fac.shape}, chandat={chandat.shape}') 

922 chandat *= fac 

923 _ia.putchunk(chandat, blc=[0, 0, 0, k]) 

924 _ia.done() 

925 _ib.done() 

926 time1 = time.time() 

927 #print(f"Time taken in modify cube model by PB is {time1-time0}") 

928 

929 ################## 

930 @time_func 

931 def removePBSpectralIndex(self, cube="", pbcube="", pbtt0="", pblimit=0.2): 

932 """ 

933 divide channel image by channel beam and multiply it back by the 

934 common beam 

935 

936 """ 

937 time0 = time.time() 

938 _ia.open(cube) 

939 shp = _ia.shape() 

940 nchan = shp[3] 

941 _ib = _image() 

942 _ib.open(pbtt0) 

943 avPB = _ib.getchunk() 

944 if (avPB.shape[0] != shp[0]) or (avPB.shape[1] != shp[1]): 

945 _ia.done() 

946 _ib.done() 

947 raise Exception( 

948 f"removePBSpectralIndex : shape of {pbtt0} is not the same as {cube}" 

949 ) 

950 _ib.done() 

951 _ib.open(pbcube) 

952 if nchan != _ib.shape()[3]: 

953 _ib.done() 

954 _ia.done() 

955 raise Exception( 

956 f"removePBSpectralIndex: number of channels of {cube} is not the same as {pbcube}" 

957 ) 

958 for k in range(nchan): 

959 fac = copy.deepcopy(avPB) 

960 divid = _ib.getchunk(blc=[0, 0, 0, k], trc=[shp[0] - 1, shp[1] - 1, 0, k]) 

961 # print(f'shapes fac={fac.shape}, divid={divid.shape}') 

962 # print(f'chan={k}, max min divid= {np.max(divid)}, {np.min(divid)}, fac, {np.max(fac)}, {np.min(fac)}') 

963 fac[divid > 0.0] /= divid[divid > 0.0] 

964 fac[avPB < pblimit] = 0.0 

965 chandat = _ia.getchunk(blc=[0, 0, 0, k], trc=[shp[0] - 1, shp[1] - 1, 0, k]) 

966 chandat *= fac 

967 _ia.putchunk(chandat, blc=[0, 0, 0, k]) 

968 _ia.done() 

969 _ib.done() 

970 time1 = time.time() 

971 #print(f"Time taken for removeSpecIndex = {time1-time0}") 

972 

973 ################################################ 

974 @time_func 

975 def modify_with_pb( 

976 self, 

977 inpcube="", 

978 pbcube="", 

979 cubewt="", 

980 chanwt=None, 

981 action="mult", 

982 pblimit=0.2, 

983 freqdep=True, 

984 ): 

985 """ 

986 Multiply or divide by the PB 

987 

988 Args: 

989 inpcube: The cube to be modified. For example: "try.int.cube.model" 

990 pbcube: The primary beam to multiply/divide by. For example: "try.int.cube.pb" 

991 cubewt: The per-channel weight of the inpcube. For example: "try.int.cube.sumwt" 

992 chanwt: List of 0s and 1s, one per channel, to effectively disable the effect of a channel on the resulting images. 

993 action: 'mult' or 'div', to multiply by the PB or divide by it. 

994 pblimit: For pixels less than this value in the PB, set those same pixels in the inpcube to zero. 

995 freqdep: True for channel by channel, False to use a freq-independent PB from the middle of the list before/after deconvolution 

996 

997 From: 

998 sdint_helper.py 

999 """ 

1000 casalog.post( 

1001 "Modify with PB : " + action + " with frequency dependence " + str(freqdep), 

1002 "INFO", 

1003 ) 

1004 

1005 freqlist = self.get_freq_list(inpcube) 

1006 

1007 _ia.open(inpcube) 

1008 shp = _ia.shape() 

1009 _ia.close() 

1010 

1011 ############## 

1012 # Calculate a reference Primary Beam 

1013 # Weighted sum of pb cube 

1014 

1015 refchan = 0 

1016 _ia.open(pbcube) 

1017 pbplane = _ia.getchunk( 

1018 blc=[0, 0, 0, refchan], trc=[shp[0] - 1, shp[1] - 1, 0, refchan] 

1019 ) 

1020 _ia.close() 

1021 pbplane.fill(0.0) 

1022 

1023 if freqdep is False: 

1024 _ia.open(cubewt) # .sumwt 

1025 cwt = _ia.getchunk()[0, 0, 0, :] 

1026 _ia.close() 

1027 

1028 if shp[3] != len(cwt) or len(freqlist) != len(cwt): 

1029 raise Exception( 

1030 "Modify with PB : Nchan shape mismatch between cube and sumwt." 

1031 ) 

1032 

1033 if chanwt is None: 

1034 chanwt = np.ones(len(freqlist), "float") 

1035 cwt = cwt * chanwt # Merge the weights and flags 

1036 

1037 sumchanwt = np.sum(cwt) 

1038 

1039 if sumchanwt == 0: 

1040 raise Exception("Weights are all zero ! ") 

1041 

1042 for i in range(len(freqlist)): 

1043 # Read the pb per plane 

1044 _ia.open(pbcube) 

1045 pbplane = pbplane + cwt[i] * _ia.getchunk( 

1046 blc=[0, 0, 0, i], trc=[shp[0] - 1, shp[1] - 1, 0, i] 

1047 ) 

1048 _ia.close() 

1049 

1050 pbplane = pbplane / sumchanwt 

1051 

1052 ############## 

1053 

1054 # Special-case for setting the PBmask to be same for all freqs 

1055 if freqdep is False: 

1056 shutil.copytree(pbcube, pbcube + "_tmpcopy") 

1057 

1058 for i in range(len(freqlist)): 

1059 

1060 # Read the pb per plane 

1061 if freqdep is True: 

1062 _ia.open(pbcube) 

1063 pbplane = _ia.getchunk( 

1064 blc=[0, 0, 0, i], trc=[shp[0] - 1, shp[1] - 1, 0, i] 

1065 ) 

1066 _ia.close() 

1067 

1068 # Make a tmp pbcube with the same pb in all planes. This is for the mask. 

1069 if freqdep is False: 

1070 _ia.open(pbcube + "_tmpcopy") 

1071 _ia.putchunk(pbplane, blc=[0, 0, 0, i]) 

1072 _ia.close() 

1073 

1074 _ia.open(inpcube) 

1075 implane = _ia.getchunk(blc=[0, 0, 0, i], trc=[shp[0] - 1, shp[1] - 1, 0, i]) 

1076 

1077 outplane = pbplane.copy() 

1078 outplane.fill(0.0) 

1079 

1080 if action == "mult": 

1081 pbplane[pbplane < pblimit] = 0.0 

1082 outplane = implane * pbplane 

1083 else: 

1084 implane[pbplane < pblimit] = 0.0 

1085 pbplane[pbplane < pblimit] = 1.0 

1086 outplane = implane / pbplane 

1087 

1088 _ia.putchunk(outplane, blc=[0, 0, 0, i]) 

1089 _ia.close() 

1090 

1091 # if freqdep==True: 

1092 # ## Set a mask based on frequency-dependent PB 

1093 # self.add_mask(inpcube,pbcube,pblimit) 

1094 # else: 

1095 if freqdep is False: 

1096 # Set a mask based on the PB in refchan 

1097 self.add_mask(inpcube, pbcube + "_tmpcopy", pblimit) 

1098 shutil.rmtree(pbcube + "_tmpcopy") 

1099 

1100 ################################################ 

1101 @time_func 

1102 def add_mask(self, inpimage="", pbimage="", pblimit=0.2): 

1103 """Create a new mask called 'pbmask' and set it as a defualt mask. 

1104 

1105 Replaces the existing mask with a new mask based on the values in the pbimage 

1106 and pblimit. The new mask name is either 'pbmask' or the name of the existing 

1107 default mask. 

1108 

1109 Args: 

1110 inpimage: image to replace the mask on 

1111 pbimage: image used to calculate the mask values, example "try.pb" 

1112 pblimit: values greater than this in pbimage will be included in the mask 

1113 

1114 From: 

1115 sdint_helper.py 

1116 """ 

1117 if not os.path.exists(pbimage): 

1118 return 

1119 _ia.open(inpimage) 

1120 defaultmaskname = _ia.maskhandler("default")[0] 

1121 # allmasknames = _ia.maskhandler('get') 

1122 

1123 # casalog.post("defaultmaskname=",defaultmaskname) 

1124 # if defaultmaskname!='' and defaultmaskname!='mask0': 

1125 # _ia.calcmask(mask='"'+pbimage+'"'+'>'+str(pblimit), name=defaultmaskname); 

1126 

1127 # elif defaultmaskname=='mask0': 

1128 # if 'pbmask' in allmasknames: 

1129 # _ia.maskhandler('delete','pbmask') 

1130 # _ia.calcmask(mask='"'+pbimage+'"'+'>'+str(pblimit), name='pbmask'); 

1131 if defaultmaskname != "": 

1132 _ia.done() 

1133 return 

1134 _ia.calcmask(mask='"' + pbimage + '"' + ">" + str(pblimit)) 

1135 _ia.close() 

1136 _ia.done() 

1137 

1138 

1139############################################# 

1140#############################################