LCOV - code coverage report
Current view: top level - synthesis/ImagerObjects - SIMinorCycleController.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 21 188 11.2 %
Date: 2025-08-21 08:01:32 Functions: 2 32 6.2 %

          Line data    Source code
       1             : //# SIISubterBot.cc: This file contains the implementation of the SISubIterBot class.
       2             : //#
       3             : //#  CASA - Common Astronomy Software Applications (http://casa.nrao.edu/)
       4             : //#  Copyright (C) Associated Universities, Inc. Washington DC, USA 2011, All rights reserved.
       5             : //#  Copyright (C) European Southern Observatory, 2011, All rights reserved.
       6             : //#
       7             : //#  This library is free software; you can redistribute it and/or
       8             : //#  modify it under the terms of the GNU Lesser General Public
       9             : //#  License as published by the Free software Foundation; either
      10             : //#  version 2.1 of the License, or (at your option) any later version.
      11             : //#
      12             : //#  This library is distributed in the hope that it will be useful,
      13             : //#  but WITHOUT ANY WARRANTY, without even the implied warranty of
      14             : //#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             : //#  Lesser General Public License for more details.
      16             : //#
      17             : //#  You should have received a copy of the GNU Lesser General Public
      18             : //#  License along with this library; if not, write to the Free Software
      19             : //#  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
      20             : //#  MA 02111-1307  USA
      21             : //# $Id: $
      22             : 
      23             : #include <synthesis/ImagerObjects/SIMinorCycleController.h>
      24             : 
      25             : /* Records Interface */
      26             : #include <casacore/casa/Containers/Record.h>
      27             : #include <casacore/casa/BasicMath/Math.h>
      28             : #include <casacore/casa/Utilities/GenSort.h>
      29             : #include <math.h> // For FLT_MAX
      30             : 
      31             : using namespace casacore;
      32             : namespace casa { //# NAMESPACE CASA - BEGIN
      33             :   
      34             :   
      35          17 :   SIMinorCycleController::SIMinorCycleController(): 
      36          17 :                                 itsCycleNiter(0),
      37          17 :                                 itsCycleThreshold(0.0),
      38          17 :                                 itsNsigmaThreshold(0.0),
      39          17 :                                 itsLoopGain(0.1),
      40          17 :                                 itsIsThresholdReached(false),
      41          17 :                                 itsUpdatedModelFlag(false),
      42          17 :                                 itsIterDone(0),
      43          17 :                                 itsCycleIterDone(0),
      44          17 :                                 itsTotalIterDone(0),
      45          17 :                                 itsMaxCycleIterDone(0),
      46          17 :                                 itsPeakResidual(0),
      47          17 :                                 itsIntegratedFlux(0),
      48          17 :                                 itsMaxPsfSidelobe(0),
      49          17 :                                 itsMinResidual(0),itsMinResidualNoMask(0),
      50          17 :                                 itsPeakResidualNoMask(0), itsNsigma(0),
      51          17 :                                 itsMadRMS(0), itsMaskSum(0),
      52             :                                 //itsSummaryMinor(IPosition(2,
      53             :                                 //                            SIMinorCycleController::useSmallSummaryminor() ? 6 : SIMinorCycleController::nSummaryFields, // temporary CAS-13683 workaround
      54          17 :                                 itsSummaryMinor(IPosition(2, SIMinorCycleController::nSummaryFields, // temporary CAS-13683 workaround
      55             :                                                             0)),
      56          17 :                                 itsDeconvolverID(0) 
      57          17 :   {}
      58             : 
      59             : 
      60             : 
      61          17 :   SIMinorCycleController::~SIMinorCycleController(){}
      62             : 
      63             : 
      64           0 :   Int SIMinorCycleController::majorCycleRequired(Float currentPeakResidual)
      65             :   {
      66           0 :     LogIO os( LogOrigin("SIMinorCycleController",__FUNCTION__,WHERE) );
      67             :     
      68           0 :     Int stopCode=0;
      69             : 
      70             :     // Reached iteration limit
      71           0 :     if (itsCycleIterDone >= itsCycleNiter ) {stopCode=1;}
      72             :     // Reached cyclethreshold
      73             :     //if( fabs(currentPeakResidual) <= itsCycleThreshold ) { stopCode=2; }
      74             :     // Reached cyclethreshold or n-sigma threshold
      75             :     //debug (TT)
      76             :     //os << LogIO::DEBUG1<< "itsNsigma="<<itsNsigma<<" itsIterDiff="<<itsIterDiff<<LogIO::POST;
      77           0 :     os << LogIO::DEBUG1<< "itsNsigmaThreshoild="<<itsNsigmaThreshold<<" itsCycleThreshold="<<itsCycleThreshold<<" currentPeakRes="<<currentPeakResidual<<LogIO::POST;
      78           0 :     if (itsCycleThreshold >= itsNsigmaThreshold) {
      79             :       //if( fabs(currentPeakResidual) <= itsCycleThreshold ) { stopCode=2; }
      80           0 :       if( fabs(currentPeakResidual) <= itsCycleThreshold ) { 
      81             :         //itsNsigmaThreshold = 0.0; // since stopped by gobal threshold, reset itsNsigmaThreshold 
      82           0 :         stopCode=2; 
      83             :       }
      84             :     }
      85             :     else {
      86           0 :       if( fabs(currentPeakResidual) <= itsNsigmaThreshold && !(itsIterDiff<=0)) { if (itsNsigma!=0.0) stopCode=6; }
      87             :     }
      88             :     // Zero iterations done
      89           0 :     if( itsIterDiff==0 ) {stopCode=3;}
      90             :     // Diverged : CAS-8767, CAS-8584
      91             :     //cout << " itsIterDiff : " << itsIterDiff << "  itsPeak : " << itsPeakResidual << " currentPeak : " << currentPeakResidual << " itsMin : " << itsMinResidual << " stopcode so far : " << stopCode ;
      92           0 :     if( itsIterDiff>0 &&
      93           0 :         ( fabs(itsMinResidual) > 0.0 ) && 
      94           0 :         ( fabs(currentPeakResidual) - fabs(itsMinResidual) )/ fabs(itsMinResidual) >0.1  ) 
      95           0 :       {stopCode=4;}
      96             : 
      97             :    //  cout << " -> " << stopCode << endl;
      98             : 
      99             :     /*    // Going nowhere
     100             :     if( itsIterDiff > 1500 && 
     101             :         ( fabs(itsPeakResidual) > 0.0 ) && 
     102             :         ( fabs(currentPeakResidual) - fabs(itsPeakResidual) )/ fabs(itsPeakResidual) < itsLoopGain  ) 
     103             :       {stopCode=5;}
     104             :     */
     105             : 
     106           0 :     return stopCode;
     107             : 
     108             : 
     109           0 :   }
     110             : 
     111             : 
     112           0 :   Float SIMinorCycleController::getLoopGain()
     113             :   {
     114           0 :     return itsLoopGain;
     115             :   }
     116             :   
     117             :   
     118           0 :   void SIMinorCycleController::setUpdatedModelFlag(Bool updatedmodel)
     119             :   {
     120           0 :     itsUpdatedModelFlag = updatedmodel;
     121           0 :   }
     122             : 
     123           0 :   void SIMinorCycleController::incrementMinorCycleCount(Int itersDonePerStep)
     124             :   {
     125             :     /*
     126             :     if( itersDonePerStep <= 0 )
     127             :       {
     128             :         LogIO os( LogOrigin("SIMinorCycleController",__FUNCTION__,WHERE) );
     129             :         os << LogIO::WARN << "Zero iterations done after " << itsCycleIterDone << LogIO::POST;
     130             :       }
     131             :     */
     132             : 
     133           0 :     itsIterDiff = itersDonePerStep;
     134           0 :     itsIterDone += itersDonePerStep;
     135           0 :     itsTotalIterDone += itersDonePerStep;
     136           0 :     itsCycleIterDone += itersDonePerStep;
     137           0 :   }
     138             : 
     139           0 :   Float SIMinorCycleController::getPeakResidual()
     140             :   {
     141           0 :     return itsPeakResidual;
     142             :   }
     143             : 
     144             :   // This is the max residual across all channels/stokes (subimages).
     145             :   // This is returned in the end-minor-cycle record.
     146             :   /// TODO : Make arrays/lists for peakresidual per 'subimage'. Max over subims gets returned.
     147           0 :   void SIMinorCycleController::setPeakResidual(Float peakResidual)
     148             :   {
     149           0 :     itsPeakResidual = peakResidual;
     150             :     //    cout << "Setting peak res (SIMinorCycleController) : " << itsPeakResidual << endl;
     151             : 
     152           0 :     if( itsMinResidual > itsPeakResidual )
     153           0 :       itsMinResidual = itsPeakResidual;
     154             : 
     155           0 :   }
     156             : 
     157           0 :   void SIMinorCycleController::setPeakResidualNoMask(Float peakResidual)
     158             :   {
     159           0 :     itsPeakResidualNoMask = peakResidual;
     160             :     //    cout << "Setting peak res (SIMinorCycleController) : " << itsPeakResidual << endl;
     161             : 
     162           0 :     if( itsMinResidualNoMask > itsPeakResidualNoMask )
     163           0 :       itsMinResidualNoMask = itsPeakResidualNoMask;
     164             : 
     165           0 :   }
     166             : 
     167           0 :   void SIMinorCycleController::setMadRMS(Float madRMS)
     168             :   {
     169           0 :     itsMadRMS = madRMS;
     170           0 :   }
     171             : 
     172           0 :   Float SIMinorCycleController::getNsigma()
     173             :   {
     174           0 :     return itsNsigma;
     175             :   }
     176             : 
     177           0 :   void SIMinorCycleController::setNsigma(Float nSigma)
     178             :   {
     179           0 :     itsNsigma = nSigma;
     180           0 :   }
     181             : 
     182           0 :   void SIMinorCycleController::setNsigmaThreshold(Float nsigmaThreshold)
     183             :   {
     184             :     
     185           0 :     LogIO os( LogOrigin("SIMinorCycleController",__FUNCTION__,WHERE) );
     186           0 :     itsNsigmaThreshold = nsigmaThreshold;
     187           0 :   }
     188             : 
     189           0 :   void SIMinorCycleController::setPBMask(Float pbMaskLevel)
     190             :   {
     191           0 :     itsPBMaskLevel = pbMaskLevel;
     192           0 :   }
     193             : 
     194           0 :   void SIMinorCycleController::setMaskSum(Float maskSum)
     195             :   {
     196           0 :     itsMaskSum = maskSum;
     197           0 :   }
     198             : 
     199           0 :   void SIMinorCycleController::setFullSummary(bool fullSummary)
     200             :   {
     201           0 :     itsFullSummary = fullSummary;
     202           0 :   }
     203             : 
     204           0 :   void SIMinorCycleController::resetMinResidual()
     205             :   {
     206           0 :     itsMinResidual = itsPeakResidual;
     207           0 :     itsIterDiff=-1;
     208           0 :   }
     209             : 
     210           0 :   Float SIMinorCycleController::getIntegratedFlux()
     211             :   {
     212           0 :     return itsIntegratedFlux;
     213             :   }
     214             : 
     215           0 :   void SIMinorCycleController::addIntegratedFlux(Float integratedFlux)
     216             :   {
     217           0 :     itsIntegratedFlux += integratedFlux;
     218           0 :   }
     219             : 
     220           0 :   Float SIMinorCycleController::getMaxPsfSidelobe()
     221             :   {
     222           0 :     return itsMaxPsfSidelobe;
     223             :   }
     224             : 
     225           0 :   void SIMinorCycleController::setMaxPsfSidelobe(Float maxPsfSidelobe)
     226             :   {
     227           0 :     itsMaxPsfSidelobe = maxPsfSidelobe;
     228           0 :   }
     229             : 
     230           0 :   Int SIMinorCycleController::getIterDone()
     231             :   {
     232           0 :     return itsIterDone;
     233             :   }
     234             : 
     235           0 :   Int SIMinorCycleController::getCycleNiter()
     236             :   {
     237           0 :     return itsCycleNiter;
     238             :   }
     239             : 
     240           0 :   Float SIMinorCycleController::getCycleThreshold()
     241             :   {
     242           0 :     return itsCycleThreshold;
     243             :   }
     244             :  
     245           0 :   Bool SIMinorCycleController::isThresholdReached()
     246             :   {
     247           0 :     return itsIsThresholdReached;
     248             :   }
     249             : 
     250           0 :   Record SIMinorCycleController::getCycleExecutionRecord() {
     251           0 :     LogIO os( LogOrigin("SISkyModel",__FUNCTION__,WHERE) );
     252           0 :     Record returnRecord;
     253             : 
     254           0 :     returnRecord.define( RecordFieldId("iterdone"),  itsIterDone);
     255           0 :     returnRecord.define(RecordFieldId("peakresidual"), itsPeakResidual);
     256           0 :     returnRecord.define(RecordFieldId("updatedmodelflag"), 
     257           0 :                         itsUpdatedModelFlag);
     258           0 :     returnRecord.define(RecordFieldId("summaryminor"), itsSummaryMinor);
     259           0 :     returnRecord.define(RecordFieldId("updatedmodelflag"),
     260           0 :                         itsUpdatedModelFlag);
     261           0 :     returnRecord.define(RecordFieldId("maxcycleiterdone"),
     262             :                         itsMaxCycleIterDone);
     263           0 :     returnRecord.define( RecordFieldId("peakresidualnomask"), itsPeakResidualNoMask);
     264             : 
     265           0 :     return returnRecord;
     266           0 :   }
     267             : 
     268           0 :   Float SIMinorCycleController::getPBMask() {
     269           0 :     return itsPBMaskLevel;
     270             :   }
     271             : 
     272           0 :   Record SIMinorCycleController::getCycleInitializationRecord() {
     273           0 :     LogIO os( LogOrigin("SIMinorCycleController",__FUNCTION__,WHERE) );
     274             : 
     275           0 :     Record returnRecord;
     276             :     
     277             :     /* Reset Counters and summary for the current set of minorcycle iterations */
     278           0 :     itsIterDone = 0;
     279           0 :     itsIterDiff = -1;
     280           0 :     int nSummaryFields = !itsFullSummary ? 7 : SIMinorCycleController::nSummaryFields; // temporary CAS-13683 workaround
     281           0 :     itsSummaryMinor.resize( IPosition( 2, nSummaryFields, 0) , true );
     282             : 
     283             :     /* Control Variables */
     284           0 :     returnRecord.define(RecordFieldId("peakresidual"), itsPeakResidual);
     285           0 :     returnRecord.define(RecordFieldId("maxpsfsidelobe"), itsMaxPsfSidelobe);
     286           0 :     returnRecord.define( RecordFieldId("peakresidualnomask"), itsPeakResidualNoMask);
     287           0 :     returnRecord.define( RecordFieldId("madrms"), itsMadRMS);
     288           0 :     returnRecord.define( RecordFieldId("masksum"), itsMaskSum);
     289           0 :     returnRecord.define( RecordFieldId("nsigmathreshold"), itsNsigmaThreshold);
     290           0 :     returnRecord.define( RecordFieldId("nsigma"), itsNsigma);
     291           0 :     returnRecord.define( RecordFieldId("fullsummary"), itsFullSummary);
     292           0 :     returnRecord.define(RecordFieldId("summaryminor"), itsSummaryMinor);
     293             : 
     294           0 :     return returnRecord;
     295           0 :   }
     296             : 
     297           0 :   void SIMinorCycleController::setCycleControls(Record &recordIn) {
     298           0 :     LogIO os( LogOrigin("SIMinorCycleController",__FUNCTION__,WHERE) );
     299             : 
     300           0 :     if (recordIn.isDefined("cycleniter"))
     301           0 :       {recordIn.get(RecordFieldId("cycleniter"), itsCycleNiter);}
     302             :     else
     303           0 :       {throw(AipsError("cycleniter not defined in input minor-cycle controller") );}
     304             : 
     305           0 :     if (recordIn.isDefined("cyclethreshold")) 
     306           0 :       {recordIn.get(RecordFieldId("cyclethreshold"),itsCycleThreshold);}
     307             :     else
     308           0 :       {throw(AipsError("cyclethreshold not defined in input minor-cycle controller") );}
     309             :      
     310           0 :     if (recordIn.isDefined("thresholdreached"))
     311           0 :       {recordIn.get(RecordFieldId("thresholdreached"), itsIsThresholdReached);}
     312             :     else
     313           0 :       { throw(AipsError("thresholdreached not defined in input minor-cycle controller") );}
     314             : 
     315           0 :     if (recordIn.isDefined("loopgain")) 
     316           0 :       {recordIn.get(RecordFieldId("loopgain"), itsLoopGain);}
     317             :     else
     318           0 :       {throw(AipsError("loopgain not defined in input minor-cycle controller") );}
     319             : 
     320           0 :     if (recordIn.isDefined("nsigma"))
     321           0 :       {recordIn.get(RecordFieldId("nsigma"), itsNsigma);}
     322             :     else 
     323           0 :       { throw(AipsError(" nsigma is not defined in input minor-cycle controller ") );}
     324             : 
     325             :     //if (recordIn.isDefined("fullsummary"))
     326             :    //  {recordIn.get(RecordFieldId("fullsummary"), itsFullSummary);}
     327             :     //else 
     328             :     //  { throw(AipsError(" fullsummary is not defined in input minor-cycle controller ") );}
     329             :     //os<<" in setCycleControls done... "<<LogIO::POST;
     330             : 
     331             :     /* Reset the counters for the new cycle */
     332           0 :     itsMaxCycleIterDone = 0;
     333           0 :     itsCycleIterDone = 0;
     334           0 :     itsUpdatedModelFlag = false;
     335           0 :   }
     336             : 
     337           0 :   void SIMinorCycleController::resetCycleIter(){
     338           0 :     itsMaxCycleIterDone = max(itsCycleIterDone, itsMaxCycleIterDone);
     339           0 :     itsCycleIterDone = 0;
     340           0 :   }
     341             : 
     342           0 :   void SIMinorCycleController::addSummaryMinor(uInt deconvolverid, uInt chan, uInt pol,
     343             :                                                Int cycleStartIter, Int startIterDone, Float startmodelflux, Float startpeakresidual, Float startpeakresidualnomask,
     344             :                                                Float modelflux, Float peakresidual, Float peakresidualnomask, Float masksum, Int mpiRank, Int stopCode, bool fullsummary)
     345             :   {
     346           0 :     LogIO os( LogOrigin("SIMinorCycleController", __FUNCTION__ ,WHERE) );
     347           0 :     IPosition shp = itsSummaryMinor.shape();
     348           0 :     int nSummaryFields = !fullsummary ? 7 : SIMinorCycleController::nSummaryFields;
     349           0 :     if( shp.nelements() != 2 && shp[0] != nSummaryFields ) 
     350           0 :       throw(AipsError("Internal error in shape of minor-cycle summary record"));
     351           0 :      itsSummaryMinor.resize( IPosition( 2, nSummaryFields, shp[1]+1 ) , true );
     352             :      // iterations done
     353             :      // make it non-cummulative for all cases
     354           0 :      itsSummaryMinor( IPosition(2, 0, shp[1] ) ) = itsIterDone - startIterDone;
     355             :      // peak residual
     356           0 :      itsSummaryMinor( IPosition(2, 1, shp[1] ) ) = (Double) peakresidual;
     357             :      // model flux
     358           0 :      itsSummaryMinor( IPosition(2, 2, shp[1] ) ) = (Double) modelflux;
     359             :      // cycle threshold
     360           0 :      itsSummaryMinor( IPosition(2, 3, shp[1] ) ) = itsCycleThreshold;
     361             :      // mapper id (or multifield id temporary CAS-13683 workaround)
     362           0 :      itsSummaryMinor( IPosition(2, 4, shp[1] ) ) = deconvolverid;
     363             :      // channel id
     364           0 :      itsSummaryMinor( IPosition(2, 5, shp[1] ) ) = chan;
     365             :      // Stokes id
     366           0 :      itsSummaryMinor( IPosition(2, 6, shp[1] ) ) = pol;
     367           0 :      if (fullsummary) {
     368             :          // cycle start iterations done (ie earliest iterDone for the entire minor cycle)
     369           0 :          itsSummaryMinor( IPosition(2, 7, shp[1] ) ) = cycleStartIter;
     370             :          // starting iterations done
     371           0 :          itsSummaryMinor( IPosition(2, 8, shp[1] ) ) = startIterDone;
     372             :          // starting peak residual
     373           0 :          itsSummaryMinor( IPosition(2, 9, shp[1] ) ) = (Double) startpeakresidual;
     374             :          // starting model flux
     375           0 :          itsSummaryMinor( IPosition(2, 10, shp[1] ) ) = (Double) startmodelflux;
     376             :          // starting peak residual, not limited to the user's mask
     377           0 :          itsSummaryMinor( IPosition(2, 11, shp[1] ) ) = (Double) startpeakresidualnomask;
     378             :          // peak residual, not limited to the user's mask
     379           0 :          itsSummaryMinor( IPosition(2, 12, shp[1] ) ) = (Double) peakresidualnomask;
     380             :          // number of pixels in the mask
     381           0 :          itsSummaryMinor( IPosition(2, 13, shp[1] ) ) = (Double) masksum;
     382             :          // mpi server
     383           0 :          itsSummaryMinor( IPosition(2, 14, shp[1] ) ) = mpiRank;
     384             :          // outlier field id, to be provided in grpcInteractiveCleanManager::mergeMinorCycleSummary
     385           0 :          itsSummaryMinor( IPosition(2, 15, shp[1] ) ) = 0;
     386             :          // stopcode
     387           0 :          itsSummaryMinor( IPosition(2, 16, shp[1] ) ) = stopCode;
     388             :      }
     389             : 
     390           0 :   }// end of addSummaryMinor
     391             : 
     392             :   // temporary CAS-13683 workaround
     393             :   /***
     394             :   Bool SIMinorCycleController::useSmallSummaryminor()
     395             :   {
     396             :     if (const char* use_small_summaryminor_p = std::getenv("USE_SMALL_SUMMARYMINOR"))
     397             :     {
     398             :         string use_small_summaryminor(use_small_summaryminor_p);
     399             :         if (use_small_summaryminor.compare("TRUE") == 0 || use_small_summaryminor.compare("true") == 0) {
     400             :             return true;
     401             :         }
     402             :     }
     403             :     return false;
     404             :   }
     405             :   ***/
     406             :   
     407             : } //# NAMESPACE CASA - END
     408             : 

Generated by: LCOV version 1.16