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

264 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-12 07:14 +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, sanitize_tclean_inputs 

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 

166 inpparams = locals().copy() 

167 # deal with parameters that are not the same name 

168 inpparams, defparm = sanitize_tclean_inputs(inpparams) 

169 

170 if specmode=='cont': 

171 specmode='mfs' 

172 inpparams['specmode']='mfs' 

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

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

175# return 

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 if deconvolver == "mtmfs" and (specmode == "cube" or specmode == "cubedata"): 

188 casalog.post( 

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

190 "WARN", 

191 "task_tclean", 

192 ) 

193 return 

194 

195 if ( 

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

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

198 casalog.post( 

199 "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", 

200 "WARN", 

201 "task_tclean", 

202 ) 

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

204 

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

206 if specmode=="mvc": 

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

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

209 "WARN", 

210 "task_tclean") 

211 return 

212 

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

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

215 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.", 

216 "WARN", 

217 "task_tclean") 

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

219 casalog.post( 

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

221 "WARN", 

222 "task_tclean", 

223 ) 

224 

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

226 casalog.post( 

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

228 "WARN", 

229 "task_tclean", 

230 ) 

231 return 

232 

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

234 casalog.post( 

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

236 "WARN", 

237 "task_tclean", 

238 ) 

239 return 

240 

241 if facets > 1 and parallel == True: 

242 casalog.post( 

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

244 "WARN", 

245 "task_tclean", 

246 ) 

247 

248 if nmajor < -1: 

249 casalog.post( 

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

251 "WARN", 

252 "task_tclean", 

253 ) 

254 return 

255 

256 ## CAS-13814 

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

258 casalog.post( 

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

260 "WARN", 

261 "task_tclean", 

262 ) 

263 return 

264 

265 #CAS-13814 

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

267 casalog.post( 

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

269 "WARN", 

270 "task_tclean", 

271 ) 

272 return 

273 

274 # CAS-14146 

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

276 casalog.post( 

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

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

279 "WARN", 

280 "task_tclean", 

281 ) 

282 

283 # CAS-13581 

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

285 if gridder == 'awphpg': 

286 casalog.post( 

287 "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.", 

288 "WARN", 

289 "task_tclean", 

290 ) 

291 

292 ##################################################### 

293 #### Construct ImagerParameters object 

294 ##################################################### 

295 

296 imager = None 

297 paramList = None 

298 

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

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

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

302 

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

304 ###expecting it to be true 

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

306 bparm["mosweight"] = False 

307 

308 if specmode == "mfs": 

309 bparm["perchanweightdensity"] = False 

310 

311 # deprecation message 

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

313 casalog.post( 

314 usemask 

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

316 "WARN", 

317 ) 

318 

319 

320 #paramList.printParameters() 

321 

322 

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

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

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

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

327 

328 if ( 

329 len(pointingoffsetsigdev) > 0 

330 and pointingoffsetsigdev[0] != 0.0 

331 and usepointing == True 

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

333 ): 

334 casalog.post( 

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

336 "WARN", 

337 ) 

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

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

340 

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

342 # ========================================================= 

343 concattype = "" 

344 pcube = False 

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

346 if specmode != "mfs": 

347 pcube = False 

348 parallel = False 

349 else: 

350 pcube = True 

351 # ========================================================= 

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

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

354 cppparallel = False 

355 if ( 

356 mpi_available 

357 and MPIEnvironment.is_mpi_enabled 

358 and specmode != "mfs" 

359 and not pcube 

360 ): 

361 mint = MPIInterface.MPIInterface() 

362 cl = mint.getCluster() 

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

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

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

366 cppparallel = True 

367 ###ignore chanchunk 

368 bparm['chanchunks']=1 

369 ######awphpg case 

370 if(gridder=='awphpg'): 

371 localsi=synthesisimager() 

372 localsi.inithpg() 

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

374 if pcube and interactive: 

375 casalog.post( 

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

377 "WARN", 

378 "task_tclean", 

379 ) 

