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

166 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-01 07:19 +0000

1import os 

2import math 

3import shutil 

4import string 

5import time 

6import re 

7import copy 

8 

9from casatools import synthesisdeconvolver, iterbotsink, ctsys, table 

10from casatasks import casalog 

11from casatasks.private.imagerhelpers.summary_minor import SummaryMinor 

12 

13ctsys_hostinfo = ctsys.hostinfo 

14_tb = table() # TODO is this necessary? 

15 

16''' 

17A set of helper functions for deconvolve. 

18 

19Summary... 

20  

21''' 

22 

23############################################# 

24class PyDeconvolver: 

25 def __init__(self,params): 

26 ################ Tools 

27 self.initDefaults() 

28 

29 # Check all input parameters, after partitioning setup. 

30 

31 # Imaging/Deconvolution parameters. Same for serial and parallel runs 

32 self.alldecpars = params.getDecPars() 

33 self.allimpars = params.getImagePars() 

34 # Iteration parameters 

35 self.iterpars = params.getIterPars() ## Or just params.iterpars 

36 

37 # Not necessary for deconvolver: 

38 ## self.allselpars = params.getSelPars() 

39 ## self.allgridpars = params.getGridPars() 

40 ## self.allnormpars = params.getNormPars() 

41 ## self.weightpars = params.getWeightPars() 

42 

43 ## Number of fields ( main + outliers ) 

44 self.NF = len(self.allimpars.keys()) 

45 self.stopMinor = {} ##[0]*self.NF 

46 for immod in range(0,self.NF): 

47 self.stopMinor[str(immod)]=1.0 

48 ## for debug mode automask incrementation only 

49 self.ncycle = 0 

50 self.initrecs = [] 

51 self.exrecs = [] 

52 

53############################################# 

54 def initializeDeconvolvers(self): 

55 for immod in range(0,self.NF): 

56 self.SDtools.append(synthesisdeconvolver()) 

57 decpars = self.alldecpars[str(immod)] 

58 decpars['noRequireSumwt'] = True 

59 self.SDtools[immod].setupdeconvolution(decpars=decpars) 

60 

61############################################# 

62 def initializeIterationControl(self): 

63 # note that in CASA5 this is casac.synthesisiterbot 

64 self.IBtool = iterbotsink() 

65 itbot = self.IBtool.setupiteration(iterpars=self.iterpars) 

66 

67############################################# 

68 def estimatememory(self): 

69 griddermem = 0 # no major cycle memory needed 

70 

71 deconmem=0 

72 for immod in range(0,self.NF): 

73 ims= self.allimpars[str(immod)]['imsize'] 

74 if(type(ims)==int) : 

75 ims=[ims, ims] 

76 if(len(ims) ==1): 

77 ims.append(ims[0]) 

78 #print 'shape', self.allimpars[str(immod)]['imsize'], len(ims)  

79 #print "DECON mem usage ", self.SDtools[immod].estimatememory(ims) 

80 if(len(self.SDtools) > immod): 

81 if(self.SDtools != None): 

82 deconmem+=self.SDtools[immod].estimatememory(ims) 

83 

84 availmem=ctsys_hostinfo()['memory']['available'] 

85 if((deconmem+griddermem) > 0.8*availmem): 

86 casalog.post("Memory available "+str(availmem)+" kB is very close to amount of required memory "+str(deconmem+griddermem)+" kB" , "WARN") 

87 else: 

88 casalog.post("Memory available "+str(availmem)+" kB and required memory "+str(deconmem+griddermem)+" kB" , "INFO2") 

89 

90############################################ 

91 def restoreImages(self): 

92 for immod in range(0,self.NF): 

93 self.SDtools[immod].restore() 

94 

95############################################# 

96 def pbcorImages(self): 

97 for immod in range(0,self.NF): 

98 self.SDtools[immod].pbcor() 

99 

100############################################# 

101 def getSummary(self,fullsummary, fignum=1): 

102 summ = self.IBtool.getiterationsummary() 

103 if ('summaryminor' in summ): 

104 summ['summaryminor'] = SummaryMinor.convertMatrix(summ['summaryminor'], fullsummary) 

105 return summ 

106 

107############################################# 

108 def deleteDeconvolvers(self): 

