LCOV - code coverage report
Current view: top level - synthesis/ImagerObjects - SynthesisDeconvolver.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 518 636 81.4 %
Date: 2024-11-06 17:42:47 Functions: 27 31 87.1 %

          Line data    Source code
       1             : //# SynthesisDeconvolver.cc: Implementation of Imager.h
       2             : //# Copyright (C) 1997-2020
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This program is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU General Public License as published by the Free
       7             : //# Software Foundation; either version 2 of the License, or (at your option)
       8             : //# any later version.
       9             : //#
      10             : //# This program is distributed in the hope that it will be useful, but WITHOUT
      11             : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             : //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      13             : //# more details.
      14             : //#
      15             : //# You should have received a copy of the GNU General Public License along
      16             : //# with this program; if not, write to the Free Software Foundation, Inc.,
      17             : //# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
      18             : //#
      19             : //# Correspondence concerning AIPS++ should be addressed as follows:
      20             : //#        Internet email: casa-feedback@nrao.edu.
      21             : //#        Postal address: AIPS++ Project Office
      22             : //#                        National Radio Astronomy Observatory
      23             : //#                        520 Edgemont Road
      24             : //#                        Charlottesville, VA 22903-2475 USA
      25             : //#
      26             : //# $Id$
      27             : 
      28             : #include <casacore/casa/Exceptions/Error.h>
      29             : #include <iostream>
      30             : #include <sstream>
      31             : 
      32             : #include <casacore/casa/Arrays/Matrix.h>
      33             : #include <casacore/casa/Arrays/ArrayMath.h>
      34             : #include <casacore/casa/Arrays/ArrayLogical.h>
      35             : 
      36             : #include <casacore/casa/Logging.h>
      37             : #include <casacore/casa/Logging/LogIO.h>
      38             : #include <casacore/casa/Logging/LogMessage.h>
      39             : #include <casacore/casa/Logging/LogSink.h>
      40             : #include <casacore/casa/Logging/LogMessage.h>
      41             : 
      42             : #include <casacore/casa/OS/DirectoryIterator.h>
      43             : #include <casacore/casa/OS/File.h>
      44             : #include <casacore/casa/OS/Path.h>
      45             : 
      46             : #include <casacore/casa/OS/HostInfo.h>
      47             : 
      48             : #include <casacore/images/Images/TempImage.h>
      49             : #include <casacore/images/Images/SubImage.h>
      50             : #include <casacore/images/Regions/ImageRegion.h>
      51             : #include <casacore/lattices/Lattices/LatticeLocker.h>
      52             : #include <synthesis/ImagerObjects/CubeMinorCycleAlgorithm.h>
      53             : #include <imageanalysis/ImageAnalysis/CasaImageBeamSet.h>
      54             : #include <synthesis/ImagerObjects/SynthesisDeconvolver.h>
      55             : #include <synthesis/ImagerObjects/SIMinorCycleController.h>
      56             : 
      57             : #include <sys/types.h>
      58             : #include <unistd.h>
      59             : using namespace std;
      60             : 
      61             : using namespace casacore;
      62             : extern casa::Applicator casa::applicator;
      63             : namespace casa { //# NAMESPACE CASA - BEGIN
      64             : 
      65        1062 :   SynthesisDeconvolver::SynthesisDeconvolver() :
      66        1062 :                                        itsDeconvolver(nullptr),
      67        1062 :                                        itsMaskHandler(nullptr ),
      68        1062 :                itsImages(nullptr),
      69        1062 :                itsImageName(""),
      70             :                                        //itsPartImageNames(Vector<String>(0)),
      71        1062 :                                        itsBeam(0.0),
      72        1062 :                                        itsDeconvolverId(0),
      73        1062 :                                        itsScales(Vector<Float>()),
      74        1062 :                itsMaskType(""),
      75        1062 :                itsPBMask(0.0),
      76             :                                        //itsMaskString(String("")),
      77        1062 :                itsIterDone(0.0),
      78        1062 :                itsChanFlag(Vector<Bool>(0)),
      79        1062 :                itsRobustStats(Record()),
      80        1062 :                initializeChanMaskFlag(false),
      81        1062 :                itsPosMask(nullptr),
      82        1062 :                                        itsIsMaskLoaded(false),
      83        1062 :                                        itsMaskSum(-1e+9),
      84        1062 :                                        itsPreviousFutureRes(0.0),
      85        5310 :                                        itsPreviousIterBotRec_p(Record())
      86             :   {
      87        1062 :   }
      88             : 
      89        1062 :   SynthesisDeconvolver::~SynthesisDeconvolver()
      90             :   {
      91        2124 :         LogIO os( LogOrigin("SynthesisDeconvolver","descructor",WHERE) );
      92        1062 :         os << LogIO::DEBUG1 << "SynthesisDeconvolver destroyed" << LogIO::POST;
      93        1062 :         SynthesisUtilMethods::getResource("End SynthesisDeconvolver");
      94             : 
      95        1062 :   }
      96             : 
      97        1062 :   void SynthesisDeconvolver::setupDeconvolution(const SynthesisParamsDeconv& decpars)
      98             :   {
      99        2124 :     LogIO os( LogOrigin("SynthesisDeconvolver","setupDeconvolution",WHERE) );
     100             : 
     101             :     //Copy this decpars into a private variable that can be used elsewhere
     102             :     //there is no proper copy operator (as public casa::Arrays members = operator fails)
     103        1062 :     itsDecPars.fromRecord(decpars.toRecord());
     104        1062 :     itsImageName = decpars.imageName;
     105        1062 :     itsStartingModelNames = decpars.startModel;
     106        1062 :     itsDeconvolverId = decpars.deconvolverId;
     107             : 
     108        1062 :     os << "Set Deconvolution Options for [" << itsImageName << "] : " << decpars.algorithm ;
     109             : 
     110        1062 :     if( itsStartingModelNames.nelements()>0 && itsStartingModelNames[0].length() > 0 )
     111          26 :       os << " , starting from model : " << itsStartingModelNames;
     112        1062 :     os << LogIO::POST;
     113             : 
     114             :     try
     115             :       {
     116        1062 :         if(decpars.algorithm==String("hogbom"))
     117             :           {
     118         799 :             itsDeconvolver.reset(new SDAlgorithmHogbomClean());
     119             :           }
     120         263 :         else if(decpars.algorithm==String("mtmfs"))
     121             :           {
     122         148 :             itsDeconvolver.reset(new SDAlgorithmMSMFS( decpars.nTaylorTerms, decpars.scales, decpars.scalebias ));
     123             :           }
     124         115 :         else if(decpars.algorithm==String("clark_exp"))
     125             :           {
     126           0 :             itsDeconvolver.reset(new SDAlgorithmClarkClean("clark"));
     127             :           }
     128         115 :         else if(decpars.algorithm==String("clarkstokes_exp"))
     129             :           {
     130           0 :             itsDeconvolver.reset(new SDAlgorithmClarkClean("clarkstokes"));
     131             :           }
     132         115 :         else if(decpars.algorithm==String("clark"))
     133             :           {
     134          64 :             itsDeconvolver.reset(new SDAlgorithmClarkClean2("clark"));
     135             :           }
     136          51 :         else if(decpars.algorithm==String("clarkstokes"))
     137             :           {
     138           5 :             itsDeconvolver.reset(new SDAlgorithmClarkClean2("clarkstokes"));
     139             :           }
     140          46 :         else if(decpars.algorithm==String("multiscale"))
     141             :           {
     142          34 :             itsDeconvolver.reset(new SDAlgorithmMSClean( decpars.scales, decpars.scalebias ));
     143             :           }
     144          12 :         else if(decpars.algorithm==String("mem"))
     145             :           {
     146           1 :             itsDeconvolver.reset(new SDAlgorithmMEM( "entropy" ));
     147             :           }
     148          11 :         else if (decpars.algorithm==String("asp"))
     149             :           {
     150          11 :       bool isSingle = false;
     151          11 :       if (decpars.specmode == String("mfs"))
     152           0 :         isSingle = true;
     153             : 
     154          11 :             itsDeconvolver.reset(new SDAlgorithmAAspClean(decpars.fusedThreshold, isSingle, decpars.largestscale));
     155             :           }
     156             :         else
     157             :           {
     158           0 :             throw( AipsError("Un-known algorithm : "+decpars.algorithm) );
     159             :           }
     160             : 
     161             :         // Set restoring beam options
     162        1062 :         itsDeconvolver->setRestoringBeam( decpars.restoringbeam, decpars.usebeam );
     163        1062 :         itsUseBeam = decpars.usebeam;// store this info also here.
     164             : 
     165             :         // Set Masking options
     166             :         //      itsDeconvolver->setMaskOptions( decpars.maskType );
     167        1062 :         itsMaskHandler.reset(new SDMaskHandler());
     168             :         //itsMaskString = decpars.maskString;
     169        1062 :         itsMaskType = decpars.maskType;
     170        1062 :         if(itsMaskType=="auto-thresh")
     171             :           {
     172           0 :             itsAutoMaskAlgorithm="thresh";
     173             :           }
     174        1062 :         else if(itsMaskType=="auto-thresh2")
     175             :           {
     176           0 :             itsAutoMaskAlgorithm="thresh2";
     177             :           }
     178        1062 :         else if(itsMaskType=="auto-multithresh")
     179             :           {
     180          46 :             itsAutoMaskAlgorithm="multithresh";
     181             :           }
     182        1016 :         else if(itsMaskType=="auto-onebox")
     183             :           {
     184           0 :             itsAutoMaskAlgorithm="onebox";
     185             :           }
     186             :         else {
     187        1016 :             itsAutoMaskAlgorithm="";
     188             :         }
     189        1062 :         itsPBMask = decpars.pbMask;
     190        1062 :         itsMaskString = decpars.maskString;
     191        2660 :         if(decpars.maskList.nelements()==0 ||
     192        1598 :             (decpars.maskList.nelements()==1 && decpars.maskList[0]==""))
     193             :           {
     194        1062 :             itsMaskList.resize(1);
     195        1062 :             itsMaskList[0] = itsMaskString;
     196             :           }
     197             :         else
     198             :           {
     199           0 :             itsMaskList = decpars.maskList;
     200             :           }
     201        1062 :         itsMaskThreshold = decpars.maskThreshold;
     202        1062 :         itsFracOfPeak = decpars.fracOfPeak;
     203        1062 :         itsMaskResolution = decpars.maskResolution;
     204        1062 :         itsMaskResByBeam = decpars.maskResByBeam;
     205        1062 :         itsNMask = decpars.nMask;
     206             :         //itsAutoAdjust = decpars.autoAdjust;
     207             :         //desable autoadjust
     208        1062 :         itsAutoAdjust = false;
     209        1062 :         itsSidelobeThreshold = decpars.sidelobeThreshold;
     210        1062 :         itsNoiseThreshold = decpars.noiseThreshold;
     211        1062 :         itsLowNoiseThreshold = decpars.lowNoiseThreshold;
     212        1062 :         itsNegativeThreshold = decpars.negativeThreshold;
     213        1062 :         itsSmoothFactor = decpars.smoothFactor;
     214        1062 :         itsMinBeamFrac = decpars.minBeamFrac;
     215        1062 :         itsCutThreshold = decpars.cutThreshold;
     216        1062 :         itsGrowIterations = decpars.growIterations;
     217        1062 :         itsDoGrowPrune = decpars.doGrowPrune;
     218        1062 :         itsMinPercentChange = decpars.minPercentChange;
     219        1062 :         itsVerbose = decpars.verbose;
     220        1062 :         itsFastNoise = decpars.fastnoise;
     221        1062 :               itsIsInteractive = decpars.interactive;
     222        1062 :         itsNsigma = decpars.nsigma;
     223        1062 :         itsNoRequireSumwt = true; //decpars.noRequireSumwt;
     224        1062 :         itsFullSummary = decpars.fullsummary;
     225             :       }
     226           0 :     catch(AipsError &x)
     227             :       {
     228           0 :         throw( AipsError("Error in constructing a Deconvolver : "+x.getMesg()) );
     229           0 :       }
     230             : 
     231        1062 :     itsAddedModel=false;
     232        1062 :   }
     233             : 
     234         770 :   Long SynthesisDeconvolver::estimateRAM(const vector<int>& imsize){
     235             : 
     236         770 :     Long mem=0;
     237             :     /* This does not work
     238             :     if( ! itsImages )
     239             :       {
     240             :         itsImages = makeImageStore( itsImageName );
     241             :       }
     242             :     */
     243         770 :     if(itsDeconvolver)
     244         770 :       mem=itsDeconvolver->estimateRAM(imsize);
     245         770 :     return mem;
     246             :   }
     247             : 
     248        2205 :   Record SynthesisDeconvolver::initMinorCycle() {
     249             :     /////IMPORTANT initMinorCycle has to be called before setupMask...that order has to be kept !
     250             : 
     251        2205 :     if(!itsImages)
     252         219 :       itsImages=makeImageStore(itsImageName, itsNoRequireSumwt);
     253             :     //For cubes as we are not doing a post major cycle residual automasking
     254             :     //Force recalculation of robust stats to update nsigmathreshold with
     255             :     //most recent residual
     256             : 
     257        2205 :     if(itsAutoMaskAlgorithm=="multithresh" && itsImages->residual()->shape()[3] >1 && itsNsigma > 0.0){
     258           0 :       Record retval;
     259           0 :       Record backupRobustStats=itsRobustStats;
     260           0 :       itsRobustStats=Record();
     261           0 :       retval=initMinorCycle(itsImages);
     262           0 :       itsRobustStats=backupRobustStats;
     263           0 :       return retval;
     264           0 :     }
     265             : 
     266             :     /* else if (itsAutoMaskAlgorithm=="multithresh" && itsImages->residual()->shape()[3]){
     267             :       ///As the automask for cubes pre-CAS-9386...
     268             :       /// was tuned to look for threshold in future mask
     269             :       ///It is as good as somewhere in between no mask and mask
     270             :       //      Record backupRobustStats=itsRobustStats;
     271             :       Record retval=initMinorCycle(itsImages);
     272             :       //cerr << "INITMINOR " << itsRobustStats << endl;
     273             :       //itsRobustStats=backupRobustStats;
     274             :       if(retval.isDefined("peakresidualnomask")){
     275             :         Float futureRes=Float(retval.asFloat("peakresidualnomask")-(retval.asFloat("peakresidualnomask")-retval.asFloat("peakresidual"))/1000.0);
     276             :         if(futureRes != itsPreviousFutureRes){
     277             :           //itsLoopController.setPeakResidual(retval.asFloat("peakresidualnomask"));
     278             :           retval.define("peakresidual", futureRes);
     279             :           itsPreviousFutureRes=futureRes;
     280             :         }
     281             :       }
     282             :       return retval;
     283             :       }
     284             :     */
     285        2211 :     Record retval= initMinorCycle(itsImages);
     286             :     //    cerr << "INITMINOR retval" << retval << endl;
     287             : 
     288        2199 :     return retval;
     289        2199 :   }
     290        2468 :   Record SynthesisDeconvolver::initMinorCycle(std::shared_ptr<SIImageStore> imstor )
     291             :   {
     292        4936 :     LogIO os( LogOrigin("SynthesisDeconvolver","initMinorCycle",WHERE) );
     293        2468 :     Record returnRecord;
     294        2468 :     Timer timer;
     295        2468 :     Timer tim;
     296        2468 :     tim.mark();
     297             :     try {
     298             : 
     299             :       //os << "---------------------------------------------------- Init (?) Minor Cycles ---------------------------------------------" << LogIO::POST;
     300             : 
     301        2468 :       itsImages = imstor;
     302             : 
     303             :       // If a starting model exists, this will initialize the ImageStore with it. Will do this only once.
     304        2468 :       setStartingModel();
     305             : 
     306             :       //itsIterDone is currently only used by automask code so move this to inside setAutomask
     307             :       //itsIterDone += itsLoopController.getIterDone();
     308             : 
     309             :       //      setupMask();
     310             : 
     311             :       Float masksum;
     312        2466 :       if( ! itsImages->hasMask() ) // i.e. if there is no existing mask to re-use...
     313         599 :         { masksum = -1.0;}
     314             :       else
     315             :         {
     316        1867 :           masksum = itsImages->getMaskSum();
     317        1863 :           itsImages->mask()->unlock();
     318             :         }
     319        2462 :       Bool validMask = ( masksum > 0 );
     320             :       //    os << LogIO::NORMAL3 << "****INITMINOR Masksum stuff "<< tim.real() << LogIO::POST;
     321             :       // tim.mark();
     322             : 
     323             :       // Calculate Peak Residual and Max Psf Sidelobe, and fill into SubIterBot.
     324        2462 :       Float peakresnomask = itsImages->getPeakResidual();
     325        2462 :       Float peakresinmask= validMask ? itsImages->getPeakResidualWithinMask() : peakresnomask;
     326             :       //os << LogIO::NORMAL3 << "****INITMINOR residual peak "<< tim.real() << LogIO::POST;
     327             :       //tim.mark();
     328        2462 :       itsLoopController.setPeakResidual( validMask ? peakresinmask : peakresnomask );
     329             :       //os << LogIO::NORMAL3 << "****INITMINOR OTHER residual peak "<< tim.real() << LogIO::POST;
     330             :       //tim.mark();
     331        2462 :       itsLoopController.setPeakResidualNoMask( peakresnomask );
     332        2462 :       itsLoopController.setMaxPsfSidelobe( itsImages->getPSFSidelobeLevel() );
     333             : 
     334             :       //re-calculate current nsigma threhold
     335             :       //os<<"Calling calcRobustRMS ....syndeconv."<<LogIO::POST;
     336        2462 :       Float nsigmathresh = 0.0;
     337        2462 :       Bool useautomask = ( itsAutoMaskAlgorithm=="multithresh" ? true : false);
     338        2462 :       Int iterdone = itsLoopController.getIterDone();
     339             : 
     340             :       //cerr << "INIT automask " << useautomask << " alg " << itsAutoMaskAlgorithm << " sigma " << itsNsigma  << endl;
     341        2462 :       if ( itsNsigma >0.0) {
     342         143 :         itsMaskHandler->setPBMaskLevel(itsPBMask);
     343         143 :         Array<Double> medians, robustrms;
     344             :         // 2 cases to use existing stats.
     345             :         // 1. automask has run and so the image statistics record has filled
     346             :         // or
     347             :         // 2. no automask but for the first cycle but already initial calcRMS has ran to avoid duplicate
     348             :         //
     349             : 
     350             :         //cerr << "useauto " << useautomask << " nfields " << itsRobustStats.nfields() << " iterdone " << iterdone << endl;
     351         278 :         if ((useautomask && itsRobustStats.nfields()) ||
     352         135 :             (!useautomask && iterdone==0 && itsRobustStats.nfields()) ) {
     353          30 :            os <<LogIO::DEBUG1<<"automask on: check the current stats"<<LogIO::POST;
     354             :            //os<< "itsRobustStats nfield="<< itsRobustStats.nfields() << LogIO::POST;;
     355          30 :            if (itsRobustStats.isDefined("medabsdevmed")) {
     356           2 :              Array<Double> mads;
     357           2 :              itsRobustStats.get(RecordFieldId("medabsdevmed"), mads);
     358           2 :              os<<LogIO::DEBUG1<<"Using robust rms from automask ="<< mads*1.4826 <<LogIO::POST;
     359           2 :              robustrms = mads*1.4826;
     360           2 :            }
     361          28 :            else if(itsRobustStats.isDefined("robustrms")) {
     362          28 :              itsRobustStats.get(RecordFieldId("robustrms"), robustrms);
     363             :            }
     364          30 :            itsRobustStats.get(RecordFieldId("median"), medians);
     365             : 
     366             :         }
     367             :        else { // do own stats calculation
     368         113 :           timer.mark();
     369             : 
     370         113 :           os<<LogIO::DEBUG1<<"Calling calcRobustRMS .. "<<LogIO::POST;
     371         113 :           robustrms = itsImages->calcRobustRMS(medians, itsPBMask, itsFastNoise);
     372             :           os<< LogIO::NORMAL << "time for calcRobustRMS:  real "<< timer.real() << "s ( user " << timer.user()
     373         113 :              <<"s, system "<< timer.system() << "s)" << LogIO::POST;
     374             :           //reset itsRobustStats
     375             :           //cerr << "medians " << medians << " pbmask " << itsPBMask << endl;
     376             :           try {
     377             :             //os<<"current content of itsRobustStats nfields=="<<itsRobustStats.nfields()<<LogIO::POST;
     378         113 :             itsRobustStats.define(RecordFieldId("robustrms"), robustrms);
     379         113 :             itsRobustStats.define(RecordFieldId("median"), medians);
     380             :           }
     381           0 :           catch(AipsError &x) {
     382           0 :             throw( AipsError("Error in storing the robust image statistics") );
     383           0 :           }
     384             : 
     385             :                 //cerr << this << " DOING robust " << itsRobustStats << endl;
     386             : 
     387             :        }
     388             : 
     389             :         /***
     390             :         Array<Double> robustrms =kitsImages->calcRobustRMS(medians, itsPBMask, itsFastNoise);
     391             :         // Before the first iteration the iteration parameters have not been
     392             :         // set in SIMinorCycleController
     393             :         // Use nsigma pass to SynthesisDeconvolver directly for now...
     394             :         //Float nsigma = itsLoopController.getNsigma();
     395             :         ***/
     396             :         Double minval, maxval;
     397         143 :         IPosition minpos, maxpos;
     398             :         //Double maxrobustrms = max(robustrms);
     399         143 :         if(robustrms.empty())
     400           0 :           throw(AipsError("No valid values to deconvolve"));
     401             :           
     402         143 :         minMax(minval, maxval, minpos, maxpos, robustrms);
     403             : 
     404             :         //Float nsigmathresh = nsigma * (Float)robustrms(IPosition(1,0));
     405             :         //nsigmathresh = itsNsigma * (Float)maxrobustrms;
     406         143 :         String msg="";
     407         143 :         if (useautomask) {
     408          12 :           nsigmathresh = (Float)(medians(maxpos)) + itsNsigma * (Float)maxval;
     409          12 :           msg+=" (nsigma*rms + median)";
     410             :         }
     411             :         else {
     412         131 :           nsigmathresh = itsNsigma * (Float)maxval;
     413             :         }
     414         143 :         os << "Current nsigma threshold (maximum along spectral channels ) ="<<nsigmathresh<< msg <<LogIO::POST;
     415         143 :       }
     416             : 
     417        2462 :       itsLoopController.setNsigmaThreshold(nsigmathresh);
     418        2462 :       itsLoopController.setPBMask(itsPBMask);
     419        2462 :       itsLoopController.setFullSummary(itsFullSummary);
     420             : 
     421        2462 :       if ( itsAutoMaskAlgorithm=="multithresh" && !initializeChanMaskFlag ) {
     422          46 :         IPosition maskshp = itsImages->mask()->shape();
     423          46 :         Int nchan = maskshp(3);
     424          46 :         itsChanFlag=Vector<Bool>(nchan,False);
     425          46 :         initializeChanMaskFlag=True;
     426             :         // also initialize posmask, which tracks only positive (emission)
     427             : 
     428          46 :         if(!itsPosMask){
     429             :           //itsPosMask = TempImage<Float> (maskshp, itsImages->mask()->coordinates(),SDMaskHandler::memoryToUse());
     430          46 :           itsPosMask=itsImages->tempworkimage();
     431             :           //you don't want to modify this here...
     432             :           //It is set to 0.0 in SIImageStore first time it is created.
     433             :           //itsPosMask->set(0);
     434          46 :           itsPosMask->unlock();
     435             :         }
     436          46 :       }
     437        2462 :       os<<LogIO::DEBUG1<<"itsChanFlag.shape="<<itsChanFlag.shape()<<LogIO::POST;
     438             : 
     439             :       /*
     440             :       Array<Double> rmss = itsImages->calcRobustRMS();
     441             :       AlwaysAssert( rmss.shape()[0]>0 , AipsError);
     442             :       cout  << "madRMS : " << rmss << "  with shape : " << rmss.shape() << endl;
     443             :       //itsLoopController.setMadRMS( rmss[0] );
     444             :       */
     445             : 
     446        2462 :       if( itsMaskSum != masksum || masksum == 0.0 ) // i.e. mask has changed.
     447             :         {
     448        1515 :           itsMaskSum = masksum;
     449        1515 :           itsLoopController.setMaskSum( masksum );
     450             :         }
     451             :       else // mask has not changed...
     452             :         {
     453         947 :           itsLoopController.setMaskSum( -1.0 );
     454             :         }
     455             : 
     456        2462 :       returnRecord = itsLoopController.getCycleInitializationRecord();
     457             :       //cerr << "INIT record " << returnRecord << endl;
     458             : 
     459             :       //      itsImages->printImageStats();
     460        2462 :       os << " Absolute Peak residual within mask : " << peakresinmask << ", over full image : " << peakresnomask  << LogIO::POST;
     461        2462 :       itsImages->releaseLocks();
     462             : 
     463        2462 :       os << LogIO::DEBUG2 << "Initialized minor cycle. Returning returnRec" << LogIO::POST;
     464             : 
     465           6 :     } catch(AipsError &x) {
     466           6 :       throw( AipsError("Error initializing the Minor Cycle for "  + itsImageName + " : "+x.getMesg()) );
     467           6 :     }
     468             : 
     469        4924 :     return returnRecord;
     470        2474 :   }
     471          15 :   void SynthesisDeconvolver::setChanFlag(const Vector<Bool>& chanflag){
     472             :     //ignore if it has not been given a size yet in initminorcycle
     473          15 :     if(itsChanFlag.nelements()==0)
     474           0 :       return;
     475          15 :     if(itsChanFlag.nelements() != chanflag.nelements())
     476           0 :       throw(AipsError("cannot set chan flags for different number of channels"));
     477          15 :     itsChanFlag =chanflag;
     478             : 
     479             :   }
     480         263 :   Vector<Bool> SynthesisDeconvolver::getChanFlag(){
     481         263 :     return itsChanFlag;
     482             :   }
     483          15 :   void SynthesisDeconvolver::setRobustStats(const Record& rec){
     484          15 :     itsRobustStats=Record();
     485          15 :     itsRobustStats=rec;
     486             : 
     487          15 :   }
     488         263 :   Record SynthesisDeconvolver::getRobustStats(){
     489         263 :     return itsRobustStats;
     490             :   }
     491             : 
     492           0 :   Record SynthesisDeconvolver::interactiveGUI(Record& iterRec)
     493             :   {
     494           0 :     LogIO os( LogOrigin("SynthesisDeconvolver","interactiveGUI",WHERE) );
     495           0 :     Record returnRecord;
     496             : 
     497             :     try {
     498             : 
     499             :       // Check that required parameters are present in the iterRec.
     500           0 :       Int niter=0,cycleniter=0,iterdone;
     501           0 :       Float threshold=0.0, cyclethreshold=0.0;
     502           0 :       if( iterRec.isDefined("niter") &&
     503           0 :           iterRec.isDefined("cycleniter") &&
     504           0 :           iterRec.isDefined("threshold") &&
     505           0 :           iterRec.isDefined("cyclethreshold") &&
     506           0 :           iterRec.isDefined("iterdone") )
     507             :         {
     508           0 :           iterRec.get("niter", niter);
     509           0 :           iterRec.get("cycleniter", cycleniter);
     510           0 :           iterRec.get("threshold", threshold);
     511           0 :           iterRec.get("cyclethreshold", cyclethreshold);
     512           0 :           iterRec.get("iterdone",iterdone);
     513             :         }
     514           0 :       else throw(AipsError("SD::interactiveGui() needs valid niter, cycleniter, threshold to start up."));
     515             :       
     516           0 :       if( ! itsImages ) itsImages = makeImageStore( itsImageName, itsNoRequireSumwt );
     517             :       
     518             :       //      SDMaskHandler masker;
     519           0 :       String strthresh = String::toString(threshold)+"Jy";
     520           0 :       String strcycthresh = String::toString(cyclethreshold)+"Jy";
     521             : 
     522           0 :       if( itsMaskString.length()>0 ) {
     523           0 :           itsMaskHandler->fillMask( itsImages, itsMaskString );
     524             :       }
     525             : 
     526           0 :       Int iterleft = niter - iterdone;
     527           0 :       if( iterleft<0 ) iterleft=0;
     528             : 
     529           0 :       Int stopcode = itsMaskHandler->makeInteractiveMask( itsImages, iterleft, cycleniter, strthresh, strcycthresh );
     530             : 
     531           0 :       Quantity qa;
     532           0 :       casacore::Quantity::read(qa,strthresh);
     533           0 :       threshold = qa.getValue(Unit("Jy"));
     534           0 :       casacore::Quantity::read(qa,strcycthresh);
     535           0 :       cyclethreshold = qa.getValue(Unit("Jy"));
     536             : 
     537           0 :       itsIsMaskLoaded=true;
     538             : 
     539           0 :       returnRecord.define( RecordFieldId("actioncode"), stopcode );
     540           0 :       returnRecord.define( RecordFieldId("niter"), iterdone + iterleft );
     541           0 :       returnRecord.define( RecordFieldId("cycleniter"), cycleniter );
     542           0 :       returnRecord.define( RecordFieldId("threshold"), threshold );
     543           0 :       returnRecord.define( RecordFieldId("cyclethreshold"), cyclethreshold );
     544             : 
     545           0 :     } catch(AipsError &x) {
     546           0 :       throw( AipsError("Error in Interactive GUI : "+x.getMesg()) );
     547           0 :     }
     548           0 :     return returnRecord;
     549           0 :   }
     550             : 
     551             : 
     552           5 :   void SynthesisDeconvolver::setMinorCycleControl(const Record& minorCycleControlRec){
     553             :     //Don't know what itsloopcontroller does not need a const record;
     554           5 :     Record lala=minorCycleControlRec;
     555           5 :     itsLoopController.setCycleControls(lala);
     556             : 
     557           5 :   }
     558             : 
     559         934 :   Record SynthesisDeconvolver::executeMinorCycle(Record& minorCycleControlRec)
     560             :   {
     561             :     // LogIO os( LogOrigin("SynthesisDeconvolver","executeMinorCycle",WHERE) );
     562             : 
     563             : 
     564             :     //    itsImages->printImageStats();
     565         934 :     SynthesisUtilMethods::getResource("Start Deconvolver");
     566             :     ///if cube execute cube deconvolution...check on residual shape as itsimagestore return 0 shape sometimes
     567         934 :     if(!itsImages)
     568           0 :       throw(AipsError("Initminor Cycle has not been called yet"));
     569         934 :     if(itsImages->residual()->shape()[3]> 1){
     570         253 :      return  executeCubeMinorCycle(minorCycleControlRec);
     571             :     }
     572             : 
     573             :     //  os << "---------------------------------------------------- Run Minor Cycle Iterations  ---------------------------------------------" << LogIO::POST;
     574         681 :     return executeCoreMinorCycle(minorCycleControlRec);
     575             :     SynthesisUtilMethods::getResource("End Deconvolver");
     576             :   }
     577         934 :   Record SynthesisDeconvolver::executeCoreMinorCycle(Record& minorCycleControlRec)
     578             :   {
     579             : 
     580         934 :     Record returnRecord;
     581             :     try {
     582             :       //      if ( !itsIsInteractive ) setAutoMask();
     583             :       //cerr << "MINORCYCLE control Rec " << minorCycleControlRec << endl;
     584         934 :       itsLoopController.setCycleControls(minorCycleControlRec);
     585         934 :       bool automaskon (false);
     586         934 :       if (itsAutoMaskAlgorithm=="multithresh") {
     587          34 :         automaskon=true;
     588             :       }
     589             :       //itsDeconvolver->deconvolve( itsLoopController, itsImages, itsDeconvolverId, automaskon, itsFastNoise );
     590             :       // include robust stats rec
     591         942 :       itsDeconvolver->deconvolve( itsLoopController, itsImages, itsDeconvolverId, automaskon, itsFastNoise, itsRobustStats, itsFullSummary );
     592             : 
     593         926 :       returnRecord = itsLoopController.getCycleExecutionRecord();
     594             : 
     595             :       //scatterModel(); // This is a no-op for the single-node case.
     596             : 
     597         926 :       itsImages->releaseLocks();
     598             : 
     599           8 :     } catch(AipsError &x) {
     600           8 :       throw( AipsError("Error in running Minor Cycle : "+x.getMesg()) );
     601           8 :     }
     602             : 
     603             : 
     604             : 
     605         926 :     return returnRecord;
     606           8 :   }
     607         263 :   Record SynthesisDeconvolver::executeCubeMinorCycle(Record& minorCycleControlRec, const Int AutoMaskFlag)
     608             :   {
     609         526 :         LogIO os( LogOrigin("SynthesisDeconvolver","executeCubeMinorCycle",WHERE) );
     610         263 :     Record returnRecord;
     611         263 :     Int doAutoMask=AutoMaskFlag;
     612             : 
     613         263 :     SynthesisUtilMethods::getResource("Start Deconvolver");
     614             : 
     615             :     try {
     616             :       //      if ( !itsIsInteractive ) setAutoMask();
     617         263 :       if(doAutoMask < 1){
     618         253 :         itsLoopController.setCycleControls(minorCycleControlRec);
     619             :       }
     620          10 :       else if(doAutoMask==1){
     621          10 :         minorCycleControlRec=itsPreviousIterBotRec_p;
     622             :       }
     623         263 :       CubeMinorCycleAlgorithm cmc;
     624             :       //casa::applicator.defineAlgorithm(cmc);
     625             :       ///argv and argc are needed just to callthe right overloaded init
     626         263 :       Int argc=1;
     627         263 :       char **argv=nullptr;
     628         263 :       applicator.init(argc, argv);
     629         263 :       if(applicator.isController()){
     630         263 :         os << ((AutoMaskFlag != 1) ? "---------------------------------------------------- Run Minor Cycle Iterations  ---------------------------------------------" : "---------------------------------------------------- Run Automask  ---------------------------------------------" )<< LogIO::POST;
     631             :         /*{///TO BE REMOVED
     632             :           LatticeExprNode le( sum( *(itsImages->mask()) ) );
     633             :           os << LogIO::WARN << "#####Sum of mask BEFORE minor cycle " << le.getFloat() << endl;
     634             :             }
     635             :         */
     636         263 :         Timer tim;
     637         263 :         tim.mark();
     638             :         //itsImages->printImageStats();
     639             :         // Add itsIterdone to be sent to child processes ...needed for automask
     640             :         //cerr << "before record " << itsIterDone << " loopcontroller " << itsLoopController.getIterDone() << endl;
     641         263 :         minorCycleControlRec.define("iterdone", itsIterDone);
     642         263 :         if(doAutoMask < 0) // && itsPreviousIterBotRec_p.nfields() >0)
     643         253 :           doAutoMask=0;
     644         263 :         minorCycleControlRec.define("onlyautomask",doAutoMask);
     645         263 :         if(itsPosMask){
     646          15 :           minorCycleControlRec.define("posmaskname", itsPosMask->name());
     647             :         }
     648             :         //Int numprocs = applicator.numProcs();
     649             :         //cerr << "Number of procs: " << numprocs << endl;
     650             : 
     651         263 :           Int numchan=itsImages->residual()->shape()[3];
     652         263 :           Vector<Int> startchans;
     653         263 :           Vector<Int> endchans;
     654         263 :           Int numblocks=numblockchans(startchans, endchans);
     655         263 :           String psfname=itsImages->psf()->name();
     656             : 
     657         263 :           Float psfsidelobelevel=itsImages->getPSFSidelobeLevel();
     658         263 :           String residualname=itsImages->residual()->name();
     659         263 :           String maskname=itsImages->mask()->name();
     660         263 :           String modelname=itsImages->model()->name();
     661             :           ////Need the pb too as calcrobustrms in SynthesisDeconvolver uses it
     662         263 :           String pbname="";
     663         263 :           if(itsImages->hasPB())
     664         263 :             pbname=itsImages->pb()->name();
     665         263 :           itsImages->releaseLocks();
     666             :           ///in lieu of = operator go via record
     667             :           // need to create a proper = operator for SynthesisParamsDeconv
     668         263 :           SynthesisParamsDeconv decpars;
     669             :           ///Will have to create a = operator...right now kludging
     670             :           ///from record has a check that has to be bypassed for just the
     671             :           /// usage as a = operator
     672             :           {
     673         263 :             String tempMaskString= itsDecPars.maskString;
     674         263 :             itsDecPars.maskString="";
     675         263 :             decpars.fromRecord(itsDecPars.toRecord());
     676             :             //return itsDecPars back to its original state
     677         263 :             itsDecPars.maskString=tempMaskString;
     678         263 :           }
     679             :           ///remove starting model as already dealt with in this deconvolver
     680         263 :           decpars.startModel="";
     681             :           ///masking is dealt already by this deconvolver so mask image
     682             :           //is all that is needed which is sent as maskname to subdeconvolver
     683         263 :           decpars.maskString="";
     684         263 :           (decpars.maskList).resize();
     685         263 :           Record decParsRec = decpars.toRecord();
     686             : 
     687             :           /////Now we loop over channels and deconvolve each
     688             :           ///If we do want to do block of channels rather than 1 channel
     689             :           ///at a time chanRange can take that and the trigger to call this
     690             :           ///function in executeMinorCycle has to change.
     691         263 :           Int rank(0);
     692             :           Bool assigned;
     693         263 :           Bool allDone(false);
     694         263 :           Vector<Int> chanRange(2);
     695             :           //Record beamsetRec;
     696         263 :           Vector<Bool> retvals(numblocks, False);
     697         263 :           Vector<Bool> chanFlag(0);
     698         263 :           if(itsChanFlag.nelements()==0){
     699         212 :             itsChanFlag.resize(numchan);
     700         212 :             itsChanFlag.set(False);
     701             :           }
     702         263 :           Record chanflagRec;
     703         263 :           Int indexofretval=0;
     704         526 :           for (Int k=0; k < numblocks; ++k) {
     705             :             //os << LogIO::DEBUG1 << "deconvolving channel "<< k << LogIO::POST;
     706         263 :             assigned=casa::applicator.nextAvailProcess(cmc, rank);
     707             :             //cerr << "assigned "<< assigned << endl;
     708         263 :             while(!assigned) {
     709             :               //cerr << "SErial ? " << casa::applicator.isSerial() << endl;
     710           0 :               rank = casa::applicator.nextProcessDone(cmc, allDone);
     711             :               //cerr << "while rank " << rank << endl;
     712             :               //receiving output of CubeMinorCycleAlgorithm::put
     713             :               //#1
     714           0 :               Vector<Int> chanRangeProcessed;
     715           0 :               casa::applicator.get(chanRangeProcessed);
     716             :               //#2
     717             : 
     718           0 :               Record chanflagRec;
     719           0 :               casa::applicator.get(chanflagRec);
     720             : 
     721             :               //#3
     722           0 :               Record retval;
     723           0 :               casa::applicator.get(retval);
     724             : 
     725           0 :               Vector<Bool> retchanflag;
     726           0 :               chanflagRec.get("chanflag", retchanflag);
     727           0 :               if(retchanflag.nelements() >0)
     728           0 :                 itsChanFlag(Slice(chanRangeProcessed[0], chanRangeProcessed[1]-chanRangeProcessed[0]+1))=retchanflag;
     729           0 :               Record substats=chanflagRec.asRecord("statsrec");
     730           0 :               setSubsetRobustStats(substats, chanRangeProcessed[0], chanRangeProcessed[1], numchan);
     731             : 
     732           0 :               retvals(indexofretval)=(retval.nfields() > 0);
     733           0 :               ++indexofretval;
     734             :               ///might need to merge these retval
     735           0 :               if(doAutoMask <1)
     736           0 :                 mergeReturnRecord(retval, returnRecord, chanRangeProcessed[0]);
     737             :               /*if(retval.nfields())
     738             :                 cerr << k << "deconv rank " << rank << " successful " << endl;
     739             :                else
     740             :                 cerr << k << "deconv rank " << rank << " failed " << endl;
     741             :               */
     742             :               //cerr <<"rank " << rank << " return rec "<< retval << endl;
     743           0 :               assigned = casa::applicator.nextAvailProcess(cmc, rank);
     744             : 
     745           0 :             }
     746             : 
     747             :             ///send process info
     748             :             // put dec sel params #1
     749         263 :             applicator.put(decParsRec);
     750             :             // put itercontrol  params #2
     751         263 :             applicator.put(minorCycleControlRec);
     752             :             // put which channel to process #3
     753         263 :             chanRange[0]=startchans[k];  chanRange[1]=endchans[k];
     754         263 :             applicator.put(chanRange);
     755             :             // psf  #4
     756         263 :             applicator.put(psfname);
     757             :             // residual #5
     758         263 :             applicator.put(residualname);
     759             :             // model #6
     760         263 :             applicator.put(modelname);
     761             :             // mask #7
     762         263 :             applicator.put(maskname);
     763             :             //pb #8
     764         263 :             applicator.put(pbname);
     765             :             //#9 psf side lobe
     766         263 :             applicator.put(psfsidelobelevel);
     767             :             //# put chanflag
     768         263 :             chanFlag.resize();
     769         263 :             chanFlag=itsChanFlag(IPosition(1, chanRange[0]), IPosition(1, chanRange[1]));
     770             : 
     771         263 :             chanflagRec.define("chanflag", chanFlag);
     772         263 :             Record statrec=getSubsetRobustStats(chanRange[0], chanRange[1]);
     773         263 :             chanflagRec.defineRecord("statsrec", statrec);
     774         263 :             applicator.put(chanflagRec);
     775             :             /// Tell worker to process it
     776         263 :             applicator.apply(cmc);
     777             : 
     778         263 :           }
     779             :           // Wait for all outstanding processes to return
     780         263 :           rank = casa::applicator.nextProcessDone(cmc, allDone);
     781         526 :           while (!allDone) {
     782             : 
     783         263 :             Vector<Int> chanRangeProcessed;
     784         263 :             casa::applicator.get(chanRangeProcessed);
     785         263 :             Record chanflagRec;
     786         263 :             casa::applicator.get(chanflagRec);
     787         263 :             Record retval;
     788         263 :             casa::applicator.get(retval);
     789         263 :             Vector<Bool> retchanflag;
     790         263 :             chanflagRec.get("chanflag", retchanflag);
     791         263 :             if(retchanflag.nelements() >0)
     792          15 :               itsChanFlag(Slice(chanRangeProcessed[0], chanRangeProcessed[1]-chanRangeProcessed[0]+1))=retchanflag;
     793         263 :             Record substats=chanflagRec.asRecord("statsrec");
     794         263 :             setSubsetRobustStats(substats, chanRangeProcessed[0], chanRangeProcessed[1], numchan);
     795         263 :             retvals(indexofretval)=(retval.nfields() > 0);
     796         263 :             ++indexofretval;
     797         263 :             if(doAutoMask < 1)
     798         253 :               mergeReturnRecord(retval, returnRecord, chanRangeProcessed[0]);
     799         263 :             if(retval.nfields() >0)
     800             :               //cerr << "deconv remainder rank " << rank << " successful " << endl;
     801         263 :               cerr << "";
     802             :             else
     803           0 :               cerr << "deconv remainder rank " << rank << " failed " << endl;
     804             : 
     805         263 :             rank = casa::applicator.nextProcessDone(cmc, allDone);
     806         263 :             if(casa::applicator.isSerial())
     807         263 :               allDone=true;
     808             : 
     809         263 :           }
     810             : 
     811         263 :           if(anyEQ(retvals, False))
     812           0 :             throw(AipsError("one of more section of the cube failed in deconvolution"));
     813         263 :           if(doAutoMask < 1){
     814         253 :             itsLoopController.incrementMinorCycleCount(returnRecord.asInt("iterdone"));
     815         253 :             itsIterDone+=returnRecord.asInt("iterdone");
     816             :           }
     817         263 :           itsPreviousIterBotRec_p=Record();
     818         263 :           itsPreviousIterBotRec_p=minorCycleControlRec;
     819             :           /*{///TO BE REMOVED
     820             :           LatticeExprNode le( sum( *(itsImages->mask()) ) );
     821             :           os << LogIO::WARN << "#####Sum of mask AFTER minor cycle " << le.getFloat()  << "loopcontroller iterdeconv " << itsLoopController.getIterDone() << endl;
     822             :           }*/
     823             : 
     824         263 :       }///end of if controller
     825             :       /////////////////////////////////////////////////
     826             : 
     827             :       //scatterModel(); // This is a no-op for the single-node case.
     828             : 
     829         263 :       itsImages->releaseLocks();
     830             : 
     831         263 :     } catch(AipsError &x) {
     832             :       //MPI_Abort(MPI_COMM_WORLD, 6);
     833           0 :       throw( AipsError("Error in running Minor Cycle : "+x.getMesg()) );
     834           0 :     }
     835             : 
     836         263 :     SynthesisUtilMethods::getResource("End Deconvolver");
     837             : 
     838         526 :     return returnRecord;
     839         263 :   }
     840             : 
     841             :   // Restore Image.
     842         733 :   void SynthesisDeconvolver::restore()
     843             :   {
     844        1466 :     LogIO os( LogOrigin("SynthesisDeconvolver","restoreImage",WHERE) );
     845             : 
     846         733 :     if( ! itsImages )
     847             :       {
     848           7 :         itsImages = makeImageStore( itsImageName, itsNoRequireSumwt );
     849             :       }
     850             : 
     851         733 :     SynthesisUtilMethods::getResource("Restoration");
     852             : 
     853         733 :     itsDeconvolver->restore(itsImages);
     854         733 :     itsImages->releaseLocks();
     855             : 
     856         733 :   }
     857             : 
     858         253 :   void SynthesisDeconvolver::mergeReturnRecord(const Record& inRec, Record& outRec, const Int chan){
     859             : 
     860             :     ///Something has to be done about what is done in SIIterBot_state::mergeMinorCycleSummary if it is needed
     861             :     //int nSummaryFields = SIMinorCycleController::useSmallSummaryminor() ? 6 : SIMinorCycleController::nSummaryFields; // temporary CAS-13683 workaround
     862             :     //int nSummaryFields = SIMinorCycleController::nSummaryFields; // temporary CAS-13683 workaround
     863         253 :     int nSummaryFields = !itsFullSummary ? 6 : SIMinorCycleController::nSummaryFields; // temporary CAS-13683 workaround
     864             : 
     865         253 :     Matrix<Double> summaryminor(nSummaryFields,0);
     866         253 :     if(outRec.isDefined("summaryminor"))
     867           0 :       summaryminor=Matrix<Double>(outRec.asArrayDouble("summaryminor"));
     868         253 :     Matrix<Double> subsummaryminor;
     869         253 :     if(inRec.isDefined("summaryminor"))
     870         253 :       subsummaryminor=Matrix<Double>(inRec.asArrayDouble("summaryminor"));
     871         253 :     if(subsummaryminor.nelements() !=0){
     872             :       ///The 6th element is supposed to be the subimage id
     873         253 :       subsummaryminor.row(5)= subsummaryminor.row(5)+(Double(chan));
     874         253 :       Matrix<Double> newsummary(nSummaryFields, summaryminor.shape()[1]+subsummaryminor.shape()[1]);
     875         253 :       Int ocol=0;
     876         253 :       for (Int col=0; col< summaryminor.shape()[1]; ++col, ++ocol)
     877           0 :         newsummary.column(ocol)=summaryminor.column(col);
     878        2678 :       for (Int col=0; col< subsummaryminor.shape()[1]; ++col, ++ocol)
     879        2425 :         newsummary.column(ocol)=subsummaryminor.column(col);
     880         253 :       summaryminor.resize(newsummary.shape());
     881         253 :       summaryminor=newsummary;
     882         253 :     }
     883         253 :     outRec.define("summaryminor", summaryminor);
     884             :     //cerr << "inRec summ minor " << inRec.asArrayDouble("summaryminor") << endl;
     885             :     //cerr << "outRec summ minor " << summaryminor << endl;
     886         253 :     outRec.define("iterdone", Int(inRec.asInt("iterdone")+ (outRec.isDefined("iterdone") ? outRec.asInt("iterdone"): Int(0))));
     887         253 :     outRec.define("maxcycleiterdone", outRec.isDefined("maxcycleiterdone") ? max(inRec.asInt("maxcycleiterdone"), outRec.asInt("maxcycleiterdone")) :inRec.asInt("maxcycleiterdone")) ;
     888             : 
     889         253 :     outRec.define("peakresidual", outRec.isDefined("peakresidual") ? max(inRec.asFloat("peakresidual"), outRec.asFloat("peakresidual")) :inRec.asFloat("peakresidual")) ;
     890             : 
     891             :     ///is not necessarily defined it seems
     892         253 :     Bool updatedmodelflag=False;
     893         253 :     if(inRec.isDefined("updatedmodelflag"))
     894         253 :       inRec.get("updatedmodelflag", updatedmodelflag);
     895         253 :     outRec.define("updatedmodelflag", outRec.isDefined("updatedmodelflag") ? updatedmodelflag || outRec.asBool("updatedmodelflag") : updatedmodelflag) ;
     896             : 
     897             : 
     898             : 
     899         253 :   }
     900             :   // get channel blocks
     901         263 :   Int SynthesisDeconvolver::numblockchans(Vector<Int>& startchans, Vector<Int>& endchans){
     902         263 :     Int nchan=itsImages->residual()->shape()[3];
     903             :     //roughly 8e6 pixel to deconvolve per lock/process is a  minimum
     904         263 :     Int optchan= 8e6/(itsImages->residual()->shape()[0])/(itsImages->residual()->shape()[1]);
     905             :     // cerr << "OPTCHAN" << optchan  << endl;
     906         263 :     if(optchan < 10) optchan=10;
     907         263 :     Int nproc= applicator.numProcs() < 2 ? 1 : applicator.numProcs()-1;
     908             :     /*if(nproc==1){
     909             :       startchans.resize(1);
     910             :       endchans.resize(1);
     911             :       startchans[0]=0;
     912             :       endchans[0]=nchan-1;
     913             :       return 1;
     914             :       }
     915             :     */
     916         263 :     Int blksize= nchan/nproc > optchan ? optchan : Int( std::floor(Float(nchan)/Float(nproc)));
     917         263 :     if(blksize< 1) blksize=1;
     918         263 :     Int nblk=Int(nchan/blksize);
     919         263 :     startchans.resize(nblk);
     920         263 :     endchans.resize(nblk);
     921         526 :     for (Int k=0; k < nblk; ++k){
     922         263 :       startchans[k]= k*blksize;
     923         263 :       endchans[k]=(k+1)*blksize-1;
     924             :     }
     925         263 :     if(endchans[nblk-1] < (nchan-1)){
     926           0 :       startchans.resize(nblk+1,True);
     927           0 :       startchans[nblk]=endchans[nblk-1]+1;
     928           0 :       endchans.resize(nblk+1,True);
     929           0 :       endchans[nblk]=nchan-1;
     930           0 :       ++nblk;
     931             :     }
     932             :     //cerr << "nblk " << nblk << " beg " << startchans << " end " << endchans << endl;
     933         263 :     return nblk;
     934             :   }
     935             : 
     936             :   // pbcor Image.
     937          43 :   void SynthesisDeconvolver::pbcor()
     938             :   {
     939          86 :     LogIO os( LogOrigin("SynthesisDeconvolver","pbcor",WHERE) );
     940             : 
     941          43 :     if( ! itsImages )
     942             :       {
     943           0 :         itsImages = makeImageStore( itsImageName, itsNoRequireSumwt );
     944             :       }
     945             : 
     946          43 :     itsDeconvolver->pbcor(itsImages);
     947          43 :     itsImages->releaseLocks();
     948             : 
     949          43 :   }
     950             : 
     951             : 
     952             : 
     953             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     954             :   ////    Internal Functions start here.  These are not visible to the tool layer.
     955             :   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     956             : 
     957         797 :   std::shared_ptr<SIImageStore> SynthesisDeconvolver::makeImageStore( String imagename, Bool noRequireSumwt )
     958             :   {
     959         797 :     std::shared_ptr<SIImageStore> imstore;
     960         797 :     if( itsDeconvolver->getAlgorithmName() == "mtmfs" )
     961         148 :       {  imstore.reset( new SIImageStoreMultiTerm( imagename, itsDeconvolver->getNTaylorTerms(), true, noRequireSumwt ) ); }
     962             :     else
     963         649 :       {  imstore.reset( new SIImageStore( imagename, true, noRequireSumwt ) ); }
     964             : 
     965         797 :     return imstore;
     966             : 
     967           0 :   }
     968             : 
     969             : 
     970             :   // #############################################
     971             :   // #############################################
     972             :   // #############################################
     973             :   // #############################################
     974             : 
     975             :   // Set a starting model.
     976        2468 :   void SynthesisDeconvolver::setStartingModel()
     977             :   {
     978        4936 :     LogIO os( LogOrigin("SynthesisDeconvolver","setStartingModel",WHERE) );
     979             : 
     980        2468 :     if(itsAddedModel==true) {return;}
     981             : 
     982             :     try
     983             :       {
     984             : 
     985         908 :         if( itsStartingModelNames.nelements()>0 && itsImages )
     986             :           {
     987             :             //      os << "Setting " << itsStartingModelNames << " as starting model for deconvolution " << LogIO::POST;
     988          11 :             itsImages->setModelImage( itsStartingModelNames );
     989             :           }
     990             : 
     991         906 :         itsAddedModel=true;
     992             : 
     993             :       }
     994           2 :     catch(AipsError &x)
     995             :       {
     996           2 :         throw( AipsError("Error in setting  starting model for deconvolution: "+x.getMesg()) );
     997           2 :       }
     998             : 
     999        2468 :   }
    1000             : 
    1001             :   // Set mask
    1002        1414 :   Bool SynthesisDeconvolver::setupMask()
    1003             :   {
    1004             : 
    1005             :     ////Remembet this has to be called only after initMinorCycle
    1006        2828 :     LogIO os( LogOrigin("SynthesisDeconvolver","setupMask",WHERE) );
    1007        1414 :     if(!itsImages)
    1008           0 :       throw(AipsError("Initminor Cycle has not been called yet"));
    1009        1414 :     Bool maskchanged=False;
    1010             :     //debug
    1011        1414 :     if( itsIsMaskLoaded==false ) {
    1012             :       // use mask(s)
    1013         660 :       if(  itsMaskList[0] != "" || itsMaskType == "pb" || itsAutoMaskAlgorithm != "" ) {
    1014             :         // Skip automask for non-interactive mode.
    1015         128 :         if ( itsAutoMaskAlgorithm != "") { // && itsIsInteractive) {
    1016          52 :           os << "[" << itsImages->getName() << "] Setting up an auto-mask"<<  ((itsPBMask>0.0)?" within PB mask limit ":"") << LogIO::POST;
    1017             :           ////For Cubes this is done in CubeMinorCycle
    1018             :           //cerr << this << "SETUP mask " << itsRobustStats << endl;
    1019          52 :           if(itsImages->residual()->shape()[3] ==1)
    1020          42 :             setAutoMask();
    1021          10 :           else if((itsImages->residual()->shape()[3] >1)){
    1022          10 :             Record dummy;
    1023          10 :             executeCubeMinorCycle(dummy, 1);
    1024          10 :           }
    1025             :           /***
    1026             :           if ( itsPBMask > 0.0 ) {
    1027             :             itsMaskHandler->autoMaskWithinPB( itsImages, itsAutoMaskAlgorithm, itsMaskThreshold, itsFracOfPeak, itsMaskResolution, itsMaskResByBeam, itsPBMask);
    1028             :           }
    1029             :           else {
    1030             :             cerr<<"automask by automask.."<<endl;
    1031             :             itsMaskHandler->autoMask( itsImages, itsAutoMaskAlgorithm, itsMaskThreshold, itsFracOfPeak, itsMaskResolution, itsMaskResByBeam);
    1032             :           }
    1033             :           ***/
    1034             :         }
    1035             :         //else if( itsMaskType=="user" && itsMaskList[0] != "" ) {
    1036         128 :         if( itsMaskType=="user" && itsMaskList[0] != "" ) {
    1037          63 :           os << "[" << itsImages->getName() << "] Setting up a mask from " << itsMaskList  <<  ((itsPBMask>0.0)?" within PB mask limit ":"") << LogIO::POST;
    1038             : 
    1039          63 :           itsMaskHandler->fillMask( itsImages, itsMaskList);
    1040          63 :           if( itsPBMask > 0.0 ) {
    1041           7 :             itsMaskHandler->makePBMask(itsImages, itsPBMask, True);
    1042             :           }
    1043             :         }
    1044          65 :         else if( itsMaskType=="pb") {
    1045          13 :           os << "[" << itsImages->getName() << "] Setting up a PB based mask" << LogIO::POST;
    1046          18 :           itsMaskHandler->makePBMask(itsImages, itsPBMask);
    1047             :         }
    1048             : 
    1049         123 :         os << "----------------------------------------------------------------------------------------------------------------------------------------" << LogIO::POST;
    1050             : 
    1051             :       } else {
    1052             : 
    1053             :         // new im statistics creates an empty mask and need to take care of that case
    1054         532 :         Bool emptyMask(False);
    1055         532 :         if( itsImages->hasMask() )
    1056             :           {
    1057             :               // CAS-14203 - Check if mask is empty AND user didn't specify an empty mask
    1058          36 :             if (itsImages->getMaskSum()==0.0 && itsMaskList[0] != "") {
    1059           0 :               emptyMask=True;
    1060             :             }
    1061             :           }
    1062         532 :         if( ! itsImages->hasMask() || emptyMask ) // i.e. if there is no existing mask to re-use...
    1063             :           {
    1064         496 :             LatticeLocker lock1 (*(itsImages->mask()), FileLocker::Write);
    1065         496 :             if( itsIsInteractive ) itsImages->mask()->set(0.0);
    1066         496 :             else itsImages->mask()->set(1.0);
    1067         496 :             os << "[" << itsImages->getName() << "] Initializing new mask to " << (itsIsInteractive?"0.0 for interactive drawing":"1.0 for the full image") << LogIO::POST;
    1068         496 :           }
    1069             :         else {
    1070          36 :           os << "[" << itsImages->getName() << "] Initializing to existing mask" << LogIO::POST;
    1071             :         }
    1072             : 
    1073             :       }
    1074             : 
    1075             :       // If anything other than automasking, don't re-make the mask here.
    1076         655 :       if ( itsAutoMaskAlgorithm == "" )
    1077         603 :         {       itsIsMaskLoaded=true; }
    1078             : 
    1079             : 
    1080             :       // Get the number of mask pixels (sum) and send to the logger.
    1081         655 :       Float masksum = itsImages->getMaskSum();
    1082         655 :       Float npix = (itsImages->getShape()).product();
    1083             : 
    1084             :       //Int npix2 = 20000*20000*16000*4;
    1085             :       //Float npix2f = 20000*20000*16000*4;
    1086             : 
    1087             :       //cout << " bigval : " << npix2 << " and " << npix2f << endl;
    1088             : 
    1089         655 :       os << "[" << itsImages->getName() << "] Number of pixels in the clean mask : " << masksum << " out of a total of " << npix << " pixels. [ " << 100.0 * masksum/npix << " % ]" << LogIO::POST;
    1090             : 
    1091         655 :       maskchanged=True;
    1092             :     }
    1093             :     else {
    1094             :     }
    1095             : 
    1096        1409 :     itsImages->mask()->unlock();
    1097        1409 :     return maskchanged;
    1098        1414 : }
    1099             : 
    1100          52 :   void SynthesisDeconvolver::setAutoMask()
    1101             :   {
    1102             :      //modify mask using automask otherwise no-op
    1103          52 :      if ( itsAutoMaskAlgorithm != "" )  {
    1104          52 :        itsIterDone += itsLoopController.getIterDone();
    1105             : 
    1106             : 
    1107             : 
    1108          52 :        Bool isThresholdReached = itsLoopController.isThresholdReached();
    1109             :              //cerr << this << " setAuto " << itsRobustStats << endl;
    1110         104 :        LogIO os( LogOrigin("SynthesisDeconvolver","setAutoMask",WHERE) );
    1111          52 :        os << "Generating AutoMask" << LogIO::POST;
    1112             :        //os << LogIO::WARN << "#####ItsIterDone value " << itsIterDone << endl;
    1113             : 
    1114             :        //os << "itsMinPercentChnage = " << itsMinPercentChange<< LogIO::POST;
    1115             :        //cerr << "SUMa of chanFlag before " << ntrue(itsChanFlag) << endl;
    1116          52 :        if ( itsPBMask > 0.0 ) {
    1117             :          //itsMaskHandler->autoMaskWithinPB( itsImages, itsPosMask, itsIterDone, itsChanFlag, itsAutoMaskAlgorithm, itsMaskThreshold, itsFracOfPeak, itsMaskResolution, itsMaskResByBeam, itsNMask, itsAutoAdjust,  itsSidelobeThreshold, itsNoiseThreshold, itsLowNoiseThreshold, itsNegativeThreshold,itsCutThreshold, itsSmoothFactor, itsMinBeamFrac, itsGrowIterations, itsDoGrowPrune, itsMinPercentChange, itsVerbose, itsFastNoise, isThresholdReached, itsPBMask);
    1118             :          //pass robust stats
    1119           0 :          itsMaskHandler->autoMaskWithinPB( itsImages, *itsPosMask, itsIterDone, itsChanFlag, itsRobustStats, itsAutoMaskAlgorithm, itsMaskThreshold, itsFracOfPeak, itsMaskResolution, itsMaskResByBeam, itsNMask, itsAutoAdjust,  itsSidelobeThreshold, itsNoiseThreshold, itsLowNoiseThreshold, itsNegativeThreshold,itsCutThreshold, itsSmoothFactor, itsMinBeamFrac, itsGrowIterations, itsDoGrowPrune, itsMinPercentChange, itsVerbose, itsFastNoise, isThresholdReached, itsPBMask);
    1120             :        }
    1121             :        else {
    1122             :          //itsMaskHandler->autoMask( itsImages, itsPosMask, itsIterDone, itsChanFlag,itsAutoMaskAlgorithm, itsMaskThreshold, itsFracOfPeak, itsMaskResolution, itsMaskResByBeam, itsNMask, itsAutoAdjust, itsSidelobeThreshold, itsNoiseThreshold, itsLowNoiseThreshold, itsNegativeThreshold, itsCutThreshold, itsSmoothFactor, itsMinBeamFrac, itsGrowIterations, itsDoGrowPrune, itsMinPercentChange, itsVerbose, itsFastNoise, isThresholdReached );
    1123             : 
    1124             :         // pass robust stats
    1125          52 :         itsMaskHandler->autoMask( itsImages, *itsPosMask, itsIterDone, itsChanFlag, itsRobustStats, itsAutoMaskAlgorithm, itsMaskThreshold, itsFracOfPeak, itsMaskResolution, itsMaskResByBeam, itsNMask, itsAutoAdjust, itsSidelobeThreshold, itsNoiseThreshold, itsLowNoiseThreshold, itsNegativeThreshold, itsCutThreshold, itsSmoothFactor, itsMinBeamFrac, itsGrowIterations, itsDoGrowPrune, itsMinPercentChange, itsVerbose, itsFastNoise, isThresholdReached );
    1126             :        }
    1127             :        //cerr <<this << " SETAutoMask " << itsRobustStats << endl;
    1128             :        //cerr << "SUM of chanFlag AFTER " << ntrue(itsChanFlag) << endl;
    1129          52 :      }
    1130          52 :   }
    1131             : 
    1132             :   // check if restoring beam is reasonable
    1133         571 :   void SynthesisDeconvolver::checkRestoringBeam()
    1134             :   {
    1135        1142 :     LogIO os( LogOrigin("SynthesisDeconvolver","checkRestoringBeam",WHERE) );
    1136             :     //check for a bad restoring beam
    1137         571 :     GaussianBeam beam;
    1138             :     
    1139         571 :     if( ! itsImages ) itsImages = makeImageStore( itsImageName, itsNoRequireSumwt );
    1140         571 :     ImageInfo psfInfo = itsImages->psf()->imageInfo();
    1141         571 :     if (psfInfo.hasSingleBeam()) {
    1142         345 :       beam = psfInfo.restoringBeam();
    1143             :     }
    1144         226 :     else if (psfInfo.hasMultipleBeams() && itsUseBeam=="common") {
    1145           9 :       beam = CasaImageBeamSet(psfInfo.getBeamSet()).getCommonBeam();
    1146             :     }
    1147         571 :     Double beammaj = beam.getMajor(Unit("arcsec"));
    1148         571 :     Double beammin = beam.getMinor(Unit("arcsec"));
    1149         571 :     if (std::isinf(beammaj) || std::isinf(beammin)) {
    1150           0 :       String msg;
    1151           0 :       if (itsUseBeam=="common") {
    1152           0 :         msg+="Bad restoring beam using the common beam (at least one of the beam axes has an infinite size)  ";
    1153           0 :         throw(AipsError(msg));
    1154             :       }
    1155           0 :     }
    1156         571 :     itsImages->releaseLocks();
    1157         571 :   }
    1158             : 
    1159             :   // This is for interactive-clean.
    1160           0 :   void SynthesisDeconvolver::getCopyOfResidualAndMask( TempImage<Float> &/*residual*/,
    1161             :                                            TempImage<Float> &/*mask*/ )
    1162             :   {
    1163             :     // Actually all I think we need here are filenames JSK 12/12/12
    1164             :     // resize/shape and copy the residual image and mask image to these in/out variables.
    1165             :     // Allocate Memory here.
    1166           0 :   }
    1167           0 :   void SynthesisDeconvolver::setMask( TempImage<Float> &/*mask*/ )
    1168             :   {
    1169             :     // Here we will just pass in the new names
    1170             :     // Copy the input mask to the local main image mask
    1171           0 :   }
    1172          15 :   void SynthesisDeconvolver::setIterDone(const Int iterdone){
    1173             :     //cerr << "SETITERDONE iterdone " << iterdone << endl;
    1174             :     ///this get lost in initMinorCycle
    1175             :     //itsLoopController.incrementMinorCycleCount(iterdone);
    1176          15 :     itsIterDone=iterdone;
    1177             : 
    1178          15 :   }
    1179           0 :   void SynthesisDeconvolver::setPosMask(std::shared_ptr<ImageInterface<Float> > posmask){
    1180           0 :     itsPosMask=posmask;
    1181             : 
    1182           0 :   }
    1183             : 
    1184         409 :   auto key2Mat = [](const Record& rec, const String& key, const Int npol) {
    1185         409 :      Matrix<Double> tmp;
    1186             :      //cerr << "KEY2mat " << key <<"  "<< rec.asArrayDouble(key).shape() << endl;
    1187         409 :      if(rec.asArrayDouble(key).shape().nelements()==1){
    1188         274 :        if(rec.asArrayDouble(key).shape()[0] != npol){
    1189         274 :          tmp.resize(1,rec.asArrayDouble(key).shape()[0]);
    1190         274 :          Vector<Double>tmpvec=rec.asArrayDouble(key);
    1191         274 :          tmp.row(0)=tmpvec;
    1192         274 :        }
    1193             :        else{
    1194           0 :          tmp.resize(rec.asArrayDouble(key).shape()[0],1);
    1195           0 :          Vector<Double>tmpvec=rec.asArrayDouble(key);
    1196           0 :          tmp.column(0)=tmpvec;
    1197           0 :        }
    1198             : 
    1199             :      }
    1200             :      else{
    1201         135 :        tmp=rec.asArrayDouble(key);
    1202             :      }
    1203         409 :      return tmp;
    1204           0 :    };
    1205             : 
    1206         263 :   Record SynthesisDeconvolver::getSubsetRobustStats(const Int chanBeg, const Int chanEnd){
    1207         263 :     Record outRec;
    1208             :     //cerr << "getSUB " << itsRobustStats << endl;
    1209         263 :     if(itsRobustStats.nfields()==0)
    1210         214 :       return outRec;
    1211          49 :     Matrix<Double> tmp;
    1212         441 :     std::vector<String> keys={"min", "max", "rms", "medabsdevmed", "med", "robustrms", "median"};
    1213         392 :     for (auto it = keys.begin() ; it != keys.end(); ++it){
    1214         343 :       if(itsRobustStats.isDefined(*it)){
    1215         128 :         tmp.resize();
    1216         128 :         tmp=key2Mat(itsRobustStats, *it, itsImages->residual()->shape()[2]);
    1217             :         /*
    1218             :         cerr << "size of " << *it << "   " << itsRobustStats.asArrayDouble(*it).shape() << endl;
    1219             :         if(itsRobustStats.asArrayDouble(*it).shape().nelements()==1){
    1220             :           tmp.resize(1, itsRobustStats.asArrayDouble(*it).shape()[0]);
    1221             :           Vector<Double>tmpvec=itsRobustStats.asArrayDouble(*it);
    1222             :           tmp.row(0)=tmpvec;
    1223             : 
    1224             :         }
    1225             :         else
    1226             :           tmp=itsRobustStats.asArrayDouble(*it);
    1227             :         */
    1228             :         //      cerr << std::setprecision(12) << tmp[chanBeg] << " bool " <<(tmp[chanBeg]> (C::dbl_max-(C::dbl_max*1e-15))) << endl;
    1229         128 :         if(tmp(0,chanBeg)> (C::dbl_max-(C::dbl_max*1e-15)))
    1230           0 :           return Record();
    1231             :         //cerr << "GETSUB blc "<< IPosition(2, 0, chanBeg)<<  " trc " << IPosition(2, tmp.shape()[0]-1, chanEnd) << " shape " << tmp.shape() << endl;
    1232         128 :         outRec.define(*it, tmp(IPosition(2, 0, chanBeg), IPosition(2, tmp.shape()[0]-1, chanEnd)));
    1233             :       }
    1234             :     }
    1235             : 
    1236             :     // When itsImages->residual() is called, it (sometimes) creates a read-lock. Release that lock.
    1237          49 :     shared_ptr<ImageInterface<Float> > resimg = itsImages->residual();
    1238          49 :     itsImages->releaseImage( resimg );
    1239             : 
    1240             :     //cerr <<"chanbeg " << chanBeg << " chanend " << chanEnd << endl;
    1241             :     //cerr << "GETSUB " << outRec << endl;
    1242          49 :     return outRec;
    1243         263 :   }
    1244             : 
    1245         263 :   void SynthesisDeconvolver::setSubsetRobustStats(const Record& inrec, const Int chanBeg, const Int chanEnd, const Int numchan){
    1246         263 :     if(inrec.nfields()==0)
    1247         209 :       return ;
    1248          54 :     Matrix<Double> tmp;
    1249         486 :     std::vector<String> keys={"min", "max", "rms", "medabsdevmed", "med", "robustrms", "median"};
    1250             : 
    1251         432 :     for (auto it = keys.begin() ; it != keys.end(); ++it){
    1252         378 :       if(inrec.isDefined(*it)){
    1253         153 :         tmp.resize();
    1254         153 :         tmp=key2Mat(inrec, *it,itsImages->residual()->shape()[2] );
    1255         153 :         Matrix<Double> outvec;
    1256         153 :         if(itsRobustStats.isDefined(*it)){
    1257         128 :           outvec=key2Mat(itsRobustStats, *it, itsImages->residual()->shape()[2]);
    1258             :         }
    1259             :         else{
    1260          25 :           outvec.resize(itsImages->residual()->shape()[2], numchan);
    1261          25 :           outvec.set(C::dbl_max);
    1262             :         }
    1263             : 
    1264             : 
    1265         153 :         outvec(IPosition(2, 0, chanBeg), IPosition(2,outvec.shape()[0]-1, chanEnd))=tmp;
    1266         153 :         itsRobustStats.define(*it, outvec);
    1267         153 :       }
    1268             :     }
    1269             : 
    1270             :     // When itsImages->residual() is called, it (sometimes) creates a read-lock. Release that lock.
    1271          54 :     shared_ptr<ImageInterface<Float> > resimg = itsImages->residual();
    1272          54 :     itsImages->releaseImage( resimg );
    1273             : 
    1274             :     //cerr << "SETT " << itsRobustStats << endl;
    1275             :     //cerr << "SETT::ItsRobustStats " << Vector<Double>(itsRobustStats.asArrayDouble("min")) << endl;
    1276          54 :   }
    1277             : } //# NAMESPACE CASA - END
    1278             : 

Generated by: LCOV version 1.16