Coverage for /home/casatest/venv/lib/python3.12/site-packages/casatasks/private/task_tclean.py: 47%

272 statements  

« prev     ^ index     » next       coverage.py v7.10.4, created at 2025-08-21 07:43 +0000

1################################################ 

2# Refactored Clean task 

3# 

4# v1.0: 2012.10.05, U.R.V. 

5# 

6################################################ 

7 

8import platform 

9import os 

10import shutil 

11import numpy 

12import copy 

13import filecmp 

14import time 

15import pdb 

16 

17 

18from casatasks import casalog 

19 

20from casatasks.private.imagerhelpers.imager_base import PySynthesisImager 

21from casatasks.private.imagerhelpers.input_parameters import saveparams2last 

22from casatasks.private.imagerhelpers.imager_parallel_continuum import PyParallelContSynthesisImager 

23from casatasks.private.imagerhelpers.imager_parallel_cube import PyParallelCubeSynthesisImager 

24from casatasks.private.imagerhelpers.imager_mtmfs_via_cube import PyMtmfsViaCubeSynthesisImager 

25from casatasks.private.imagerhelpers.input_parameters import ImagerParameters 

26from casatasks.private.imagerhelpers.imager_return_dict import ImagingDict 

27from .cleanhelper import write_tclean_history, get_func_params 

28from casatools import table 

29from casatools import image 

30from casatools import synthesisutils 

31from casatools import synthesisimager 

32 

33try: 

34 from casampi.MPIEnvironment import MPIEnvironment 

35 from casampi import MPIInterface 

36 

37 mpi_available = True 

38except ImportError: 

39 mpi_available = False 

40 

41 

42# if you want to save tclean.last.* from python call of tclean uncomment the decorator 

43#@saveparams2last(multibackup=True) 

44def tclean( 

45 ####### Data Selection 

46 vis, # ='', 

47 selectdata, 

48 field, # ='', 

49 spw, # ='', 

50 timerange, # ='', 

51 uvrange, # ='', 

52 antenna, # ='', 

53 scan, # ='', 

54 observation, # ='', 

55 intent, # ='', 

56 datacolumn, # ='corrected', 

57 ####### Image definition 

58 imagename, # ='', 

59 imsize, # =[100,100], 

60 cell, # =['1.0arcsec','1.0arcsec'], 

61 phasecenter, # ='J2000 19:59:28.500 +40.44.01.50', 

62 stokes, # ='I', 

63 projection, # ='SIN', 

64 startmodel, # ='', 

65 ## Spectral parameters 

66 specmode, # ='mfs', 

67 reffreq, # ='', 

68 nchan, # =1, 

69 start, # ='', 

70 width, # ='', 

71 outframe, # ='LSRK', 

72 veltype, # ='', 

73 restfreq, # =[''], 

74 # sysvel,#='', 

75 # sysvelframe,#='', 

76 interpolation, # ='', 

77 perchanweightdensity, # ='' 

78 ## 

79 ####### Gridding parameters 

80 gridder, # ='ft', 

81 facets, # =1, 

82 psfphasecenter, # ='', 

83 wprojplanes, # =1, 

84 ### PB 

85 vptable, 

86 mosweight, # =True 

87 aterm, # =True, 

88 psterm, # =True, 

89 wbawp, # = True, 

90 conjbeams, # = True, 

91 cfcache, # = "", 

92 usepointing, # =false 

93 computepastep, # =360.0, 

94 rotatepastep, # =360.0, 

95 pointingoffsetsigdev, # =[10.0], 

96 pblimit, # =0.01, 

97 normtype, # ='flatnoise', 

98 ####### Deconvolution parameters 

99 deconvolver, # ='hogbom', 

100 scales, # =[], 

101 nterms, # =1, 

102 smallscalebias, # =0.0 

103 fusedthreshold, # =0.0 

104 largestscale, # =-1 

105 ### restoration options 

106 restoration, 

107 restoringbeam, # =[], 

108 pbcor, 

109 ##### Outliers 

110 outlierfile, # ='', 

111 ##### Weighting 

112 weighting, # ='natural', 

113 robust, # =0.5, 

114 noise, # 0.0Jy 

115 npixels, # =0, 

116 # uvtaper,#=False, 

117 uvtaper, # =[], 

118 ##### Iteration control 

119 niter,#=0, 

120 gain,#=0.1, 

121 threshold,#=0.0, 

122 nsigma,#=0.0 

123 cycleniter,#=0, 

124 cyclefactor,#=1.0, 

125 minpsffraction,#=0.1, 

126 maxpsffraction,#=0.8, 

127 interactive,#=False, 

128 nmajor,#=-1, 

129 fullsummary,#=False, 

130 

131 ##### (new) Mask parameters 

132 usemask, # ='user', 

133 mask, # ='', 

134 pbmask, # ='', 

135 # maskthreshold,#='', 

136 # maskresolution,#='', 

137 # nmask,#=0, 

138 ##### automask by multithresh 

139 sidelobethreshold, # =5.0, 

140 noisethreshold, # =3.0, 

141 lownoisethreshold, # =3.0, 

142 negativethreshold, # =0.0, 

143 smoothfactor, # =1.0, 

144 minbeamfrac, # =0.3, 

145 cutthreshold, # =0.01, 

146 growiterations, # =100 

147 dogrowprune, # =True 

148 minpercentchange, # =0.0 

149 verbose, # =False 

150 fastnoise, # =False 

151 ## Misc 

152 restart, # =True, 

153 savemodel, # ="none", 

154 # makeimages,#="auto" 

155 calcres, # =True, 

156 calcpsf, # =True, 

157 psfcutoff, # =0.35 

158 ####### State parameters 

159 parallel, 

160): # =False): 