380 return False 

381 

382 

383 if interactive: 

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

385 if pcube: 

386 casalog.post( 

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

388 "WARN", 

389 "task_tclean", 

390 ) 

391 return False 

392 

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

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

395 # False instead of throwing an exception results in: 

396 # 

397 # RuntimeError: No active exception to reraise 

398 # 

399 # from tclean run from casashell. 

400 try: 

401 import casaviewer as __test_casaviewer 

402 except: 

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

404 casalog.post( 

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

406 "WARN", 

407 "task_tclean", 

408 ) 

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

410 

411 

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

413 paramList=ImagerParameters(**bparm) 

414 

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

416 imagerInst = PySynthesisImager 

417 if specmode == "mvc": 

418 imager = PyMtmfsViaCubeSynthesisImager(params=paramList) 

419 imagerInst = PyMtmfsViaCubeSynthesisImager 

420 elif parallel == False and pcube == False: 

421 imager = PySynthesisImager(params=paramList) 

422 imagerInst = PySynthesisImager 

423 elif parallel == True: 

424 imager = PyParallelContSynthesisImager(params=paramList) 

425 imagerInst = PySynthesisImager 

426 elif pcube == True: 

427 imager = PyParallelCubeSynthesisImager(params=paramList) 

428 imagerInst = PyParallelCubeSynthesisImager 

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

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

431 concattype = "copyvirtual" 

432 else: 

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

434 return 

435 

436 retrec = {} 

437 

438 try: 

439 # if (1): 

440 # pdb.set_trace() 

441 ## Init major cycle elements 

442 t0 = time.time() 

443 imager.initializeImagers() 

444 

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

446 # other choices the following three calls become NoOps. 

447 # imager.dryGridding(); 

448 # imager.fillCFCache(); 

449 # imager.reloadCFCache(); 

450 

451 imager.initializeNormalizers() 

452 imager.setWeighting() 

453 t1 = time.time() 

454 casalog.post( 

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

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

457 + " sec", 

458 "INFO3", 

459 "task_tclean", 

460 ) 

461 

462 ## Init minor cycle elements 

463 if niter > 0 or restoration == True: 

464 t0 = time.time() 

465 imager.initializeDeconvolvers() 

466 t1 = time.time() 

467 casalog.post( 

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

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

470 + " sec", 

471 "INFO3", 

472 "task_tclean", 

473 ) 

474 

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

476 imager.estimatememory() 

477 

478 if niter > 0: 

479 t0 = time.time() 

480 imager.initializeIterationControl() 

481 t1 = time.time() 

482 casalog.post( 

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

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

485 + " sec", 

486 "INFO3", 

487 "task_tclean", 

488 ) 

489 

490 ## Make PSF 

491 

492 if calcpsf==True: 

493 t0=time.time(); 

494 #####TESTOO 

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

496 imager.makePB() 

497 #####TESTOO  

498 imager.makePSF() 

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

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

501 imager.deleteTools() 

502 mytb = table() 

503 psfname = ( 

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

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

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

507 ) 

508 mytb.open(psfname) 

509 miscinf = mytb.getkeyword("miscinfo") 

510 iminf = mytb.getkeyword("imageinfo") 

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

512 mytb.done() 

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

514 imager.unlockimages(0) 

515 psfParameters = paramList.getAllPars() 

516 psfParameters["phasecenter"] = psfphasecenter 

517 psfParamList = ImagerParameters(**psfParameters) 

518 psfimager = imagerInst(params=psfParamList) 

519 psfimager.initializeImagers() 

520 psfimager.setWeighting() 

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

522 psfimager.deleteTools() 

523 mytb.open(psfname, nomodify=False) 

524 mytb.putkeyword("imageinfo", iminf) 

525 mytb.putkeyword("miscinfo", miscinf) 

526 mytb.done() 

527 mysu=synthesisutils() 

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

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

530 psfcutoff=bparm['psfcutoff']) 

531 imager = PySynthesisImager(params=paramList) 