109 for immod in range(0,len(self.SDtools)): 

110 self.SDtools[immod].done() 

111 

112 def deleteIterBot(self): 

113 if self.IBtool != None: 

114 self.IBtool.done() 

115 

116 def initDefaults(self): 

117 # Reset globals/members 

118 self.NF=1 

119 self.stopMinor={'0':1.0} # Flag to call minor cycle for this field or not. 

120 self.NN=1 

121 self.SItool=None 

122 self.SDtools=[] 

123 self.PStools=[] 

124 self.IBtool=None 

125 

126############################################# 

127 

128 def deleteTools(self): 

129 self.deleteDeconvolvers() 

130 self.deleteIterBot() 

131 self.initDefaults() 

132 

133############################################# 

134 

135 def hasConverged(self): 

136 # Merge peak-res info from all fields to decide iteration parameters 

137 time0=time.time() 

138 self.IBtool.resetminorcycleinfo() 

139 self.initrecs = [] 

140 for immod in range(0,self.NF): 

141 initrec = self.SDtools[immod].initminorcycle() 

142 self.IBtool.mergeinitrecord( initrec ); 

143 self.initrecs.append(initrec) 

144 

145 # Check with the iteration controller about convergence. 

146 #print("check convergence") 

147 stopflag = self.IBtool.cleanComplete() 

148 #print('Converged : ', stopflag) 

149 if( stopflag>0 ): 

150 stopreasons = ['iteration limit', 'threshold', 'force stop','no change in peak residual across two major cycles', 'peak residual increased by more than 3 times from the previous major cycle','peak residual increased by more than 3 times from the minimum reached','zero mask', 'any combination of n-sigma and other valid exit criterion'] 

151 casalog.post("Reached global stopping criterion : " + stopreasons[stopflag-1], "INFO") 

152 

153 # revert the current automask to the previous one  

154 #if self.iterpars['interactive']: 

155 for immod in range(0,self.NF): 

156 if self.alldecpars[str(immod)]['usemask'].count('auto')>0: 

157 prevmask = self.allimpars[str(immod)]['imagename']+'.prev.mask' 

158 if os.path.isdir(prevmask): 

159 # Try to force rmtree even with an error as an nfs mounted disk gives an error  

160 #shutil.rmtree(self.allimpars[str(immod)]['imagename']+'.mask') 

161 shutil.rmtree(self.allimpars[str(immod)]['imagename']+'.mask', ignore_errors=True) 

162 # For NFS mounted disk it still leave .nfs* file(s)  

163 if os.path.isdir(self.allimpars[str(immod)]['imagename']+'.mask'): 

164 import glob 

165 if glob.glob(self.allimpars[str(immod)]['imagename']+'.mask/.nfs*'): 

166 for item in os.listdir(prevmask): 

167 src = os.path.join(prevmask,item) 

168 dst = os.path.join(self.allimpars[str(immod)]['imagename']+'.mask',item) 

169 if os.path.isdir(src): 

170 shutil.move(src, dst) 

171 else: 

172 shutil.copy2(src,dst) 

173 shutil.rmtree(prevmask) 

174 else: 

175 shutil.move(prevmask,self.allimpars[str(immod)]['imagename']+'.mask') 

176 casalog.post("[" + str(self.allimpars[str(immod)]['imagename']) + "] : Reverting output mask to one that was last used ", "INFO") 

177 

178 casalog.post("***Time taken in checking hasConverged "+str(time.time()-time0), "INFO3") 

179 return (stopflag>0) 

180 

181############################################# 

182 def updateMask(self): 

183 # Setup mask for each field ( input mask, and automask ) 

184 maskchanged = False 

185 time0=time.time() 

186 for immod in range(0,self.NF): 

187 maskchanged = maskchanged | self.SDtools[immod].setupmask() 

188 

189 # Run interactive masking (and threshold/niter editors), if interactive=True 

190 ig2maskchanged, nil, forcestop = self.runInteractiveGUI2() 

191 maskchanged = maskchanged | ig2maskchanged 

192 

193 time1=time.time(); 

194 casalog.post("Time to update mask "+str(time1-time0)+"s", "INFO3") 

195 ## Return a flag to say that the mask has changed or not. 

196 return maskchanged, forcestop 

197 

198############################################# 