161 

162 ##################################################### 

163 #### Sanity checks and controls 

164 ##################################################### 

165 ### Move these checks elsewhere ?  

166 inpparams=locals().copy() 

167# saveinputs(inpparams) 

168 ###now deal with parameters which are not the same name 

169 inpparams['msname']= inpparams.pop('vis') 

170 inpparams['timestr']= inpparams.pop('timerange') 

171 inpparams['uvdist']= inpparams.pop('uvrange') 

172 inpparams['obs']= inpparams.pop('observation') 

173 inpparams['state']= inpparams.pop('intent') 

174 inpparams['loopgain']=inpparams.pop('gain') 

175 inpparams['scalebias']=inpparams.pop('smallscalebias') 

176 # 

177 # Force chanchunks=1 always now (CAS-13400) 

178 inpparams['chanchunks']=1 

179 

180 if specmode=='cont': 

181 specmode='mfs' 

182 inpparams['specmode']='mfs' 

183# if specmode=='mfs' and nterms==1 and deconvolver == "mtmfs": 

184# casalog.post( "The MTMFS deconvolution algorithm (deconvolver='mtmfs') needs nterms>1.Please set nterms=2 (or more). ", "WARN", "task_tclean" ) 

185# return 

186 

187 # Force chanchunks=1 always now (CAS-13400) 

188 inpparams["chanchunks"] = 1 

189 

190 if specmode == "cont": 

191 specmode = "mfs" 

192 inpparams["specmode"] = "mfs" 

193 # if specmode=='mfs' and nterms==1 and deconvolver == "mtmfs": 

194 # casalog.post( "The MTMFS deconvolution algorithm (deconvolver='mtmfs') needs nterms>1.Please set nterms=2 (or more). ", "WARN", "task_tclean" ) 

195 # return 

196 

197 if deconvolver == "mtmfs" and (specmode == "cube" or specmode == "cubedata"): 

198 casalog.post( 

199 "The MSMFS algorithm (deconvolver='mtmfs') with specmode='cube' is not supported", 

200 "WARN", 

201 "task_tclean", 

202 ) 

203 return 

204 

205 if ( 

206 (specmode == "cube" or specmode == "cubedata" or specmode == "cubesource") 

207 ) and (parallel == False and mpi_available and MPIEnvironment.is_mpi_enabled): 

208 casalog.post( 

209 "When CASA is launched with mpi, the parallel=False option has no effect for 'cube' imaging for gridder='mosaic','wproject','standard' and major cycles are always executed in parallel.\n", 

210 "WARN", 

211 "task_tclean", 

212 ) 

