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

337 statements  

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

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

2# single dish + interfermeter join image reconstruction task 

3# 

4# 

5################################################ 

6 

7import platform 

8import os 

9import shutil 

10import numpy 

11import copy 

12import time 

13 

14from casatasks import casalog 

15 

16from casatasks.private.imagerhelpers.imager_base import PySynthesisImager 

17from casatasks.private.imagerhelpers.imager_parallel_continuum import PyParallelContSynthesisImager 

18from casatasks.private.imagerhelpers.imager_parallel_cube import PyParallelCubeSynthesisImager 

19from casatasks.private.imagerhelpers.input_parameters import ImagerParameters 

20#from casatasks import imregrid 

21from .cleanhelper import write_tclean_history, get_func_params 

22from .sdint_helper import * 

23from casatools import table 

24from casatools import synthesisimager,synthesisutils 

25 

26try: 

27 from casampi.MPIEnvironment import MPIEnvironment 

28 from casampi import MPIInterface 

29 mpi_available = True 

30except ImportError: 

31 mpi_available = False 

32 

33sdintlib = SDINT_helper() 

34synu = synthesisutils() 

35 

36# setup functions 

37def setup_imagerObj(paramList=None): 

38 """ 

39 setup imaging parameters 

40 """ 

41 defaultconstructor = False 

42 if paramList!=None: 

43 if not isinstance(paramList, ImagerParameters): 

44 raise RuntimeError("Internal Error: invalid paramList") 

45 else: 

46 defaultconstructor = True 

47 

48 if defaultconstructor: 

49 return PySynthesisImager 

50 else: 

51 return PySynthesisImager(params=paramList) 

52 

53 

54def setup_imager(imagename, specmode,calcres,calpsf,inparams): 

55 """ 

56 Setup cube imaging for major cycles. 

57 - Do initialization 

58 - and run a major cycle 

59 """ 

60 # create a local copy of input params dict so that it can be  

61 # modified 

62 locparams = copy.deepcopy(inparams) 

63 

64 # cube imaging setup  

65 locparams['imagename']=imagename 

66 locparams['specmode']='cube' 

67 locparams['niter']=0 

68 locparams['deconvolver']='hogbom' 

69 

70 #casalog.post("local inparams(msname) in setup_imager==",locparams['msname']) 

71 params = ImagerParameters(**locparams) 

72 #params = ImagerParameters(msname=self.vis, field=self.field,spw=self.spw, 

73 # imagename=imagename, 

74 # imsize=self.imsize, cell=self.cell, phasecenter=self.phasecenter, 

75 # weighting=self.weighting, 

76 # gridder=self.gridder, pblimit=self.pblimit,wprojplanes=self.wprojplanes, 

77 # specmode='cube',nchan=self.nchan, 

78 # reffreq=self.reffreq, width=self.width, start=self.start, interpolation=self.interpolation, 

79 # interactive=self.interactive, 

80 # deconvolver='hogbom', niter=0, 

81 # wbawp=True) 

82 

83 ## Major cycle is either PySynthesisImager or PyParallelCubeSynthesisImager 

84 imagertool = setup_imagerObj(params) 

85 

86 #self.imagertool = PySynthesisImager(params=params) 

87 imagertool.initializeImagers() 

88 imagertool.initializeNormalizers() 

89 imagertool.setWeighting() 

90 if 'psfphasecenter' in locparams: 

91 psfphasecenter = locparams['psfphasecenter'] 

92 else: 

93 psfphasecenter = '' 

94 

95 ## Extra one for psfphasecenter... 

96 imagerInst=None 

97 if((psfphasecenter != '') and (gridder=='mosaic')): 

98 imagerInst = setup_imagerObj() 

99 

100 

101 gridder = locparams['gridder'] 

102 

103 if calpsf == True: 

104 imagertool.makePSF() 

105 imagertool.makePB() 

106 if((psfphasecenter != '') and (gridder=='mosaic')): 

107 casalog.post("doing with different phasecenter psf", "INFO") 

108 imagertool.unlockimages(0) 

109 psfParameters=paramList.getAllPars() 

110 psfParameters['phasecenter']=psfphasecenter 

111 psfParamList=ImagerParameters(**psfParameters) 

112 psfimager=imagerInst(params=psfParamList) 

113 psfimager.initializeImagers() 

114 psfimager.setWeighting() 

115 psfimager.makeImage('psf', psfParameters['imagename']+'.psf') 

116 

117 # can take out this since niter is fixed to 0 

118 if locparams['niter'] >=0 : 

119 ## Make dirty image 

120 if calcres == True: 

121 t0=time.time(); 

122 imagertool.runMajorCycle(isCleanCycle=False) 

123 t1=time.time(); 