532 imager.initializeImagers() 

533 imager.initializeNormalizers() 

534 imager.setWeighting() 

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

536 ## Init minor cycle elements 

537 if niter > 0 or restoration == True: 

538 imager.initializeDeconvolvers() 

539 if niter > 0: 

540 imager.initializeIterationControl() 

541 

542 t1 = time.time() 

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

544 casalog.post( 

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

546 "INFO3", 

547 "task_tclean", 

548 ) 

549 else: 

550 casalog.post( 

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

552 "INFO3", 

553 "task_tclean", 

554 ) 

555 

556 imager.makePB() 

557 

558 t2 = time.time() 

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

560 casalog.post( 

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

562 "INFO3", 

563 "task_tclean", 

564 ) 

565 

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

567 imager.checkPB() 

568 

569 if niter >= 0: 

570 

571 ## Make dirty image 

572 if calcres == True: 

573 t0 = time.time() 

574 imager.runMajorCycle(isCleanCycle=False) 

575 t1 = time.time() 

576 casalog.post( 

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

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

579 + " sec", 

580 "INFO3", 

581 "task_tclean", 

582 ) 

583 

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

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

586 if savemodel != "none": 

587 imager.predictModel() 

588 

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

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

591 # populated. 

592 if niter==0: 

593 id = ImagingDict() 

594 retrec = id.construct_residual_dict(paramList) 

595 

596 ## Do deconvolution and iterations 

597 if niter > 0: 

598 t0 = time.time() 

599 

600 

601 isit = imager.hasConverged() 

602 imager.updateMask() 

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

604 # isit = imager.hasConverged() 

605 isit = imager.hasConverged() 

606 t1 = time.time() 

607 casalog.post( 

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

609 "INFO3", 

610 "task_tclean", 

611 ) 

612 while not isit: 

613 t0 = time.time() 

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

615 doneMinor = imager.runMinorCycle() 

616 t1 = time.time() 

617 casalog.post( 

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

619 "INFO3", 

620 "task_tclean", 

621 ) 

622 

623 t0 = time.time() 

624 if doneMinor: 

625 imager.runMajorCycle() 

626 t1 = time.time() 

627 casalog.post( 

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

629 "INFO3", 

630 "task_tclean", 

631 ) 

632 

633 imager.updateMask() 

634 t2 = time.time() 

635 casalog.post( 

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

637 "INFO3", 

638 "task_tclean", 

639 ) 

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

641 

642 ## Get summary from iterbot 

643 #if type(interactive) != bool: 

644 retrec=imager.getSummary(fullsummary); 

645 

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

647 paramList.resetParameters() 

648 if parallel and specmode == "mfs": 

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

650 imager.resetSaveModelParams(paramList) 

651 imager.initializeImagers() 

652 imager.predictModel() 

653 

654 ## Restore images. 

655 if restoration == True: 

656 t0 = time.time() 

657 imager.restoreImages() 

658 t1 = time.time() 

659 casalog.post( 

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

661 "INFO3", 

662 "task_tclean", 

663 ) 

664 if pbcor == True: 

665 t0 = time.time() 

666 imager.pbcorImages() 

667 t1 = time.time() 

668 casalog.post( 

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

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

671 + " sec", 

672 "INFO3", 

673 "task_tclean", 

674 ) 

675 ######### niter >=0 end if 

676 

677 finally: 

678 ##close tools 

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

680 if imager != None: 

681 imager.deleteTools() 

682 if cppparallel: 

683 ###release workers back to python mpi control 

684 si = synthesisimager() 

685 si.releasempi() 

686 if pcube: 

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

688 casalog.post( 

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

690 "INFO2", 

691 "task_tclean", 

692 ) 

693 imager.concatImages(type=concattype) 

694 # CAS-10721 

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

696 # 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") 

697 

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

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

700 try: 

701 params = get_func_params(tclean, locals()) 

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

703 except Exception as exc: 

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

705 

706 return retrec 

707 

708 

709##################################################