199 def runInteractiveGUI2(self): 

200 maskchanged = False 

201 forcestop = True 

202 if self.iterpars['interactive'] == True: 

203 self.stopMinor = self.IBtool.pauseforinteraction() 

204 #print("Actioncodes in python : " , self.stopMinor) 

205 

206 for akey in self.stopMinor: 

207 if self.stopMinor[akey] < 0: 

208 maskchanged = True 

209 self.stopMinor[akey] = abs( self.stopMinor[akey] ) 

210 

211 #Check if force-stop has happened while savemodel != "none". 

212 forcestop=True; 

213 for akey in self.stopMinor: 

214 # Predicting the model requires knowledge about the normalization parameters. 

215 # Instead of predicting the model, return the value of forcestop so that the 

216 # major cycle has a chance to predict the model. 

217 forcestop = forcestop and self.stopMinor[akey]==3 

218 

219 #print('Mask changed during interaction : ', maskchanged) 

220 return ( maskchanged or forcestop, maskchanged, forcestop ) 

221 

222############################################# 

223 def runMinorCycle(self): 

224 self.runMinorCycleCore() 

225 

226############################################# 

227 def runMinorCycleCore(self): 

228 

229 # Set False for release packages.  

230 # Only set this to True for testing and debugging automask in parallel mode 

231 # since in parallel mode, runtime setting of the enviroment variable 

232 # currently does not work. 

233 # False = disable always save intermediate images mode 

234 alwaysSaveIntermediateImages=False 

235 

236 # Get iteration control parameters 

237 iterbotrec = self.IBtool.getminorcyclecontrols() 

238 #print("In synthdeconv. Minor Cycle controls : ", iterbotrec) 

239 

240 self.IBtool.resetminorcycleinfo() 

241 

242 # 

243 # Run minor cycle 

244 self.ncycle+=1 

245 self.exrecs = [] 

246 for immod in range(0,self.NF): 

247 if self.stopMinor[str(immod)]<3 : 

248 

249 # temporarily disable the check (=> always save the intermediate images 

250 if alwaysSaveIntermediateImages or ('SAVE_ALL_RESIMS' in os.environ and os.environ['SAVE_ALL_RESIMS']=="true"): 

251 resname = self.allimpars[str(immod)]['imagename']+'.residual' 

252 tempresname = self.allimpars[str(immod)]['imagename']+'.inputres'+str(self.ncycle) 

253 if os.path.isdir(resname): 

254 shutil.copytree(resname, tempresname) 

255 

256 exrec = self.SDtools[immod].executeminorcycle( iterbotrecord = iterbotrec ) 

257 

258 #print('.... iterdone for ', immod, ' : ' , exrec['iterdone']) 

259 self.IBtool.mergeexecrecord( exrec ) 

260 if alwaysSaveIntermediateImages or ('SAVE_ALL_AUTOMASKS' in os.environ and os.environ['SAVE_ALL_AUTOMASKS']=="true"): 

261 maskname = self.allimpars[str(immod)]['imagename']+'.mask' 

262 tempmaskname = self.allimpars[str(immod)]['imagename']+'.autothresh'+str(self.ncycle) 

263 if os.path.isdir(maskname): 

264 shutil.copytree(maskname, tempmaskname) 

265 self.exrecs.append(exrec) 

266 

267 # Some what duplicated as above but keep a copy of the previous mask 

268 # for interactive automask to revert to it if the current mask 

269 # is not used (i.e. reached deconvolution stopping condition). 

270 #if self.iterpars['interactive'] and self.alldecpars[str(immod)]['usemask']=='auto-thresh': 

271 if self.alldecpars[str(immod)]['usemask'].count('auto')>0: 

272 maskname = self.allimpars[str(immod)]['imagename']+'.mask' 

273 prevmaskname=self.allimpars[str(immod)]['imagename']+'.prev.mask' 

274 if os.path.isdir(maskname): 

275 if os.path.isdir(prevmaskname): 

276 shutil.rmtree(prevmaskname) 

277 shutil.copytree(maskname, prevmaskname) 

278 

279############################################# 

280 def getIterRecords(self): 

281 return {'initrecs':self.initrecs, 'exrecs':self.exrecs} 

282 

283####################################################### 

284####################################################### 

285