124 casalog.post("***Time for major cycle (calcres=T): "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean"); 

125 

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

127 #if locparams['niter']==0 and calcres==False: 

128 # if savemodel != "none": 

129 # imagertool.predictModel() 

130 

131 sdintlib.copy_restoringbeam(fromthis=imagename+'.psf', tothis=imagename+'.residual') 

132 return imagertool 

133 

134def setup_deconvolver(imagename,specmode,inparams): 

135 """ 

136 Cube or MFS minor cycles.  

137 """ 

138 #params = ImagerParameters(msname=self.vis, field=self.field,spw=self.spw, 

139 # imagename=imagename, 

140 # imsize=self.imsize, cell=self.cell, phasecenter=self.phasecenter, 

141 # weighting=self.weighting, 

142 # gridder=self.gridder, pblimit=self.pblimit,wprojplanes=self.wprojplanes, 

143 # specmode=self.specmode,nchan=self.nchan, 

144 # reffreq=self.reffreq, width=self.width, start=self.start, interpolation=self.interpolation, 

145 # interactive=self.interactive, 

146 # deconvolver=self.deconvolver, scales=self.scales,nterms=self.nterms, 

147 # niter=self.niter,cycleniter=self.cycleniter, threshold=self.threshold, 

148 # mask=self.mask) 

149 inparams['imagename']=imagename 

150 params = ImagerParameters(**inparams) 

151 deconvolvertool = setup_imagerObj(params) 

152 

153 ## Why are we initializing these ?  

154 deconvolvertool.initializeImagers() 

155 deconvolvertool.initializeNormalizers() 

156 deconvolvertool.setWeighting() 

157 

158 

159 ### These three should be unncessary. Need a 'makeimage' method for csys generation.  

160 deconvolvertool.makePSF() ## Make this to get a coordinate system 

161 #deconvolvertool.makeImage('psf', imagename+'.psf') 

162 deconvolvertool.makePB() ## Make this to turn .weight into .pb maps 

163 

164 ## Initialize deconvolvers. ( Order is important. This cleans up a leftover tablecache image.... FIX!) 

165 deconvolvertool.initializeDeconvolvers() 

166 deconvolvertool.initializeIterationControl() # This needs to be run before runMajorCycle 

167 deconvolvertool.runMajorCycle(isCleanCycle=False) ## Make this to make template residual images. 

168 

169 return deconvolvertool 

170 

171def setup_sdimaging(template='',output='', inparms=None, sdparms=None): 

172 """ 

173 Make the SD cube Image and PSF 

174 

175 Option 1 : Use/Regrid cubes for the observed image and PSF 

176 Option 2 : Make the SD image and PSF cubes using 'tsdimager's usage of the SD gridder option. 

177 

178 Currently, only Option 1 is supported.  

179 

180 """ 

181 sdintlib = SDINT_helper() 

182 if 'sdpsf' in sdparms: 

183 sdpsf = sdparms['sdpsf'] 

184 else: 

185 raise RuntimeError("Internal Error: missing sdpsf parameter") 

186 

187 if 'sdimage' in sdparms: 

188 sdimage = sdparms['sdimage'] 

189 else: 

190 raise RuntimeError("Internal Error: missing sdimage parameter") 

191 if 'pblimit' in inparms: 

192 pblimit = inparms['pblimit'] 

193 

194 if sdpsf !="": 

195 ## check the coordinates of psf with int psf 

196 sdintlib.checkpsf(sdpsf, template+'.psf') 

197 

198 ## Regrid the input SD image and PSF cubes to the target coordinate system.  

199 #imregrid(imagename=sdimage, template=template+'.residual', 

200 # output=output+'.residual',overwrite=True,axes=[0,1]) 

201 sdintlib.regridimage(imagename=sdimage, template=template+'.residual', outfile=output+'.residual') 

202 #imregrid(imagename=sdimage, template=template+'.residual', 

203 # output=output+'.image',overwrite=True,axes=[0,1]) 

204 sdintlib.regridimage(imagename=sdimage, template=template+'.residual', outfile=output+'.image') 

205 

206 if sdpsf !="": 

207 #imregrid(imagename=sdpsf, template=template+'.psf', 

208 # output=output+'.psf',overwrite=True,axes=[0,1]) 

209 sdintlib.regridimage(imagename=sdpsf, template=template+'.psf', outfile=output+'.psf') 

210 else: 

211 ## Make an internal sdpsf image if the user has not supplied one.  

212 casalog.post("Constructing a SD PSF cube by evaluating Gaussians based on the restoring beam information in the regridded SD Image Cube") 

213 sdintlib.create_sd_psf(sdimage=output+'.residual', sdpsfname=output+'.psf') 

214 

215 ## Apply the pbmask from the INT image cube, to the SD cubes. 

216 #TTB: Create *.mask cube  

217 

218 sdintlib.addmask(inpimage=output+'.residual', pbimage=template+'.pb', pblimit=pblimit) 

219 sdintlib.addmask(inpimage=output+'.image', pbimage=template+'.pb', pblimit=pblimit) 

220 

221 

222 

223def feather_residual(int_cube, sd_cube, joint_cube, applypb, inparm): 

224 

225 if applypb==True: 

226 ## Take initial INT_dirty image to flat-sky.  

227 sdintlib.modify_with_pb(inpcube=int_cube+'.residual', 

228 pbcube=int_cube+'.pb', 

229 cubewt=int_cube+'.sumwt', 

230 chanwt=inparm['chanwt'], 

231 action='div', 

232 pblimit=inparm['pblimit'], 

233 freqdep=True) 

234 

235 ## Feather flat-sky INT dirty image with SD image 

236 sdintlib.feather_int_sd(sdcube=sd_cube+'.residual', 

237 intcube=int_cube+'.residual', 

238 jointcube=joint_cube+'.residual', ## output 

239 sdgain=inparm['sdgain'], 

240 dishdia=inparm['dishdia'], 

241 usedata=inparm['usedata'], 

242 chanwt = inparm['chanwt']) 

243 

244 if applypb==True: 

245 if inparm['specmode'].count('cube')>0: 

246 ## Multiply the new JOINT dirty image by the frequency-dependent PB.  

247 fdep_pb = True 

248 else: 

249 ## Multiply new JOINT dirty image by a common PB to get the effect of conjbeams.  

250 fdep_pb = False 

251 sdintlib.modify_with_pb(inpcube=joint_cube+'.residual', 

252 pbcube=int_cube+'.pb', 

253 cubewt=int_cube+'.sumwt', 

254 chanwt=inparm['chanwt'], 

255 action='mult', 

256 pblimit=inparm['pblimit'], 

257 freqdep=fdep_pb) 

258 

259def deleteTmpFiles(): 

260 if os.path.exists('tmp_intplane'): 

261 os.system('rm -rf tmp_intplane') 

262 if os.path.exists('tmp_sdplane'): 

263 os.system('rm -rf tmp_sdplane') 

264 if os.path.exists('tmp_jointplane'): 

265 os.system('rm -rf tmp_jointplane') 

266 

267 

268def sdintimaging( 

269 usedata, 

270 ####### Single dish input data 

271 sdimage, 

272 sdpsf, 

273 sdgain, 

274 dishdia, 

275 ####### Interferometer Data Selection 

276 vis,#='',  

277 selectdata, 

278 field,#='',  

279 spw,#='', 

280 timerange,#='', 

281 uvrange,#='', 

282 antenna,#='', 

283 scan,#='', 

284 observation,#='', 

285 intent,#='', 

286 datacolumn,#='corrected', 

287 

288 

289 ####### Image definition 

290 imagename,#='', 

291 imsize,#=[100,100], 

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

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

294 stokes,#='I', 

295 projection,#='SIN', 

296 startmodel,#='', 

297 

298 ## Spectral parameters 

299 specmode,#='mfs', 

300 reffreq,#='', 

301 nchan,#=1, 

302 start,#='', 

303 width,#='', 

304 outframe,#='LSRK', 

305 veltype,#='', 

306 restfreq,#=[''], 

307# sysvel,#='', 

308# sysvelframe,#='', 

309 interpolation,#='', 

310# chanchunks,#=1, 

311 perchanweightdensity, #='' 

312 ##  

313 ####### Gridding parameters 

314 gridder,#='ft', 

315 facets,#=1, 

316 psfphasecenter,#='', 

317 

318 wprojplanes,#=1, 

319 

320 ### PB 

321 vptable, 

322 mosweight, #=True 

323 aterm,#=True, 

324 psterm,#=True, 

325 wbawp ,#= True, 

326# conjbeams ,#= True, 

327 cfcache ,#= "", 

328 usepointing, #=false 

329 computepastep ,#=360.0, 

330 rotatepastep ,#=360.0, 

331 pointingoffsetsigdev ,#=0.0, 

332 

333 pblimit,#=0.01, 

334# normtype,#='flatnoise', 

335 

336 ####### Deconvolution parameters 

337 deconvolver,#='hogbom', 

338 scales,#=[], 

339 nterms,#=1, 

340 smallscalebias,#=0.0 

341 

342 ### restoration options 

343 restoration, 

344 restoringbeam,#=[], 

345 pbcor, 

346 

347 ##### Outliers 

348# outlierfile,#='', ### RESTRICTION : No support for outlier fields for joint SD-INT imaging.  

349 

350 ##### Weighting 

351 weighting,#='natural', 

352 robust,#=0.5, 

353 noise,#0.0Jy 

354 npixels,#=0, 

355# uvtaper,#=False, 

356 uvtaper,#=[], 

357 

358 

359 ##### Iteration control 

360 niter,#=0,  

361 gain,#=0.1, 

362 threshold,#=0.0,  

363 nsigma,#=0.0 

364 cycleniter,#=0,  

365 cyclefactor,#=1.0, 

366 minpsffraction,#=0.1, 

367 maxpsffraction,#=0.8, 

368 interactive,#=False,  

369 fullsummary,#=False, 

370 nmajor,#=-1, 

371 

372 ##### (new) Mask parameters 

373 usemask,#='user', 

374 mask,#='', 

375 pbmask,#='', 

376 # maskthreshold,#='', 

377 # maskresolution,#='', 

378 # nmask,#=0, 

379 

380 ##### automask by multithresh 

381 sidelobethreshold,#=5.0, 

382 noisethreshold,#=3.0, 

383 lownoisethreshold,#=3.0, 

384 negativethreshold,#=0.0, 

385 smoothfactor,#=1.0, 

386 minbeamfrac,#=0.3,  

387 cutthreshold,#=0.01, 

388 growiterations,#=100 

389 dogrowprune,#=True 

390 minpercentchange,#=0.0 

391 verbose, #=False 

392 fastnoise, #=False 

393 

394 ## Misc 

395 

396 restart,#=True, 

397 

398 #savemodel,#="none", 

399 

400# makeimages,#="auto" 

401 calcres,#=True, 

402 calcpsf):#=True, 

403 

404 ####### State parameters 

405 #parallel):#=False): 

406 

407 

408 ################################################## 

409 # copied from SDINT.do_reconstruct  

410 ################################################# 

411 int_cube = imagename+'.int.cube' 

412 sd_cube = imagename+'.sd.cube' 

413 joint_cube = imagename+'.joint.cube' 

414 joint_multiterm = imagename+'.joint.multiterm' 

415 

416 if specmode=='mfs': 

417 decname = joint_multiterm 

418 else: 

419 decname = joint_cube 

420 

421 ##################################################### 

422 #### Sanity checks and controls 

423 ##################################################### 

424 

425 if interactive: 

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

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

428 try: 

429 import casaviewer as __test_casaviewer 

430 except: 

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

432 casalog.post( 

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

434 "WARN", 

435 "task_sdintimaging", 

436 ) 

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

438 

439 ### Move these checks elsewhere ?  

440 inpparams=locals().copy() 

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

442 #casalog.post("current inpparams=",inpparams) 

443 #casalog.post("inpparams.keys()=",inpparams.keys()) 

444 locvis=inpparams.pop('vis') 

445 #casalog.post("LOCVIS====",locvis) 

446 if type(locvis)==list: 

447 llocvis = [v.lstrip() for v in locvis] 

448 else: 

449 llocvis = locvis.lstrip() 

450 inpparams['msname']=llocvis 

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

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

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

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

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

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

457 

458 sdparms={} 

459 sdparms['sdimage']=inpparams['sdimage'] 

460 sdparms['sdpsf']=inpparams['sdpsf'] 

461 sdparms['sdgain']=inpparams['sdgain'] 

462 

463 if usedata!='int': # check sd parameters 

464 

465 _myia = image() 

466 

467 if not os.path.exists(sdparms['sdimage']): 

468 casalog.post( "Input image sdimage = '"+str(sdparms['sdimage'])+"' does not exist.", "WARN", "task_sdintimaging" ) 

469 return 

470 else: 

471 try: 

472 _myia.open(sdparms['sdimage']) 

473 except Exception as instance: 

474 casalog.post( "Input image sdimage = '"+str(sdparms['sdimage'])+"' cannot be opened.", "WARN", "task_sdintimaging" ) 

475 casalog.post( str(instance), "WARN", "task_sdintimaging" ) 

476 return 

477 

478 mysummary = _myia.summary(list=False) 

479 _myia.close() 

480 

481 try: 

482 freqaxis_index = list(mysummary['axisnames']).index('Frequency') 

483 except(ValueError): 

484 casalog.post('The image '+sdparms['sdimage']+' has no frequency axis. Try adding one with ia.adddegaxis() .', 

485 'WARN', 'task_sdintimaging') 

486 return 

487 

488 if freqaxis_index != 3: 

489 casalog.post('The image '+sdparms['sdimage']+' has its frequency axis on position '+str(freqaxis_index)+ 

490 ' whereas it should be in position 3 (counting from 0). Use task imtrans() with order=["r", "d", "s", "f"] to fix this.', 

491 'WARN', 'task_sdintimaging') 

492 return 

493 

494 

495 if sdparms['sdpsf']!='': 

496 if not os.path.exists(sdparms['sdpsf']): 

497 casalog.post( "Input image sdpsf = '"+str(sdparms['sdpsf'])+"' does not exist.", "WARN", "task_sdintimaging" ) 

498 return 

499 else: 

500 try: 

501 _myia.open(sdparms['sdpsf']) 

502 _myia.close() 

503 except Exception as instance: 

504 casalog.post( "Input image sdpsf = '"+str(sdparms['sdpsf'])+"' cannot be opened.", "WARN", "task_sdintimaging" ) 

505 casalog.post( str(instance), "WARN", "task_sdintimaging" ) 

506 return 

507 

508 if (sdparms['sdgain']*0!=0 or sdparms['sdgain']<=0): 

509 casalog.post('Invalid sdgain: '+str(sdparms['sdgain']), 'WARN') 

510 casalog.post("The sdgain parameter needs to be chosen as a number > 0 which represents the weight of the SD contribution relative to the INT contribution to the joint image.", "WARN", "task_sdintimaging") 

511 return 

512 

513 if (dishdia*0!=0 or dishdia<=0): 

514 casalog.post('Invalid dishdia: '+str(dishdia), 'WARN') 

515 casalog.post("The dishdia parameter needs to provide the diameter (meters) of the SD telescope which produced the SD image.", "WARN", "task_sdintimaging") 

516 return 

517 

518 

519 if specmode=='cont': 

520 specmode='mfs' 

521 inpparams['specmode']='mfs' 

522 

523 # from sdint 

524 # automatically decide if pb need to be applied 

525 if gridder=='mosaic' or gridder=='awproject': 

526 applypb = True 

527 else: 

528 applypb = False 

529 

530 if (deconvolver=="mtmfs") and (specmode!='mfs') and (specmode!='cube' or nterms!=1) and (specmode!='cubedata' or nterms!=1): 

531 casalog.post( "The MSMFS algorithm (deconvolver='mtmfs') applies only to specmode='mfs' or specmode='cube' with nterms=1 or specmode='cubedata' with nterms=1.", "WARN", "task_sdintimaging" ) 

532 return 

533 

534 if(deconvolver=="mtmfs" and (specmode=='cube' or specmode=='cubedata') and nterms==1 ): 

535 casalog.post( "The MSMFS algorithm (deconvolver='mtmfs') with specmode='cube', nterms=1 is currently not supported. Please use deconvolver='multiscale' instead for cubes.", "WARN", "task_sdintimaging" ) 

536 return 

537 

538 if(specmode=='mfs' and deconvolver!='mtmfs'): 

539 casalog.post("Currently, only the multi-term MFS algorithm is supported for specmode=mfs. To make a single plane MFS image (while retaining the frequency dependence for the cube major cycle stage), please pick nterms=1 along with deconvolver=mtmfs. The scales parameter is still usable for multi-scale multi-term deconvolution","WARN","task_sdintimaging") 

540 return; 

541 

542 if(usedata=='sd'): 

543 casalog.post("The Single-Dish-Only mode of sdintimaging is better supported via the deconvolve task which supports spectral cube, mfs and multi-term mfs deconvolution in the image domain alone. The deconvolve task is the more appropriate version to use for stand-alone image-domain deconvolution, and will not have the bookkeeping overheads currently present in the sdintimaging task's sd-only mode. Please note that the 'sd' option of the sdintimaging task will be removed in a subsequent release. Please refer to the task deconvolve documentation for instructions on how to prepare image and psf cubes for the deconvolve task for all these modes.","WARN","task_sdintimaging"); 

544 

545 if (nmajor < -1): 

546 casalog.post("Negative values less than -1 for nmajor are reserved for possible future implementation", "WARN", "task_sdintimaging") 

547 return 

548 

549# if parallel==True: 

550# casalog.post("Cube parallelization (all major cycles) is currently not supported via task_sdintimaging. This will be enabled after a cube parallelization rework.") 

551# return; 

552 

553 ##################################################### 

554 #### Construct ImagerParameters object 

555 ##################################################### 

556 

557 imager = None 

558 paramList = None 

559 deconvolvertool = None 

560 

561 # Put all parameters into dictionaries and check them. 

562 ##make a dictionary of parameters that ImagerParameters take 

563 defparm=dict(list(zip(ImagerParameters.__init__.__code__.co_varnames[1:], ImagerParameters.__init__.__defaults__))) 

564 

565 

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

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

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

569 

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

571 ###expecting it to be true 

572 if(bparm['mosweight']==True and bparm['gridder'].find("mosaic") == -1): 

573 bparm['mosweight']=False 

574 

575 ## Two options have been removed from the interface. Hard-code them here. 

576 bparm['normtype'] = 'flatnoise' ## Hard-code this since the pbcor steps assume it. 

577 bparm['conjbeams']=False 

578 

579 #paramList=ImagerParameters(**bparm) 

580 

581 #paramList.printParameters() 

582 

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

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

585 

586 #========================================================= 

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

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

589 cppparallel=False 

590 if mpi_available and MPIEnvironment.is_mpi_enabled: 

591 mint=MPIInterface.MPIInterface() 

592 cl=mint.getCluster() 

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

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

595 

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

597 cppparallel=True 

598 ###ignore chanchunk 

599 bparm['chanchunks']=1 

600 

601 ################################################# 

602 #### start of more computing-intensive work ##### 

603 ################################################# 

604 

605 retrec={} 

606 

607 try: 

608 sdintlib = SDINT_helper() 

609 ## Init major cycle elements 

610 ### debug (remove it later)  

611 casalog.post("INT cube setup ....") 

612 t0=time.time(); 

613 imager=setup_imager(int_cube, specmode, calcres, calcpsf, bparm) 

614 

615 

616 ##imager.initializeImagers() 

617 

618 ##imager.initializeNormalizers() 

619 ##imager.setWeighting() 

620 t1=time.time(); 

621 casalog.post("***Time for initializing imager (INT cube) : "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_sdintimaging"); 

622 

623 ## Init minor cycle elements 

624 if niter>0 or restoration==True: 

625 ### debug (remove it later)  

626 casalog.post("Combined image setup ....") 

627 t0=time.time(); 

628 deconvolvertool=setup_deconvolver(decname, specmode, bparm ) 

629 #imager.initializeDeconvolvers() 

630 t1=time.time(); 

631 casalog.post("***Time for seting up deconvolver(s): "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_sdintimaging"); 

632 

633 if usedata!='int': 

634 ### debug (remove it later)  

635 casalog.post("SD cube setup ....") 

636 setup_sdimaging(template=int_cube, output=sd_cube, inparms=bparm, sdparms=sdparms ) 

637 

638 

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

640 # need to move to somewhere below??? 

641 imager.estimatememory() 

642 

643 ## Do sanity checks on INT and SD cubes 

644 ### Frequency range of cube, data selection range. mtmfs reffreq. 

645 ### nchan too small or too large 

646 ### sumwt : flagged channels in int cubes 

647 ### sd cube empty channels ? Weight image ?  

648 validity, inpparams = sdintlib.check_coords(intres=int_cube+'.residual', intpsf=int_cube+'.psf', 

649 intwt = int_cube+'.sumwt', 

650 sdres=sd_cube+'.residual', sdpsf=sd_cube+'.psf', 

651 sdwt = '', 

652 pars=inpparams) 

653 

654 if validity==False: 

655 casalog.post('Exiting from the sdintimaging task due to inconsistencies found between the interferometer-only and singledish-only image and psf cubes. Please modify inputs as needed','WARN') 

656 if imager != None: 

657 imager.deleteTools() 

658 if deconvolvertool != None: 

659 deconvolvertool.deleteTools() 

660 deleteTmpFiles() 

661 return 

662 

663 #### inpparams now has a new parameter "chanwt" with ones and zeros to indicate chans 

664 #### that have data from both INT and SD cubes (they are the 'ones'). This is to be used in  

665 #### feathering and in the cube-to-taylor sum and modify_with_pb.  

666 

667 #### END MOVE THIS SECTION to setup_imager ....for sdint 

668 

669 #### SDINT specific feathering.... 

670 ## Feather INT and SD residual images (feather in flat-sky. output has common PB) 

671 casalog.post("Feathering INT and SD residual images...") 

672 feather_residual(int_cube, sd_cube, joint_cube, applypb, inpparams) 

673 sdintlib.feather_int_sd(sdcube=sd_cube+'.psf', 

674 intcube=int_cube+'.psf', 

675 jointcube=joint_cube+'.psf', 

676 sdgain=sdgain, 

677 dishdia=dishdia, 

678 usedata=usedata, 

679 chanwt = inpparams['chanwt']) 

680 

681 #print("Fitting for cube") 

682 synu.fitPsfBeam(joint_cube) 

683 

684 ############### 

685 ##### Placeholder code for PSF renormalization if needed 

686 ##### Note : If this is enabled, we'll need to restrict the use of 'faceting' as .sumwt shape changes. 

687 #sdintlib.calc_renorm(intname=int_cube, jointname=joint_cube) 

688 #sdintlib.apply_renorm(imname=joint_cube+'.psf', sumwtname=joint_cube+'.sumwt') 

689 #sdintlib.apply_renorm(imname=joint_cube+'.residual', sumwtname=joint_cube+'.sumwt') 

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

691 

692 #casalog.post("feather_int_sd DONE") 

693 

694 if specmode=='mfs': 

695 ## Calculate Spectral PSFs and Taylor Residuals 

696 casalog.post("Calculate spectral PSFs and Taylor Residuals...") 

697 sdintlib.cube_to_taylor_sum(cubename=joint_cube+'.psf', 

698 cubewt=int_cube+'.sumwt', 

699 chanwt=inpparams['chanwt'], 

700 mtname=joint_multiterm+'.psf', 

701 nterms=nterms, reffreq=inpparams['reffreq'], dopsf=True) 

702 sdintlib.cube_to_taylor_sum(cubename=joint_cube+'.residual', 

703 cubewt=int_cube+'.sumwt', 

704 chanwt=inpparams['chanwt'], 

705 mtname=joint_multiterm+'.residual', 

706 nterms=nterms, reffreq=inpparams['reffreq'], dopsf=False) 

707 

708 #print("Fit for multiterm") 

709 if(deconvolver=='mtmfs' and nterms==1): # work around file naming issue 

710 os.system('rm -rf '+joint_multiterm+'tmp.psf') 

711 os.system('ln -sf '+joint_multiterm+'.psf.tt0 '+joint_multiterm+'tmp.psf') 

712 synu.fitPsfBeam(joint_multiterm+'tmp',nterms=nterms) 

713 os.system('rm -rf '+joint_multiterm+'tmp.psf') 

714 else: 

715 synu.fitPsfBeam(joint_multiterm,nterms=nterms) 

716 

717 if niter>0 : 

718 isit = deconvolvertool.hasConverged() 

719 deconvolvertool.updateMask() 

720 

721 while ( not deconvolvertool.hasConverged() ): 

722 

723 t0=time.time(); 

724 

725 #### Print out the peak of the residual image here to check !!!  

726# if specmode=='mfs': 

727# print('Max of joint residual before initminorcycle' + str(imstat(joint_multiterm+'.residual.tt0',verbose=False)['max'][0])) 

728# else: 

729# print('Max of joint residual before initminorcycle' + str(imstat(joint_cube+'.residual',verbose=False)['max'][0])) 

730 

731 

732 

733 deconvolvertool.runMinorCycle() 

734 

735# if specmode=='mfs': 

736# print('Max of joint residual after minorcycle' + str(imstat(joint_multiterm+'.residual.tt0',verbose=False)['max'][0])) 

737# else: 

738# print('Max of joint residual after minorcycle' + str(imstat(joint_cube+'.residual',verbose=False)['max'][0])) 

739 

740 

741 t1=time.time(); 

742 casalog.post("***Time for minor cycle: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_sdintimaging"); 

743 

744 ### sdint specific feathering steps HERE 

745 ## Prepare the joint model cube for INT and SD major cycles 

746 if specmode=='mfs': 

747 ## Convert Taylor model coefficients into a model cube : int_cube.model 

748 sdintlib.taylor_model_to_cube(cubename=int_cube, ## output  

749 mtname=joint_multiterm, ## input 

750 nterms=nterms, reffreq=inpparams['reffreq']) 

751 else: 

752 ## Copy the joint_model cube to the int_cube.model 

753 shutil.rmtree(int_cube+'.model',ignore_errors=True) 

754 shutil.copytree(joint_cube+'.model', int_cube+'.model') 

755 hasfile=os.path.exists(joint_cube+'.model') 

756 #casalog.post("DEBUG: has joint cube .image===",hasfile) 

757 

758 if applypb==True: 

759 ## Take the int_cube.model to flat sky.  

760 if specmode=='cube': 

761 ## Divide the model by the frequency-dependent PB to get to flat-sky 

762 fdep_pb = True 

763 else: 

764 ## Divide the model by the common PB to get to get to flat-sky 

765 fdep_pb = False 

766 sdintlib.modify_with_pb(inpcube=int_cube+'.model', 

767 pbcube=int_cube+'.pb', 

768 cubewt=int_cube+'.sumwt', 

769 chanwt=inpparams['chanwt'], 

770 action='div', pblimit=pblimit,freqdep=fdep_pb) 

771 

772 if usedata!="int": 

773 ## copy the int_cube.model to the sd_cube.model 

774 shutil.rmtree(sd_cube+'.model',ignore_errors=True) 

775 shutil.copytree(int_cube+'.model', sd_cube+'.model') 

776 

777 if applypb==True: 

778 ## Multiply flat-sky model with freq-dep PB 

779 sdintlib.modify_with_pb(inpcube=int_cube+'.model', 

780 pbcube=int_cube+'.pb', 

781 cubewt=int_cube+'.sumwt', 

782 chanwt=inpparams['chanwt'], 

783 action='mult', pblimit=pblimit, freqdep=True) 

784 

785 ## Major cycle for interferometer data 

786 t0=time.time(); 

787 # print('Max of int residual before major cycle' + str(imstat(int_cube+'.residual',verbose=False)['max'][0])) 

788 # print('Max of int model before major cycle' + str(imstat(int_cube+'.model',verbose=False)['max'][0])) 

789 

790 if usedata != "sd": 

791 imager.runMajorCycle() 

792 # track nmajor for the deconvolvertool.hasConverged() method 

793 deconvolvertool.majorCnt = imager.majorCnt 

794 

795 # print('Max of int residual after major cycle' + str(imstat(int_cube+'.residual',verbose=False)['max'][0])) 

796 t1=time.time(); 

797 casalog.post("***Time for major cycle: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean"); 

798 

799 if usedata!="int": 

800 ## Major cycle for Single Dish data (uses the flat sky cube model in sd_cube.model ) 

801 sdintlib.calc_sd_residual(origcube=sd_cube+'.image', 

802 modelcube=sd_cube+'.model', 

803 residualcube=sd_cube+'.residual', ## output 

804 psfcube=sd_cube+'.psf') 

805 

806 ## Feather the residuals 

807 feather_residual(int_cube, sd_cube, joint_cube, applypb, inpparams ) 

808 ############### 

809 ##### Placeholder code for PSF renormalization if needed 

810 #sdintlib.apply_renorm(imname=joint_cube+'.residual', sumwtname=joint_cube+'.sumwt') 

811 ############### 

812 

813 if specmode=='mfs': 

814 ## Calculate Spectral Taylor Residuals 

815 sdintlib.cube_to_taylor_sum(cubename=joint_cube+'.residual', 

816 cubewt=int_cube+'.sumwt', 

817 chanwt=inpparams['chanwt'], 

818 mtname=joint_multiterm+'.residual', 

819 nterms=nterms, reffreq=inpparams['reffreq'], dopsf=False) 

820 

821# if specmode=='mfs': 

822# print('Max of residual after feather step ' + str(imstat(joint_multiterm+'.residual.tt0',verbose=False)['max'][0])) 

823# else: 

824# print('Max of residual after feather step ' + str(imstat(joint_cube+'.residual',verbose=False)['max'][0])) 

825 

826 

827 deconvolvertool.updateMask() 

828 

829 ## Get summary from iterbot 

830 #if type(interactive) != bool: 

831 #retrec=imager.getSummary(); 

832 retrec=deconvolvertool.getSummary(fullsummary); 

833 retrec['nmajordone'] = imager.majorCnt 

834 if calcres==True: 

835 retrec['nmajordone'] = retrec['nmajordone'] + 1 ## To be consistent with tclean. Remove, when we can change the meaning of nmajordone to exclude the initial major cycles.  

836 

837 ## Restore images. 

838 if restoration==True: 

839 t0=time.time(); 

840 deconvolvertool.restoreImages() 

841 t1=time.time(); 

842 casalog.post("***Time for restoring images: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean"); 

843 if pbcor==True: 

844 #if applypb==True: 

845 t0=time.time(); 

846 if specmode=='mfs': 

847 sdintlib.pbcor(imagename=decname+'.image.tt0' , pbimage=decname+'.pb.tt0' , cutoff=pblimit,outfile=decname+'.image.tt0.pbcor') 

848 else: 

849 sdintlib.pbcor(imagename=joint_cube+'.image' , pbimage=int_cube+'.pb' , cutoff=pblimit,outfile=joint_cube+'.image.pbcor') 

850 

851 #imager.pbcorImages() 

852 t1=time.time(); 

853 casalog.post("***Time for pb-correcting images: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean"); 

854 

855 ##close tools 

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

857 imager.deleteTools() 

858 deconvolvertool.deleteTools() 

859 

860 

861 finally: 

862 if imager != None: 

863 imager.deleteTools() 

864 if(cppparallel): 

865 ###release workers back to python mpi control 

866 si=synthesisimager() 

867 si.releasempi() 

868 

869 #clean up tmp files 

870 deleteTmpFiles() 

871 

872 # Write history at the end, when hopefully all temp files are gone from disk, 

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

874 # Copied from tclean. 

875 try: 

876 params = get_func_params(sdintimaging, locals()) 

877 write_tclean_history(imagename, 'sdintimaging', params, casalog) 

878 except Exception as exc: 

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

880 

881 return retrec 

882 

883##################################################