Commits

Srikrishna Sekhar authored 730b65e0308
CAS-14184 : Fix mask handling logic on startup

The mask handling used to be in the frontend, but moved it to the backend. It now correctly accounts for a restarted state with a previously active mask. The logic is : - Initial launch : If usemask='user' and mask = '' then make sure the default mask is filled with zeros before the GUI is launched. Leave mask untouched for all other cases - Restart : - If usemask='user' and mask='' : - If mask exists on disk - leave untouched - If mask does not exist, make sure mask is filled with zeros - Leave mask untouched for all other cases
No tags

casatasks/src/private/imagerhelpers/_gclean.py

Modified
267 267 self._minbeamfrac = minbeamfrac
268 268 self._cutthreshold = cutthreshold
269 269 self._growiterations = growiterations
270 270 self._dogrowprune = dogrowprune
271 271 self._minpercentchange = minpercentchange
272 272 self._verbose = verbose
273 273 self._fastnoise = fastnoise
274 274 self._savemodel = savemodel
275 275 self._parallel = parallel
276 276 self._usemask = usemask
277 -
278 - ###
279 - ### 'self._mask' always contains the mask as supplied by the user while 'self._effective_mask' is
280 - ### the mask currently in play as interactive clean progresses. When the user has supplied a mask,
281 - ### it should be the same as 'self._mask' but when the mask is managed internally by iclean/gclean
282 - ### the two will diverge.
283 - ###
284 277 self._mask = mask
285 278 self.global_imdict = ImagingDict()
286 279 self.current_imdict = ImagingDict()
287 280 self._major_done = 0
288 281 self.hasit = False # Convergence flag
289 282 self.stopdescription = '' # Convergence flag
283 + self._initial_mask_exists = False
290 284 self._convergence_result = (None,None,None,None,None,{ 'chan': None, 'major': None })
291 285 # ^^^^ ^^^^ ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----->>> convergence info
292 286 # | | | | +----->>> Number of global iterations remaining for current run (niterleft)
293 287 # | | | +---------->>> Number of major cycles remaining for current run (nmajorleft)
294 288 # | | +---------------->>> major cycles done for current run (nmajordone)
295 289 # | +------------------>>> tclean stopcode
296 290 # +----------------------->>> tclean stopdescription
297 291
298 292 # Convert threshold from string to float, interpreting units.
299 293 # XXX : We should ideally use quantities, but we are trying to
364 358 if key == 'iterDone':
365 359 # Maintain cumulative sum of iterations per entry
366 360 outrec[nn][ss]['iterations'] = np.cumsum(self.global_imdict.get_key(key, stokes=ss, chan=nn))
367 361 # Replace iterDone with iterations
368 362 #outrec[nn][ss]['iterations'] = self.global_imdict.get_key(key, stokes=ss, chan=nn)
369 363 else:
370 364 outrec[nn][ss][key] = self.global_imdict.get_key(key, stokes=ss, chan=nn)
371 365
372 366 return outrec
373 367
368 +
369 + def _check_initial_mask(self):
370 + """
371 + Check if a mask from a previous run exists on disk or not.
372 + """
373 +
374 + if self._usemask == 'user' and self._mask == '':
375 + if self._deconvolver == 'mtmfs':
376 + maskname = self._imagename + '.mask.tt0'
377 + else:
378 + maskname = self._imagename + '.mask'
379 +
380 + if os.path.exists(maskname):
381 + self._initial_mask_exists = True
382 + else:
383 + self._initial_mask_exists = False
384 +
385 + def _fix_initial_mask(self):
386 + """
387 + If on start up, no user mask is provided, then flip the initial mask to
388 + be all zeros for interactive use.
389 + """
390 +
391 + from casatools import image
392 + ia = image()
393 +
394 + if self._usemask == 'user' and self._mask == '':
395 + if self._deconvolver == 'mtmfs':
396 + maskname = self._imagename + '.mask.tt0'
397 + else:
398 + maskname = self._imagename + '.mask'
399 +
400 + # This means the mask was newly created by deconvolve, so flip it
401 + if os.path.exists(maskname) and self._initial_mask_exists is False:
402 + ia.open(maskname)
403 + ia.set(0.0)
404 + ia.close()
405 +
374 406 def _update_peakres(self):
375 407 if self._deconvolver == 'mtmfs':
376 408 residname = self._imagename + '.residual.tt0'
377 409 else:
378 410 residname = self._imagename + '.residual'
379 411
380 412 maskname = self._imagename + '.mask'
381 413 if not os.path.exists(maskname):
382 414 maskname = ''
383 415
438 470 interpolation=self._interpolation, perchanweightdensity=self._perchanweightdensity,
439 471 nchan=self._nchan, start=self._start, width=self._width, veltype=self._veltype, restfreq=self._restfreq,
440 472 outframe=self._outframe, pointingoffsetsigdev=self._pointingoffsetsigdev, pblimit=self._pblimit,
441 473 deconvolver=self._deconvolver, smallscalebias=self._smallscalebias, cyclefactor=self._cyclefactor,
442 474 scales=self._scales, restoringbeam=self._restoringbeam, pbcor=self._pbcor, nterms=self._nterms,
443 475 field=self._field, spw=self._spw, timerange=self._timerange, uvrange=self._uvrange, antenna=self._antenna,
444 476 scan=self._scan, observation=self._observation, intent=self._intent, datacolumn=self._datacolumn,
445 477 weighting=self._weighting, robust=self._robust, npixels=self._npixels, interactive=False, niter=0,
446 478 gain=self._gain, calcres=True, calcpsf=True, restoration=False, parallel=self._parallel, fullsummary=True)
447 479
480 + # Check if a mask from a previous run exists on disk
481 + self._check_initial_mask()
448 482
449 483 deconv_ret = self._deconvolve(imagename=self._imagename, startmodel=self._startmodel,
450 484 deconvolver=self._deconvolver, restoration=False,
451 485 threshold=self._threshold, niter=0,
452 486 nsigma=self._nsigma, fullsummary=True, fastnoise=self._fastnoise, usemask=self._usemask,
453 487 mask=self._mask, pbmask=self._pbmask, sidelobethreshold=self._sidelobethreshold, noisethreshold=self._noisethreshold,
454 488 lownoisethreshold=self._lownoisethreshold, negativethreshold=self._negativethreshold, smoothfactor=self._smoothfactor,
455 489 minbeamfrac=self._minbeamfrac, cutthreshold=self._cutthreshold, growiterations=self._growiterations,
456 490 dogrowprune=self._dogrowprune, verbose=self._verbose)
457 491
492 + # If no mask from a previous run exists, over-write the ones with zeros for the default mask
493 + self._fix_initial_mask()
494 +
458 495 self.current_imdict.returndict = self.current_imdict.merge(tclean_ret, deconv_ret)
459 496 self.global_imdict.returndict = self.current_imdict.returndict
460 497
461 498 ## Initial call where niterleft and nmajorleft are same as original input values.
462 499 self.hasit, self.stopdescription = self.global_imdict.has_converged(self._niter, self._threshold, self._nmajor)
463 500
464 501 self.current_imdict.returndict['stopcode'] = self.hasit
465 502 self.current_imdict.returndict['stopDescription'] = self.stopdescription
466 503 self._major_done = 0
467 504 else:
477 514 #self.global_imdict.returndict['stopcode'] = self.hasit
478 515 #self.global_imdict.returndict['stopDescription'] = self.stopdescription
479 516
480 517 #self.current_imdict.returndict['stopcode'] = self.hasit
481 518 #self.current_imdict.returndict['stopDescription'] = self.stopdescription
482 519
483 520 # Has not, i.e., not converged
484 521 if self.hasit ==0 :
485 522 use_cycleniter, cyclethreshold = self._calc_deconv_controls(self.current_imdict, self._niter, self._threshold, self._cycleniter)
486 523
487 - print("No convergence, running deconvolve + tclean")
488 524 # Run the minor cycle
489 525 deconv_ret = self._deconvolve(imagename=self._imagename, startmodel=self._startmodel,
490 526 deconvolver=self._deconvolver, restoration=False,
491 527 threshold=cyclethreshold, niter=use_cycleniter, gain=self._gain, fullsummary=True)
492 528
493 529 # Run the major cycle
494 530 tclean_ret = self._tclean( vis=self._vis, imagename=self._imagename, imsize=self._imsize, cell=self._cell,
495 531 phasecenter=self._phasecenter, stokes=self._stokes, specmode=self._specmode, reffreq=self._reffreq,
496 532 gridder=self._gridder, wprojplanes=self._wprojplanes, mosweight=self._mosweight, psterm=self._psterm,
497 533 wbawp=self._wbawp, conjbeams=self._conjbeams, usepointing=self._usepointing, interpolation=self._interpolation,
528 564 self.hasit, self.stopdescription = self.global_imdict.has_converged(self._niter, self._threshold, self._nmajor, masksum=0)
529 565 else:
530 566 self.hasit, self.stopdescription = self.global_imdict.has_converged(self._niter, self._threshold, self._nmajor)
531 567
532 568
533 569 self.global_imdict.returndict['stopcode'] = self.hasit
534 570 self.global_imdict.returndict['stopDescription'] = self.stopdescription
535 571
536 572 if not self.hasit:
537 573 # If we haven't converged, run deconvolve to update the mask
538 - #print("no convergence, updating mask")
539 -
540 574 self._deconvolve(imagename=self._imagename, startmodel=self._startmodel, deconvolver=self._deconvolver, restoration=False, threshold=self._threshold, niter=0,
541 575 nsigma=self._nsigma, fullsummary=True, fastnoise=self._fastnoise, usemask=self._usemask, mask=self._mask, pbmask=self._pbmask,
542 576 sidelobethreshold=self._sidelobethreshold, noisethreshold=self._noisethreshold, lownoisethreshold=self._lownoisethreshold,
543 577 negativethreshold=self._negativethreshold, smoothfactor=self._smoothfactor, minbeamfrac=self._minbeamfrac, cutthreshold=self._cutthreshold,
544 578 growiterations=self._growiterations, dogrowprune=self._dogrowprune, verbose=self._verbose)
545 579
546 580
547 581 if len(self.global_imdict.returndict) > 0 and 'summaryminor' in self.global_imdict.returndict and sum(map(len,self.global_imdict.returndict['summaryminor'].values())) > 0:
548 582 self._convergence_result = ( self.global_imdict.returndict['stopDescription'] if 'stopDescription' in self.global_imdict.returndict else '',
549 583 self.global_imdict.returndict['stopcode'] if 'stopcode' in self.global_imdict.returndict else 0,

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut