casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables
task_tclean.py
Go to the documentation of this file.
00001 ################################################
00002 # Refactored Clean task
00003 #
00004 # v1.0: 2012.10.05, U.R.V.
00005 #
00006 ################################################
00007 
00008 from taskinit import *
00009 
00010 import os
00011 import shutil
00012 import numpy
00013 from taskinit import *
00014 import copy
00015 
00016 def tclean(vis='', field='', spw='',
00017            imagename='',nchan=1,
00018            startmodel='',
00019            niter=0, threshold=0.0, loopgain=0.1, maxcycleniter=-1, cyclefactor=1, minpsffraction=0.05, maxpsffraction=0.8,
00020            usescratch=True, clusterdef=''):
00021 
00022     #casalog.post('This is an empty task. It is meant only to build/test/maintain the interface for the refactored imaging code. When ready, it will be offered to users for testing.','WARN')
00023 
00024     # Put all parameters into dictionaries
00025     params={}
00026     params['dataselection']={'vis':vis, 'field':field, 'spw':spw, 'usescratch':usescratch}
00027     params['imagedefinition']={'imagename':imagename, 'nchan':nchan}
00028     params['imaging']={'startmodel':startmodel}
00029     params['deconvolution']={}
00030     params['iteration']={'niter':niter, 'threshold':threshold, 'loopgain':loopgain, 'maxcycleniter':maxcycleniter, 'cyclefactor':cyclefactor , 'minpsffraction':minpsffraction, 'maxpsffraction':maxpsffraction}
00031     params['other']={'clusterdef':clusterdef}
00032 
00033     # Instantiate the Imager class
00034     if len(clusterdef)==0:
00035         imager = PySynthesisImager(casalog,params)
00036     else:
00037         imager = ParallelPySynthesisImager(casalog,params)
00038 
00039     # Check input parameters (types, etc..)
00040     if not imager.checkParameters():
00041         return False
00042 
00043     # All setup steps
00044     imager.initialize()
00045 
00046     # Run major/minor cycle loops
00047     imager.runLoops()
00048 
00049     # Restore and Clean up.
00050     imager.finalize()
00051 
00052     # Save history - Params, Flux Cleaned, Peak Residual, Niter, TimeTaken, Image Names?
00053     return imager.returninfo()
00054 
00055 
00056 ###################################################
00057 ##  Single-node imaging.
00058 ###################################################
00059 
00060 class PySynthesisImager:
00061     """ Class to do imaging and deconvolution """
00062 
00063     def __init__(self,casalog,params):
00064         self.toolsi=None #gentools(['si'])[0]
00065         self.casalog = casalog
00066         self.params = params
00067         self.loopcontrols = {}
00068         self.listofimagedefinitions = []
00069         self.casalog.origin('tclean')
00070 
00071 
00072     def checkParameters(self):
00073         self.casalog.origin('tclean.checkParameters')
00074         self.casalog.post('Verifying Input Parameters')
00075         # Init the error-string
00076         errs = "" 
00077 
00078         errs = errs + self.checkAndFixSelectionPars( self.params['dataselection'] )
00079 
00080         errs = errs + self.checkAndFixImageCoordPars( self.params['imagedefinition'] )
00081 
00082         ## If there are errors, print a message and exit.
00083         if len(errs) > 0:
00084             casalog.post('Parameter Errors : \n' + errs)
00085             return False
00086         return True
00087 
00088     def initialize(self, toolsi=None):
00089         self.casalog.origin('tclean.initialize')
00090         if toolsi==None:
00091             #self.toolsi = gentools(['si'])[0]
00092             self.toolsi = casac.synthesisimager() ##gentools(['si'])[0]
00093             toolsi = self.toolsi
00094         toolsi.selectdata(selpars=self.params['dataselection'])
00095 
00096         impars = copy.deepcopy( self.params['imagedefinition'] )
00097 
00098         ## Start a loop on 'multi-fields' here....
00099         for eachimdef in self.listofimagedefinitions:
00100             # Fill in the individual parameters
00101             impars['imagename'] = eachimdef[ 'imagename' ]
00102             # Init a mapper for each individual field
00103             toolsi.defineimage(impars=impars)
00104             toolsi.setupimaging(gridpars=self.params['imaging'])
00105             toolsi.setupdeconvolution(decpars=self.params['deconvolution'])
00106             toolsi.initmapper()
00107         ## End loop on 'multi-fields' here....
00108 
00109         self.loopcontrols = toolsi.setupiteration(iterpars=self.params['iteration'] ) # From ParClean loopcontrols gets overwritten, but it is always with the same thing. Try to clean this up. 
00110 
00111         ##toolsi.initcycles()
00112 
00113 
00114     def runMajorCycle(self,toolsi=None):
00115         self.casalog.origin('tclean.runMajorCycle')
00116         if toolsi==None:
00117             toolsi = self.toolsi
00118         self.loopcontrols.update( toolsi.runmajorcycle( self.loopcontrols ) ) 
00119         # In this prev statement, send in updated model to override default.
00120 
00121 
00122     def runMinorCycle(self, toolsi=None):
00123         self.casalog.origin('tclean.runMinorCycle')
00124         if toolsi==None:
00125             toolsi = self.toolsi
00126         self.loopcontrols.update( toolsi.runminorcycle( self.loopcontrols ) )
00127 
00128     def runLoops(self):
00129         self.casalog.origin('tclean.runLoops')
00130         self.runMajorCycle()
00131         while not self.loopcontrols['stop']:  # Make the tool take loopcontrols as in/out ( not const ! )
00132             self.runMinorCycle()
00133             self.runMajorCycle()
00134 
00135     def finalize(self, toolsi=None):
00136         if toolsi==None:
00137             toolsi = self.toolsi
00138         toolsi.endloops( self.loopcontrols )
00139         #toolsi.done()
00140 
00141     def returninfo(self):
00142         return self.loopcontrols
00143 
00144 
00145     ###### Start : Parameter-checking functions ##################
00146     def checkAndFixSelectionPars(self, selpars={} ):
00147         errs=""
00148         # vis, field, spw, etc must all be equal-length lists of strings.
00149         if not selpars.has_key('vis'):
00150             errs = errs + 'MS name(s) not specified'
00151         else:
00152             if type(selpars['vis'])==str:
00153                 selpars['vis']=[selpars['vis']]
00154             nvis = len(selpars['vis'])
00155             selkeys = ['field','spw']
00156             for par in selkeys:
00157                 if selpars.has_key(par):
00158                     if selpars[par]=='':
00159                         selpars[par] = []
00160                         for it in range(0,nvis):
00161                             selpars[par].append('')
00162                     if type(selpars[par])==str:
00163                         selpars[par]=[selpars[par]]
00164                     if len(selpars[par]) != nvis:
00165                         errs = errs + "Selection for " + par + " must be a list of " + str(nvis) + " selection strings\n"
00166                 else:
00167                     errs = errs + "Selection for " + par + " is unspecified\n"
00168 
00169         return errs
00170 
00171     def checkAndFixImageCoordPars(self, impars={} ):
00172         errs=""
00173 
00174         ### Get a list of image-coord pars from the multifield outlier file + main field...
00175         ### Go through this list, and do setup. :  Fill in self.listofimagedefinitions with dicts of params
00176 
00177         ## FOR NOW... this list is just a list of image names....
00178 
00179         ## One image only
00180         if type( impars['imagename'] ) == str:
00181             self.listofimagedefinitions.append( {'imagename':impars['imagename']} )
00182 
00183         ## If multiple images are specified....... 
00184         if type( impars['imagename'] ) == list:
00185             for imname in impars['imagename']:
00186                 self.listofimagedefinitions.append( {'imagename':imname} )
00187 
00188         return errs
00189 
00190     ###### End : Parameter-checking functions ##################
00191 
00192 
00193 
00194 ###################################################
00195 ##  Parallel imaging.
00196 ###################################################
00197 
00198 class ParallelPySynthesisImager(PySynthesisImager):
00199     """ Class to do imaging and deconvolution, with major cycles distributed across cluster nodes """
00200 
00201     def __init__(self,casalog,params):
00202         PySynthesisImager.__init__(self,casalog,params)
00203         # Read params['other']['clusterdef'] to decide chunking.
00204         self.nchunks = len(params['other']['clusterdef'])
00205         # Initialize a list of synthesisimager tools
00206         self.toollist = []
00207         for ch in range(0,self.nchunks):
00208             #self.toollist.append( gentools(['si'])[0]  )
00209             self.toollist.append( casac.synthesisimager() ) ## gentools(['si'])[0]  )
00210 
00211 
00212     def initialize(self):
00213         selpars = copy.deepcopy( self.params['dataselection'] )
00214         for ch in range(0,self.nchunks):
00215             casalog.origin('parallel.tclean.runMinorCycle')
00216             casalog.post('Initialize for chunk '+str(ch))
00217 
00218             for dat in range(0,len( selpars['spw'] )):
00219                 self.params['dataselection']['spw'][dat] = selpars['spw'][dat] + ':'+str(ch)
00220 
00221             PySynthesisImager.initialize(self, self.toollist[ch] )
00222         self.params['dataselection'] = copy.deepcopy(selpars)
00223 
00224     def runMajorCycle(self):
00225         lcontrols = copy.deepcopy( self.loopcontrols )
00226         for ch in range(0,self.nchunks):
00227             self.loopcontrols = copy.deepcopy( lcontrols )
00228             PySynthesisImager.runMajorCycle(self, self.toollist[ch] )  # Send in updated model as startmodel..
00229         self.gatherImages()
00230 
00231     def runMinorCycle(self):
00232         casalog.origin('parallel.tclean.runMinorCycle')
00233         casalog.post('Set combined images for the minor cycle')
00234         PySynthesisImager.runMinorCycle(self, self.toollist[0] )  # Use the full list for spectral-cube deconv.
00235         casalog.origin('parallel.tclean.runMinorCycle')
00236         casalog.post('Mark updated model as input to all major cycles') 
00237 
00238     def finalize(self):
00239         self.toollist[0].endloops( self.loopcontrols )
00240         #for ch in range(0,self.nchunks):
00241         #    self.toollist[ch].done()
00242 
00243     def gatherImages(self):
00244         casalog.origin('parallel.tclean.gatherimages')
00245         casalog.post('Gather images from all chunks')
00246