213 # casalog.post( "Setting parameter parallel=False with specmode='cube' when launching CASA with mpi has no effect except for awproject.", "WARN", "task_tclean" ) 

214 

215 ## Part of CAS-13814, checking for the only options compatible with mtmfs_via_cube.  

216 if specmode=="mvc": 

217 if deconvolver != 'mtmfs' or nterms<=1 : 

218 casalog.post("The specmode='mvc' option requires the deconvolver to be 'mtmfs' and 'nterms>1.", 

219 "WARN", 

220 "task_tclean") 

221 return 

222 

223 ## Part of CAS-13814, moving warnings about pbcor and widebandpbcor from the C++ code to here, for better access to user-settings. 

224 if specmode=='mfs' and deconvolver=='mtmfs' and gridder in ['standard','mosaic'] and pbcor==True: 

225 casalog.post("For specmode='mfs' and deconvolver='mtmfs', the option of pbcor=True divides each restored Taylor coefficient image by the pb.tt0 image. This correction ignores the frequency-dependence of the primary beam and does not correct for PB spectral index. It is scientifically valid only for small fractional bandwidths. For more accurate wideband primary beam correction (if needed), please use one of the following options : (1) specmode='mvc' with gridder='standard' or 'mosaic' with pbcor=True, (2) conjbeams=True and wbawp=True with gridder='awproject' and pbcor=True.", 

226 "WARN", 

227 "task_tclean") 

228 if perchanweightdensity == False and weighting == "briggsbwtaper": 

229 casalog.post( 

230 "The briggsbwtaper weighting scheme is not compatable with perchanweightdensity=False.", 

231 "WARN", 

232 "task_tclean", 

233 ) 

234 

235 if (specmode == "mfs" or specmode == "cont") and weighting == "briggsbwtaper": 

236 casalog.post( 

237 "The briggsbwtaper weighting scheme is not compatable with specmode='mfs' or 'cont'.", 

238 "WARN", 

239 "task_tclean", 

240 ) 

241 return 

242 

243 if npixels != 0 and weighting == "briggsbwtaper": 

244 casalog.post( 

245 "The briggsbwtaper weighting scheme is not compatable with npixels != 0.", 

246 "WARN", 

247 "task_tclean", 

248 ) 

249 return 

250 

251 if facets > 1 and parallel == True: 

252 casalog.post( 

253 "Facetted imaging currently works only in serial. Please choose pure W-projection instead.", 

254 "WARN", 

255 "task_tclean", 

256 ) 

257 

258 if nmajor < -1: 

259 casalog.post( 

260 "Negative values less than -1 for nmajor are reserved for possible future implementation", 

261 "WARN", 

262 "task_tclean", 

263 ) 

264 return 

265 

266 ## CAS-13814 

267 if (specmode == "mvc" and gridder == 'awproject' and (conjbeams==True or wbawp==False) ): 

268 casalog.post( 

269 "specmode='mvc' requires frequency-dependent primary beams to be used during cube gridding. Please set conjbeams=False and wbawp=True for the awproject gridder.", 

270 "WARN", 

271 "task_tclean", 

272 ) 

273 return 

274 

275 #CAS-13814 

276 if (specmode == "mvc" and gridder == 'mosaic' and conjbeams==True): 

277 casalog.post( 

278 "specmode='mvc' requires frequency-dependent primary beams to be used during cube gridding. Please set conjbeams=False with the mosaic gridder.", 

279 "WARN", 

280 "task_tclean", 

281 ) 

282 return 

283 

284 # CAS-14146 

285 if (specmode == "mfs" and deconvolver == 'mtmfs' and (gridder == 'mosaic' or gridder == 'awp2')): 

286 casalog.post( 

287 "Please consider using specmode=mvc with " + gridder + " gridder" 

288 " as this gridder does not implement conjbeams \n thus it needs a few major cycles to converge towards the correct answer", 

289 "WARN", 

290 "task_tclean", 

291 ) 

292 

293 # CAS-13581 

294 # XXX : Remove this once awp-hpg is released for general use 

295 if gridder == 'awphpg': 

