Coverage for /home/casatest/venv/lib/python3.12/site-packages/casatasks/private/task_sdintimaging.py: 7%
324 statements
« prev ^ index » next coverage.py v7.10.4, created at 2025-08-21 07:43 +0000
« prev ^ index » next coverage.py v7.10.4, created at 2025-08-21 07:43 +0000
1################################################
2# single dish + interfermeter join image reconstruction task
3#
4#
5################################################
7import platform
8import os
9import shutil
10import numpy
11import copy
12import time
14from casatasks import casalog
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
20from .cleanhelper import write_tclean_history, get_func_params
21from .sdint_helper import *
22from casatools import table
23from casatools import synthesisimager,synthesisutils
25try:
26 from casampi.MPIEnvironment import MPIEnvironment
27 from casampi import MPIInterface
28 mpi_available = True
29except ImportError:
30 mpi_available = False
33# setup functions
34def setup_imagerObj(paramList=None):
35 """
36 setup imaging parameters
37 """
38 defaultconstructor = False
39 if paramList!=None:
40 if not isinstance(paramList, ImagerParameters):
41 raise RuntimeError("Internal Error: invalid paramList")
42 else:
43 defaultconstructor = True
45 if defaultconstructor:
46 return PySynthesisImager
47 else:
48 return PySynthesisImager(params=paramList)
51def setup_imager(imagename, specmode,calcres,calpsf,inparams):
52 """
53 Setup cube imaging for major cycles.
54 - Do initialization
55 - and run a major cycle
56 """
57 # create a local copy of input params dict so that it can be modified
58 locparams = copy.deepcopy(inparams)
60 # cube imaging setup
61 locparams['imagename']=imagename
62 locparams['specmode']='cube'
63 locparams['niter']=0
64 locparams['deconvolver']='hogbom'
66 #casalog.post("local inparams(msname) in setup_imager==",locparams['msname'])
67 params = ImagerParameters(**locparams)
69 ## Major cycle is either PySynthesisImager or PyParallelCubeSynthesisImager
70 imagertool = setup_imagerObj(params)
72 #self.imagertool = PySynthesisImager(params=params)
73 imagertool.initializeImagers()
74 imagertool.initializeNormalizers()
75 imagertool.setWeighting()
76 if 'psfphasecenter' in locparams:
77 psfphasecenter = locparams['psfphasecenter']
78 else:
79 psfphasecenter = ''
81 ## Extra one for psfphasecenter...
82 imagerInst=None
83 if((psfphasecenter != '') and (gridder=='mosaic')):
84 imagerInst = setup_imagerObj()
87 gridder = locparams['gridder']
89 if calpsf == True:
90 imagertool.makePSF()
91 imagertool.makePB()
92 if((psfphasecenter != '') and (gridder=='mosaic')):
93 casalog.post("doing with different phasecenter psf", "INFO")
94 imagertool.unlockimages(0)
95 psfParameters=paramList.getAllPars()
96 psfParameters['phasecenter']=psfphasecenter
97 psfParamList=ImagerParameters(**psfParameters)
98 psfimager=imagerInst(params=psfParamList)
99 psfimager.initializeImagers()
100 psfimager.setWeighting()
101 psfimager.makeImage('psf', psfParameters['imagename']+'.psf')
103 # can take out this since niter is fixed to 0
104 if locparams['niter'] >=0 :
105 ## Make dirty image
106 if calcres == True:
107 t0=time.time();
108 imagertool.runMajorCycle(isCleanCycle=False)
109 t1=time.time();
110 casalog.post("***Time for major cycle (calcres=T): "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean");
112 ## In case of no deconvolution iterations....
113 #if locparams['niter']==0 and calcres==False:
114 # if savemodel != "none":
115 # imagertool.predictModel()
117 return imagertool
119def setup_deconvolver(imagename,specmode,inparams):
120 """
121 Cube or MFS minor cycles.
122 """
123 inparams['imagename']=imagename
124 params = ImagerParameters(**inparams)
125 deconvolvertool = setup_imagerObj(params)
127 ## Why are we initializing these ?
128 deconvolvertool.initializeImagers()
129 deconvolvertool.initializeNormalizers()
130 deconvolvertool.setWeighting()
133 ### These three should be unncessary. Need a 'makeimage' method for csys generation.
134 deconvolvertool.makePSF() ## Make this to get a coordinate system
135 #deconvolvertool.makeImage('psf', imagename+'.psf')
136 deconvolvertool.makePB() ## Make this to turn .weight into .pb maps
138 ## Initialize deconvolvers. ( Order is important. This cleans up a leftover tablecache image.... FIX!)
139 deconvolvertool.initializeDeconvolvers()
140 deconvolvertool.initializeIterationControl() # This needs to be run before runMajorCycle
141 deconvolvertool.runMajorCycle(isCleanCycle=False) ## Make this to make template residual images.
143 return deconvolvertool
145def setup_sdimaging(template='',output='', inparms=None, sdparms=None):
146 """
147 Make the SD cube Image and PSF
149 Option 1 : Use/Regrid cubes for the observed image and PSF
150 Option 2 : Make the SD image and PSF cubes using 'tsdimager's usage of the SD gridder option.
152 Currently, only Option 1 is supported.
154 """
155 sdintlib = SDINT_helper()
156 if 'sdpsf' in sdparms:
157 sdpsf = sdparms['sdpsf']
158 else:
159 raise RuntimeError("Internal Error: missing sdpsf parameter")
161 if 'sdimage' in sdparms:
162 sdimage = sdparms['sdimage']
163 else:
164 raise RuntimeError("Internal Error: missing sdimage parameter")
165 if 'pblimit' in inparms:
166 pblimit = inparms['pblimit']
168 if sdpsf !="":
169 ## check the coordinates of psf with int psf
170 sdintlib.checkpsf(sdpsf, template+'.psf')
172 ## Regrid the input SD image and PSF cubes to the target coordinate system.
173 sdintlib.regridimage(imagename=sdimage, template=template+'.residual', outfile=output+'.residual')
174 sdintlib.regridimage(imagename=sdimage, template=template+'.residual', outfile=output+'.image')
176 if sdpsf !="":
177 sdintlib.regridimage(imagename=sdpsf, template=template+'.psf', outfile=output+'.psf')
178 else:
179 ## Make an internal sdpsf image if the user has not supplied one.
180 casalog.post("Constructing a SD PSF cube by evaluating Gaussians based on the restoring beam information in the regridded SD Image Cube")
181 sdintlib.create_sd_psf(sdimage=output+'.residual', sdpsfname=output+'.psf')
183 ## Apply the pbmask from the INT image cube, to the SD cubes.
184 #TTB: Create *.mask cube
186 sdintlib.addmask(inpimage=output+'.residual', pbimage=template+'.pb', pblimit=pblimit)
187 sdintlib.addmask(inpimage=output+'.image', pbimage=template+'.pb', pblimit=pblimit)
189 sdintlib.deleteTmpFiles()
193def sdintimaging(
194 usedata,
195 ####### Single dish input data
196 sdimage,
197 sdpsf,
198 sdgain,
199 dishdia,
200 ####### Interferometer Data Selection
201 vis,#='',
202 selectdata,
203 field,#='',
204 spw,#='',
205 timerange,#='',
206 uvrange,#='',
207 antenna,#='',
208 scan,#='',
209 observation,#='',
210 intent,#='',
211 datacolumn,#='corrected',
214 ####### Image definition
215 imagename,#='',
216 imsize,#=[100,100],
217 cell,#=['1.0arcsec','1.0arcsec'],
218 phasecenter,#='J2000 19:59:28.500 +40.44.01.50',
219 stokes,#='I',
220 projection,#='SIN',
221 startmodel,#='',
223 ## Spectral parameters
224 specmode,#='mfs',
225 reffreq,#='',
226 nchan,#=1,
227 start,#='',
228 width,#='',
229 outframe,#='LSRK',
230 veltype,#='',
231 restfreq,#=[''],
232# sysvel,#='',
233# sysvelframe,#='',
234 interpolation,#='',
235# chanchunks,#=1,
236 perchanweightdensity, #=''
237 ##
238 ####### Gridding parameters
239 gridder,#='ft',
240 facets,#=1,
241 psfphasecenter,#='',
243 wprojplanes,#=1,
245 ### PB
246 vptable,
247 mosweight, #=True
248 aterm,#=True,
249 psterm,#=True,
250 wbawp ,#= True,
251# conjbeams ,#= True,
252 cfcache ,#= "",
253 usepointing, #=false
254 computepastep ,#=360.0,
255 rotatepastep ,#=360.0,
256 pointingoffsetsigdev ,#=0.0,
258 pblimit,#=0.01,
259# normtype,#='flatnoise',
261 ####### Deconvolution parameters
262 deconvolver,#='hogbom',
263 scales,#=[],
264 nterms,#=1,
265 smallscalebias,#=0.0
267 ### restoration options
268 restoration,
269 restoringbeam,#=[],
270 pbcor,
272 ##### Outliers
273# outlierfile,#='', ### RESTRICTION : No support for outlier fields for joint SD-INT imaging.
275 ##### Weighting
276 weighting,#='natural',
277 robust,#=0.5,
278 noise,#0.0Jy
279 npixels,#=0,
280# uvtaper,#=False,
281 uvtaper,#=[],
284 ##### Iteration control
285 niter,#=0,
286 gain,#=0.1,
287 threshold,#=0.0,
288 nsigma,#=0.0
289 cycleniter,#=0,
290 cyclefactor,#=1.0,
291 minpsffraction,#=0.1,
292 maxpsffraction,#=0.8,
293 interactive,#=False,
294 fullsummary,#=False,
295 nmajor,#=-1,
297 ##### (new) Mask parameters
298 usemask,#='user',
299 mask,#='',
300 pbmask,#='',
301 # maskthreshold,#='',
302 # maskresolution,#='',
303 # nmask,#=0,
305 ##### automask by multithresh
306 sidelobethreshold,#=5.0,
307 noisethreshold,#=3.0,
308 lownoisethreshold,#=3.0,
309 negativethreshold,#=0.0,
310 smoothfactor,#=1.0,
311 minbeamfrac,#=0.3,
312 cutthreshold,#=0.01,
313 growiterations,#=100
314 dogrowprune,#=True
315 minpercentchange,#=0.0
316 verbose, #=False
317 fastnoise, #=False
319 ## Misc
321 restart,#=True,
323 #savemodel,#="none",
325# makeimages,#="auto"
326 calcres,#=True,
327 calcpsf):#=True,
329 ####### State parameters
330 #parallel):#=False):
333 ##################################################
334 # copied from SDINT.do_reconstruct
335 #################################################
336 int_cube = imagename+'.int.cube'
337 sd_cube = imagename+'.sd.cube'
338 joint_cube = imagename+'.joint.cube'
339 joint_multiterm = imagename+'.joint.multiterm'
341 if specmode=='mfs':
342 decname = joint_multiterm
343 else:
344 decname = joint_cube
346 #####################################################
347 #### Sanity checks and controls
348 #####################################################
350 if interactive:
351 # Check for casaviewer, if it does not exist flag it up front for macOS
352 # since casaviewer is no longer provided by default with macOS.
353 try:
354 import casaviewer as __test_casaviewer
355 except:
356 if platform.system( ) == "Darwin":
357 casalog.post(
358 "casaviewer is no longer available for macOS, for more information see: http://go.nrao.edu/casa-viewer-eol Please restart by setting interactive=F",
359 "WARN",
360 "task_sdintimaging",
361 )
362 raise RuntimeError( "casaviewer is no longer available for macOS, for more information see: http://go.nrao.edu/casa-viewer-eol" )
364 ### Move these checks elsewhere ?
365 inpparams=locals().copy()
366 ###now deal with parameters which are not the same name
367 #casalog.post("current inpparams=",inpparams)
368 #casalog.post("inpparams.keys()=",inpparams.keys())
369 locvis=inpparams.pop('vis')
370 #casalog.post("LOCVIS====",locvis)
371 if type(locvis)==list:
372 llocvis = [v.lstrip() for v in locvis]
373 else:
374 llocvis = locvis.lstrip()
375 inpparams['msname']=llocvis
376 inpparams['timestr']= inpparams.pop('timerange')
377 inpparams['uvdist']= inpparams.pop('uvrange')
378 inpparams['obs']= inpparams.pop('observation')
379 inpparams['state']= inpparams.pop('intent')
380 inpparams['loopgain']=inpparams.pop('gain')
381 inpparams['scalebias']=inpparams.pop('smallscalebias')
383 sdparms={}
384 sdparms['sdimage']=inpparams['sdimage']
385 sdparms['sdpsf']=inpparams['sdpsf']
386 sdparms['sdgain']=inpparams['sdgain']
388 if usedata!='int': # check sd parameters
390 _myia = image()
392 if not os.path.exists(sdparms['sdimage']):
393 casalog.post( "Input image sdimage = '"+str(sdparms['sdimage'])+"' does not exist.", "WARN", "task_sdintimaging" )
394 return
395 else:
396 try:
397 _myia.open(sdparms['sdimage'])
398 except Exception as instance:
399 casalog.post( "Input image sdimage = '"+str(sdparms['sdimage'])+"' cannot be opened.", "WARN", "task_sdintimaging" )
400 casalog.post( str(instance), "WARN", "task_sdintimaging" )
401 return
403 mysummary = _myia.summary(list=False)
404 _myia.close()
406 try:
407 freqaxis_index = list(mysummary['axisnames']).index('Frequency')
408 except(ValueError):
409 casalog.post('The image '+sdparms['sdimage']+' has no frequency axis. Try adding one with ia.adddegaxis() .',
410 'WARN', 'task_sdintimaging')
411 return
413 if freqaxis_index != 3:
414 casalog.post('The image '+sdparms['sdimage']+' has its frequency axis on position '+str(freqaxis_index)+
415 ' whereas it should be in position 3 (counting from 0). Use task imtrans() with order=["r", "d", "s", "f"] to fix this.',
416 'WARN', 'task_sdintimaging')
417 return
419 if stokes!='I' and usedata=='sdint':
420 casalog.post('You have specified parameter stokes=\"'+str(stokes)+'\" but presently only stokes=\"I\" is supported when usedata=\"sdint\".',
421 'WARN', 'task_sdintimaging')
422 return
425 if sdparms['sdpsf']!='':
426 if not os.path.exists(sdparms['sdpsf']):
427 casalog.post( "Input image sdpsf = '"+str(sdparms['sdpsf'])+"' does not exist.", "WARN", "task_sdintimaging" )
428 return
429 else:
430 try:
431 _myia.open(sdparms['sdpsf'])
432 _myia.close()
433 except Exception as instance:
434 casalog.post( "Input image sdpsf = '"+str(sdparms['sdpsf'])+"' cannot be opened.", "WARN", "task_sdintimaging" )
435 casalog.post( str(instance), "WARN", "task_sdintimaging" )
436 return
438 if (sdparms['sdgain']*0!=0 or sdparms['sdgain']<=0):
439 casalog.post('Invalid sdgain: '+str(sdparms['sdgain']), 'WARN')
440 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")
441 return
443 if (dishdia*0!=0 or dishdia<=0):
444 casalog.post('Invalid dishdia: '+str(dishdia), 'WARN')
445 casalog.post("The dishdia parameter needs to provide the diameter (meters) of the SD telescope which produced the SD image.", "WARN", "task_sdintimaging")
446 return
449 if specmode=='cont':
450 specmode='mfs'
451 inpparams['specmode']='mfs'
453 # from sdint
454 # automatically decide if pb need to be applied
455 if gridder=='mosaic' or gridder=='awproject':
456 applypb = True
457 else:
458 applypb = False
460 if (deconvolver=="mtmfs") and (specmode!='mfs') and (specmode!='cube' or nterms!=1) and (specmode!='cubedata' or nterms!=1):
461 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" )
462 return
464 if(deconvolver=="mtmfs" and (specmode=='cube' or specmode=='cubedata') and nterms==1 ):
465 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" )
466 return
468 if(specmode=='mfs' and deconvolver!='mtmfs'):
469 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")
470 return;
472 if(usedata=='sd'):
473 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");
475 if (nmajor < -1):
476 casalog.post("Negative values less than -1 for nmajor are reserved for possible future implementation", "WARN", "task_sdintimaging")
477 return
479# if parallel==True:
480# casalog.post("Cube parallelization (all major cycles) is currently not supported via task_sdintimaging. This will be enabled after a cube parallelization rework.")
481# return;
483 #####################################################
484 #### Construct ImagerParameters object
485 #####################################################
487 imager = None
488 paramList = None
489 deconvolvertool = None
491 # Put all parameters into dictionaries and check them.
492 ##make a dictionary of parameters that ImagerParameters take
493 defparm=dict(list(zip(ImagerParameters.__init__.__code__.co_varnames[1:], ImagerParameters.__init__.__defaults__)))
496 ###assign values to the ones passed to tclean and if not defined yet in tclean...
497 ###assign them the default value of the constructor
498 bparm={k: inpparams[k] if k in inpparams else defparm[k] for k in defparm.keys()}
500 ###default mosweight=True is tripping other gridders as they are not
501 ###expecting it to be true
502 if(bparm['mosweight']==True and bparm['gridder'].find("mosaic") == -1):
503 bparm['mosweight']=False
505 ## Two options have been removed from the interface. Hard-code them here.
506 bparm['normtype'] = 'flatnoise' ## Hard-code this since the pbcor steps assume it.
507 bparm['conjbeams']=False
509 #paramList=ImagerParameters(**bparm)
511 #paramList.printParameters()
513 if len(pointingoffsetsigdev)>0 and pointingoffsetsigdev[0]!=0.0 and usepointing==True and gridder.count('awproj')>1:
514 casalog.post("pointingoffsetsigdev will be used for pointing corrections with AWProjection", "WARN")
516 #=========================================================
517 ####set the children to load c++ libraries and applicator
518 ### make workers ready for c++ based mpicommands
519 cppparallel=False
520 if mpi_available and MPIEnvironment.is_mpi_enabled:
521 mint=MPIInterface.MPIInterface()
522 cl=mint.getCluster()
523 cl._cluster.pgc("from casatools import synthesisimager", False)
524 cl._cluster.pgc("si=synthesisimager()", False)
526 cl._cluster.pgc("si.initmpi()", False)
527 cppparallel=True
528 ###ignore chanchunk
529 bparm['chanchunks']=1
531 #################################################
532 #### start of more computing-intensive work #####
533 #################################################
535 synu = synthesisutils()
537 retrec={}
539 try:
540 mysdintlib = SDINT_helper()
541 ## Init major cycle elements
542 casalog.post("INT cube setup ....")
543 t0=time.time();
544 imager=setup_imager(int_cube, specmode, calcres, calcpsf, bparm)
545 mysdintlib.copy_restoringbeam(fromthis=int_cube+'.psf', tothis=int_cube+'.residual')
547 t1=time.time();
548 casalog.post("***Time for initializing imager (INT cube) : "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_sdintimaging");
550 ## Init minor cycle elements
551 if niter>0 or restoration==True:
552 casalog.post("Combined image setup ....")
553 t0=time.time();
554 deconvolvertool=setup_deconvolver(decname, specmode, bparm )
556 t1=time.time();
557 casalog.post("***Time for seting up deconvolver(s): "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_sdintimaging");
559 if usedata!='int':
560 ### debug (remove it later)
561 casalog.post("SD cube setup ....")
562 setup_sdimaging(template=int_cube, output=sd_cube, inparms=bparm, sdparms=sdparms )
565 ####now is the time to check estimated memory
566 # need to move to somewhere below???
567 imager.estimatememory()
569 ## Do sanity checks on INT and SD cubes
570 ### Frequency range of cube, data selection range. mtmfs reffreq.
571 ### nchan too small or too large
572 ### sumwt : flagged channels in int cubes
573 ### sd cube empty channels ? Weight image ?
574 validity, inpparams = mysdintlib.check_coords(intres=int_cube+'.residual', intpsf=int_cube+'.psf',
575 intwt = int_cube+'.sumwt',
576 sdres=sd_cube+'.residual', sdpsf=sd_cube+'.psf',
577 sdwt = '',
578 pars=inpparams)
580 if validity==False:
581 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')
582 if imager != None:
583 imager.deleteTools()
584 if deconvolvertool != None:
585 deconvolvertool.deleteTools()
586 mysdintlib.deleteTmpFiles()
587 return
589 #### SDINT specific feathering....
590 ## Feather INT and SD residual images (feather in flat-sky. output has common PB)
591 casalog.post("Feathering INT and SD residual images...")
592 mysdintlib.feather_residual(int_cube, sd_cube, joint_cube, applypb, inpparams)
593 mysdintlib.feather_int_sd(sdcube=sd_cube+'.psf',
594 intcube=int_cube+'.psf',
595 jointcube=joint_cube+'.psf',
596 sdgain=sdgain,
597 dishdia=dishdia,
598 usedata=usedata,
599 chanwt = inpparams['chanwt'])
601 #print("Fitting for cube")
602 synu.fitPsfBeam(joint_cube)
604 ###############
605 ##### Placeholder code for PSF renormalization if needed
606 ##### Note : If this is enabled, we'll need to restrict the use of 'faceting' as .sumwt shape changes.
607 #mysdintlib.calc_renorm(intname=int_cube, jointname=joint_cube)
608 #mysdintlib.apply_renorm(imname=joint_cube+'.psf', sumwtname=joint_cube+'.sumwt')
609 #mysdintlib.apply_renorm(imname=joint_cube+'.residual', sumwtname=joint_cube+'.sumwt')
610 ###############
612 #casalog.post("feather_int_sd DONE")
614 if specmode=='mfs':
615 ## Calculate Spectral PSFs and Taylor Residuals
616 casalog.post("Calculate spectral PSFs and Taylor Residuals...")
617 mysdintlib.cube_to_taylor_sum(cubename=joint_cube+'.psf',
618 cubewt=int_cube+'.sumwt',
619 chanwt=inpparams['chanwt'],
620 mtname=joint_multiterm+'.psf',
621 nterms=nterms, reffreq=inpparams['reffreq'], dopsf=True)
622 mysdintlib.cube_to_taylor_sum(cubename=joint_cube+'.residual',
623 cubewt=int_cube+'.sumwt',
624 chanwt=inpparams['chanwt'],
625 mtname=joint_multiterm+'.residual',
626 nterms=nterms, reffreq=inpparams['reffreq'], dopsf=False)
628 #print("Fit for multiterm")
629 if(deconvolver=='mtmfs' and nterms==1): # work around file naming issue
630 os.system('rm -rf '+joint_multiterm+'tmp.psf')
631 os.system('ln -sf '+joint_multiterm+'.psf.tt0 '+joint_multiterm+'tmp.psf')
632 synu.fitPsfBeam(joint_multiterm+'tmp',nterms=nterms)
633 os.system('rm -rf '+joint_multiterm+'tmp.psf')
634 else:
635 synu.fitPsfBeam(joint_multiterm,nterms=nterms)
637 if niter>0 :
638 isit = deconvolvertool.hasConverged()
639 deconvolvertool.updateMask()
641 while ( not deconvolvertool.hasConverged() ):
643 t0=time.time();
645 #### Print out the peak of the residual image here to check !!!
646# if specmode=='mfs':
647# print('Max of joint residual before initminorcycle' + str(imstat(joint_multiterm+'.residual.tt0',verbose=False)['max'][0]))
648# else:
649# print('Max of joint residual before initminorcycle' + str(imstat(joint_cube+'.residual',verbose=False)['max'][0]))
653 deconvolvertool.runMinorCycle()
655# if specmode=='mfs':
656# print('Max of joint residual after minorcycle' + str(imstat(joint_multiterm+'.residual.tt0',verbose=False)['max'][0]))
657# else:
658# print('Max of joint residual after minorcycle' + str(imstat(joint_cube+'.residual',verbose=False)['max'][0]))
661 t1=time.time();
662 casalog.post("***Time for minor cycle: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_sdintimaging");
664 ### sdint specific feathering steps HERE
665 ## Prepare the joint model cube for INT and SD major cycles
666 if specmode=='mfs':
667 ## Convert Taylor model coefficients into a model cube : int_cube.model
668 mysdintlib.taylor_model_to_cube(cubename=int_cube, ## output
669 mtname=joint_multiterm, ## input
670 nterms=nterms, reffreq=inpparams['reffreq'])
671 else:
672 ## Copy the joint_model cube to the int_cube.model
673 shutil.rmtree(int_cube+'.model',ignore_errors=True)
674 shutil.copytree(joint_cube+'.model', int_cube+'.model')
675 hasfile=os.path.exists(joint_cube+'.model')
676 #casalog.post("DEBUG: has joint cube .image===",hasfile)
678 if applypb==True:
679 ## Take the int_cube.model to flat sky.
680 if specmode=='cube':
681 ## Divide the model by the frequency-dependent PB to get to flat-sky
682 fdep_pb = True
683 else:
684 ## Divide the model by the common PB to get to get to flat-sky
685 fdep_pb = False
686 mysdintlib.modify_with_pb(inpcube=int_cube+'.model',
687 pbcube=int_cube+'.pb',
688 cubewt=int_cube+'.sumwt',
689 chanwt=inpparams['chanwt'],
690 action='div', pblimit=pblimit,freqdep=fdep_pb)
692 if usedata!="int":
693 ## copy the int_cube.model to the sd_cube.model
694 shutil.rmtree(sd_cube+'.model',ignore_errors=True)
695 shutil.copytree(int_cube+'.model', sd_cube+'.model')
697 if applypb==True:
698 ## Multiply flat-sky model with freq-dep PB
699 mysdintlib.modify_with_pb(inpcube=int_cube+'.model',
700 pbcube=int_cube+'.pb',
701 cubewt=int_cube+'.sumwt',
702 chanwt=inpparams['chanwt'],
703 action='mult', pblimit=pblimit, freqdep=True)
705 ## Major cycle for interferometer data
706 t0=time.time();
707 # print('Max of int residual before major cycle' + str(imstat(int_cube+'.residual',verbose=False)['max'][0]))
708 # print('Max of int model before major cycle' + str(imstat(int_cube+'.model',verbose=False)['max'][0]))
710 if usedata != "sd":
711 imager.runMajorCycle()
712 # track nmajor for the deconvolvertool.hasConverged() method
713 deconvolvertool.majorCnt = imager.majorCnt
715 # print('Max of int residual after major cycle' + str(imstat(int_cube+'.residual',verbose=False)['max'][0]))
716 t1=time.time();
717 casalog.post("***Time for major cycle: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean");
719 if usedata!="int":
720 ## Major cycle for Single Dish data (uses the flat sky cube model in sd_cube.model )
721 mysdintlib.calc_sd_residual(origcube=sd_cube+'.image',
722 modelcube=sd_cube+'.model',
723 residualcube=sd_cube+'.residual', ## output
724 psfcube=sd_cube+'.psf')
726 ## Feather the residuals
727 mysdintlib.feather_residual(int_cube, sd_cube, joint_cube, applypb, inpparams)
728 ###############
729 ##### Placeholder code for PSF renormalization if needed
730 #mysdintlib.apply_renorm(imname=joint_cube+'.residual', sumwtname=joint_cube+'.sumwt')
731 ###############
733 if specmode=='mfs':
734 ## Calculate Spectral Taylor Residuals
735 mysdintlib.cube_to_taylor_sum(cubename=joint_cube+'.residual',
736 cubewt=int_cube+'.sumwt',
737 chanwt=inpparams['chanwt'],
738 mtname=joint_multiterm+'.residual',
739 nterms=nterms, reffreq=inpparams['reffreq'], dopsf=False)
741# if specmode=='mfs':
742# print('Max of residual after feather step ' + str(imstat(joint_multiterm+'.residual.tt0',verbose=False)['max'][0]))
743# else:
744# print('Max of residual after feather step ' + str(imstat(joint_cube+'.residual',verbose=False)['max'][0]))
747 deconvolvertool.updateMask()
749 ## Get summary from iterbot
750 #if type(interactive) != bool:
751 #retrec=imager.getSummary();
752 retrec=deconvolvertool.getSummary(fullsummary);
753 retrec['nmajordone'] = imager.majorCnt
754 if calcres==True:
755 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.
757 ## Restore images.
758 if restoration==True:
759 t0=time.time();
760 deconvolvertool.restoreImages()
761 t1=time.time();
762 casalog.post("***Time for restoring images: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean");
763 if pbcor==True:
764 #if applypb==True:
765 t0=time.time();
766 if specmode=='mfs':
767 mysdintlib.pbcor(imagename=decname+'.image.tt0' , pbimage=decname+'.pb.tt0' , cutoff=pblimit,outfile=decname+'.image.tt0.pbcor')
768 else:
769 mysdintlib.pbcor(imagename=joint_cube+'.image' , pbimage=int_cube+'.pb' , cutoff=pblimit,outfile=joint_cube+'.image.pbcor')
771 #imager.pbcorImages()
772 t1=time.time();
773 casalog.post("***Time for pb-correcting images: "+"%.2f"%(t1-t0)+" sec", "INFO3", "task_tclean");
775 ##close tools
776 # needs to deletools before concat or lock waits for ever
777 imager.deleteTools()
778 deconvolvertool.deleteTools()
781 finally:
782 if imager != None:
783 imager.deleteTools()
784 if(cppparallel):
785 ###release workers back to python mpi control
786 si=synthesisimager()
787 si.releasempi()
789 #clean up tmp files
790 mysdintlib.deleteTmpFiles()
792 # Write history at the end, when hopefully all temp files are gone from disk,
793 # so they won't be picked up. They need time to disappear on NFS or slow hw.
794 # Copied from tclean.
795 try:
796 params = get_func_params(sdintimaging, locals())
797 write_tclean_history(imagename, 'sdintimaging', params, casalog)
798 except Exception as exc:
799 casalog.post("Error updating history (logtable): {} ".format(exc),'WARN')
801 return retrec
803##################################################