296 casalog.post( 

297 "The awphpg gridder is not available for general use in the CASA 6.7.0 release. It will be made available in a future release.", 

298 "WARN", 

299 "task_tclean", 

300 ) 

301 

302 ##################################################### 

303 #### Construct ImagerParameters object 

304 ##################################################### 

305 

306 imager = None 

307 paramList = None 

308 

309 # Put all parameters into dictionaries and check them. 

310 ##make a dictionary of parameters that ImagerParameters take 

311 

312 defparm = dict( 

313 list( 

314 zip( 

315 ImagerParameters.__init__.__code__.co_varnames[1:], 

316 ImagerParameters.__init__.__defaults__, 

317 ) 

318 ) 

319 ) 

320 ###assign values to the ones passed to tclean and if not defined yet in tclean... 

321 ###assign them the default value of the constructor 

322 bparm = {k: inpparams[k] if k in inpparams else defparm[k] for k in defparm.keys()} 

323 

324 ###default mosweight=True is tripping other gridders as they are not 

325 ###expecting it to be true 

326 if bparm["mosweight"] == True and (not bparm["gridder"] in ['mosaic', 'awp2']): 

327 bparm["mosweight"] = False 

328 

329 if specmode == "mfs": 

330 bparm["perchanweightdensity"] = False 

331 

332 # deprecation message 

333 if usemask == "auto-thresh" or usemask == "auto-thresh2": 

334 casalog.post( 

335 usemask 

336 + " is deprecated, will be removed in CASA 5.4. It is recommended to use auto-multithresh instead", 

337 "WARN", 

338 ) 

339 

340 

341 #paramList.printParameters() 

342 

343 

344 if len(pointingoffsetsigdev)>0 and pointingoffsetsigdev[0]!=0.0 and usepointing==True and gridder.count('awproj')>1: 

345 casalog.post("pointingoffsetsigdev will be used for pointing corrections with AWProjection", "WARN") 

346# elif usepointing==True and pointingoffsetsigdev[0] == 0: 

347# casalog.post("pointingoffsetsigdev is set to zero which is an unphysical value, will proceed with the native sky pixel resolution instead". "WARN") 

348 

349 if ( 

350 len(pointingoffsetsigdev) > 0 

351 and pointingoffsetsigdev[0] != 0.0 

352 and usepointing == True 

353 and gridder.count("awproj") > 1 

354 ): 

355 casalog.post( 

356 "pointingoffsetsigdev will be used for pointing corrections with AWProjection", 

357 "WARN", 

358 ) 

359 # elif usepointing==True and pointingoffsetsigdev[0] == 0: 

360 # casalog.post("pointingoffsetsigdev is set to zero which is an unphysical value, will proceed with the native sky pixel resolution instead". "WARN") 

361 

362 ##pcube may still need to be set to True for some combination of ftmachine etc... 

363 # ========================================================= 

364 concattype = "" 

365 pcube = False 

366 if parallel == True and specmode != "mfs": 

367 if specmode != "mfs": 

368 pcube = False 

369 parallel = False 

370 else: 

371 pcube = True 

372 # ========================================================= 

373 ####set the children to load c++ libraries and applicator 

374 ### make workers ready for c++ based mpicommands 

375 cppparallel = False 

376 if ( 

377 mpi_available 

378 and MPIEnvironment.is_mpi_enabled 

379 and specmode != "mfs" 

380 and not pcube 

381 ): 

382 mint = MPIInterface.MPIInterface() 

383 cl = mint.getCluster() 

384 cl._cluster.pgc("from casatools import synthesisimager", False) 

385 cl._cluster.pgc("si=synthesisimager()", False) 

386 cl._cluster.pgc("si.initmpi()", False) 

387 cppparallel = True 

388 ###ignore chanchunk 

389 bparm['chanchunks']=1 

390 ######awphpg case 

391 if(gridder=='awphpg'): 

392 localsi=synthesisimager() 

393 localsi.inithpg() 

394 # catch non operational case (parallel cube tclean with interative=T) 

395 if pcube and interactive: 

396 casalog.post( 

397 "Interactive mode is not currently supported with parallel apwproject cube CLEANing, please restart by setting interactive=F", 

398 "WARN", 

399 "task_tclean", 

400 ) 

401 return False 

402 

403 

404 if interactive: 

405 # catch non operational case (parallel cube tclean with interative=T) 

406 if pcube: 

407 casalog.post( 

408 "Interactive mode is not currently supported with parallel apwproject cube CLEANing, please restart by setting interactive=F", 

409 "WARN", 

410 "task_tclean", 

411 ) 

412 return False 

413 

414 # Check for casaviewer, if it does not exist flag it up front for macOS 

415 # since casaviewer is no longer provided by default with macOS. Returning 

416 # False instead of throwing an exception results in: 

417 # 

418 # RuntimeError: No active exception to reraise 

419 # 

420 # from tclean run from casashell. 

421 try: 

422 import casaviewer as __test_casaviewer 

423 except: 

424 if platform.system( ) == "Darwin": 

425 casalog.post( 

426 "casaviewer is no longer available for macOS, for more information see: http://go.nrao.edu/casa-viewer-eol Please restart by setting interactive=F", 

427 "WARN", 

428 "task_tclean", 

429 ) 

430 raise RuntimeError( "casaviewer is no longer available for macOS, for more information see: http://go.nrao.edu/casa-viewer-eol" ) 

431 

432 

433 #casalog.post('parameters {}'.format(bparm))  

434 paramList=ImagerParameters(**bparm) 

435 

436 ## Setup Imager objects, for different parallelization schemes. 

437 imagerInst = PySynthesisImager 

438 if specmode == "mvc": 

439 imager = PyMtmfsViaCubeSynthesisImager(params=paramList) 

440 imagerInst = PyMtmfsViaCubeSynthesisImager 

441 elif parallel == False and pcube == False: 

442 imager = PySynthesisImager(params=paramList) 

443 imagerInst = PySynthesisImager 

444 elif parallel == True: 

445 imager = PyParallelContSynthesisImager(params=paramList) 

446 imagerInst = PySynthesisImager 

447 elif pcube == True: 

448 imager = PyParallelCubeSynthesisImager(params=paramList) 

449 imagerInst = PyParallelCubeSynthesisImager 

450 # virtualconcat type - changed from virtualmove to virtualcopy 2016-07-20 

451 # using ia.imageconcat now the name changed to copyvirtual 2019-08-12 

452 concattype = "copyvirtual" 

453 else: 

454 casalog.post("Invalid parallel combination in doClean.", "ERROR") 

455 return 

456 

457 retrec = {} 

458 

459 try: 

460 # if (1): 

461 # pdb.set_trace() 

462 ## Init major cycle elements 

463 t0 = time.time() 

464 imager.initializeImagers() 

465 

466 # Construct the CFCache for AWProject-class of FTMs. For 

467 # other choices the following three calls become NoOps. 

468 # imager.dryGridding(); 

469 # imager.fillCFCache(); 

470 # imager.reloadCFCache(); 

471 

472 imager.initializeNormalizers() 

473 imager.setWeighting() 

474 t1 = time.time() 

475 casalog.post( 

476 "***Time for initializing imager and normalizers: " 

477 + "%.2f" % (t1 - t0) 

478 + " sec", 

479 "INFO3", 

480 "task_tclean", 

481 ) 

482 

483 ## Init minor cycle elements 

484 if niter > 0 or restoration == True: 

485 t0 = time.time() 

486 imager.initializeDeconvolvers() 

487 t1 = time.time() 

488 casalog.post( 

489 "***Time for initializing deconvolver(s): " 

490 + "%.2f" % (t1 - t0) 

491 + " sec", 

492 "INFO3", 

493 "task_tclean", 

494 ) 

495 

496 ####now is the time to check estimated memory 

497 imager.estimatememory() 

498 

499 if niter > 0: 

500 t0 = time.time() 

501 imager.initializeIterationControl() 

502 t1 = time.time() 

503 casalog.post( 

504 "***Time for initializing iteration controller: " 

505 + "%.2f" % (t1 - t0) 

506 + " sec", 

507 "INFO3", 

508 "task_tclean", 

509 ) 

510 

511 ## Make PSF 

512 

513 if calcpsf==True: 

514 t0=time.time(); 

515 #####TESTOO 

516 if(gridder=="awphpg" and specmode=="mfs"): 

517 imager.makePB() 

518 #####TESTOO  

519 imager.makePSF() 

520 if (psfphasecenter != "") and ("mosaic" in gridder): 

521 ###for some reason imager keeps the psf open delete it and recreate it afterwards 

522 imager.deleteTools() 

523 mytb = table() 

524 psfname = ( 

525 bparm["imagename"] + ".psf.tt0" 

526 if (os.path.exists(bparm["imagename"] + ".psf.tt0")) 

527 else bparm["imagename"] + ".psf" 

528 ) 

529 mytb.open(psfname) 

530 miscinf = mytb.getkeyword("miscinfo") 

531 iminf = mytb.getkeyword("imageinfo") 

532 # casalog.post ('miscinfo {} {}'.format(miscinf, iminf)) 

533 mytb.done() 

534 casalog.post("doing with different phasecenter psf") 

535 imager.unlockimages(0) 

536 psfParameters = paramList.getAllPars() 

537 psfParameters["phasecenter"] = psfphasecenter 

538 psfParamList = ImagerParameters(**psfParameters) 

539 psfimager = imagerInst(params=psfParamList) 

540 psfimager.initializeImagers() 

541 psfimager.setWeighting() 

542 psfimager.makeImage("psf", psfParameters["imagename"] + ".psf") 

543 psfimager.deleteTools() 

544 mytb.open(psfname, nomodify=False) 

545 mytb.putkeyword("imageinfo", iminf) 

546 mytb.putkeyword("miscinfo", miscinf) 

547 mytb.done() 

548 mysu=synthesisutils() 

549 mysu.fitPsfBeam(imagename=bparm['imagename'], 

550 nterms=(bparm['nterms'] if deconvolver=="mtmfs" else 1), 

551 psfcutoff=bparm['psfcutoff']) 

552 imager = PySynthesisImager(params=paramList) 

553 imager.initializeImagers() 

554 imager.initializeNormalizers() 

555 imager.setWeighting() 

556 ###redo these as we destroyed things for lock issues 

557 ## Init minor cycle elements 

558 if niter > 0 or restoration == True: 

559 imager.initializeDeconvolvers() 

560 if niter > 0: 

561 imager.initializeIterationControl() 

562 

563 t1 = time.time() 

564 if specmode != "mfs" and ("stand" in gridder): 

565 casalog.post( 

566 "***Time for making PSF and PB: " + "%.2f" % (t1 - t0) + " sec", 

567 "INFO3", 

568 "task_tclean", 

569 ) 

570 else: 

571 casalog.post( 

572 "***Time for making PSF: " + "%.2f" % (t1 - t0) + " sec", 

573 "INFO3", 

574 "task_tclean", 

575 ) 

576 

577 imager.makePB() 

578 

579 t2 = time.time() 

580 if specmode == "mfs" and ("stand" in gridder): 

581 casalog.post( 

582 "***Time for making PB: " + "%.2f" % (t2 - t1) + " sec", 

583 "INFO3", 

584 "task_tclean", 

585 ) 

586 

587 if gridder in ["mosaic", "awproject"]: 

588 imager.checkPB() 

589 

590 if niter >= 0: 

591 

592 ## Make dirty image 

593 if calcres == True: 

594 t0 = time.time() 

595 imager.runMajorCycle(isCleanCycle=False) 

596 t1 = time.time() 

597 casalog.post( 

598 "***Time for major cycle (calcres=T): " 

599 + "%.2f" % (t1 - t0) 

600 + " sec", 

601 "INFO3", 

602 "task_tclean", 

603 ) 

604 

605 ## In case of no deconvolution iterations.... 

606 if niter == 0 and calcres == False: 

607 if savemodel != "none": 

608 imager.predictModel() 

609 

610 # CAS-13960 : Construct return dict for niter=0 case 

611 # If residual image does not exist, summaryminor will not be 

612 # populated. 

613 if niter==0: 

614 id = ImagingDict() 

615 retrec = id.construct_residual_dict(paramList) 

616 

617 ## Do deconvolution and iterations 

618 if niter > 0: 

619 t0 = time.time() 

620 

621 

622 isit = imager.hasConverged() 

623 imager.updateMask() 

624 # if((type(usemask)==str) and ('auto' in usemask)): 

625 # isit = imager.hasConverged() 

626 isit = imager.hasConverged() 

627 t1 = time.time() 

628 casalog.post( 

629 "***Time to update mask: " + "%.2f" % (t1 - t0) + " sec", 

630 "INFO3", 

631 "task_tclean", 

632 ) 

633 while not isit: 

634 t0 = time.time() 

635 ### sometimes after automasking it does not do anything 

636 doneMinor = imager.runMinorCycle() 

637 t1 = time.time() 

638 casalog.post( 

639 "***Time for minor cycle: " + "%.2f" % (t1 - t0) + " sec", 

640 "INFO3", 

641 "task_tclean", 

642 ) 

643 

644 t0 = time.time() 

645 if doneMinor: 

646 imager.runMajorCycle() 

647 t1 = time.time() 

648 casalog.post( 

649 "***Time for major cycle: " + "%.2f" % (t1 - t0) + " sec", 

650 "INFO3", 

651 "task_tclean", 

652 ) 

653 

654 imager.updateMask() 

655 t2 = time.time() 

656 casalog.post( 

657 "***Time to update mask: " + "%.2f" % (t2 - t1) + " sec", 

658 "INFO3", 

659 "task_tclean", 

660 ) 

661 isit = imager.hasConverged() or (not doneMinor) 

662 

663 ## Get summary from iterbot 

664 #if type(interactive) != bool: 

665 retrec=imager.getSummary(fullsummary); 

666 

667 if savemodel!='none' and (interactive==True or usemask=='auto-multithresh' or nsigma>0.0): 

668 paramList.resetParameters() 

669 if parallel and specmode == "mfs": 

670 # For parallel mfs, also needs to reset the parameters for each node 

671 imager.resetSaveModelParams(paramList) 

672 imager.initializeImagers() 

673 imager.predictModel() 

674 

675 ## Restore images. 

676 if restoration == True: 

677 t0 = time.time() 

678 imager.restoreImages() 

679 t1 = time.time() 

680 casalog.post( 

681 "***Time for restoring images: " + "%.2f" % (t1 - t0) + " sec", 

682 "INFO3", 

683 "task_tclean", 

684 ) 

685 if pbcor == True: 

686 t0 = time.time() 

687 imager.pbcorImages() 

688 t1 = time.time() 

689 casalog.post( 

690 "***Time for pb-correcting images: " 

691 + "%.2f" % (t1 - t0) 

692 + " sec", 

693 "INFO3", 

694 "task_tclean", 

695 ) 

696 ######### niter >=0 end if 

697 

698 finally: 

699 ##close tools 

700 # needs to deletools before concat or lock waits for ever 

701 if imager != None: 

702 imager.deleteTools() 

703 if cppparallel: 

704 ###release workers back to python mpi control 

705 si = synthesisimager() 

706 si.releasempi() 

707 if pcube: 

708 casalog.post("running concatImages ...") 

709 casalog.post( 

710 "Running virtualconcat (type=%s) of sub-cubes" % concattype, 

711 "INFO2", 

712 "task_tclean", 

713 ) 

714 imager.concatImages(type=concattype) 

715 # CAS-10721 

716 # if niter>0 and savemodel != "none": 

717 # casalog.post("Please check the casa log file for a message confirming that the model was saved after the last major cycle. If it doesn't exist, please re-run tclean with niter=0,calcres=False,calcpsf=False in order to trigger a 'predict model' step that obeys the savemodel parameter.","WARN","task_tclean") 

718 

719 # Write history at the end, when hopefully all .workdirectory, .work.temp, etc. are gone 

720 # from disk, so they won't be picked up. They need time to disappear on NFS or slow hw. 

721 try: 

722 params = get_func_params(tclean, locals()) 

723 write_tclean_history(imagename, "tclean", params, casalog) 

724 except Exception as exc: 

725 casalog.post("Error updating history (logtable): {} ".format(exc), "WARN") 

726 

727 return retrec 

728 

729 

730##################################################