LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations - ClarkCleanModel.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 616 0.0 %
Date: 2024-12-11 20:54:31 Functions: 0 42 0.0 %

          Line data    Source code
       1             : //# ClarkCleanModel.cc:  this defines ClarkCleanModel
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2003
       3             : //# Associated Universities, Inc. Washington DC, USA.
       4             : //#
       5             : //# This library is free software; you can redistribute it and/or modify it
       6             : //# under the terms of the GNU Library General Public License as published by
       7             : //# the Free Software Foundation; either version 2 of the License, or (at your
       8             : //# option) any later version.
       9             : //#
      10             : //# This library 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 Library General Public
      13             : //# License for more details.
      14             : //#
      15             : //# You should have received a copy of the GNU Library General Public License
      16             : //# along with this library; if not, write to the Free Software Foundation,
      17             : //# Inc., 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 <synthesis/MeasurementEquations/ClarkCleanModel.h>
      29             : #include <synthesis/MeasurementEquations/ClarkCleanProgress.h>
      30             : #include <casacore/casa/Arrays/IPosition.h>
      31             : #include <casacore/casa/Arrays/Slice.h>
      32             : #include <casacore/casa/Arrays/Matrix.h>
      33             : #include <casacore/casa/Arrays/Vector.h>
      34             : #include <casacore/casa/Arrays/Array.h>
      35             : #include <casacore/casa/Arrays/ArrayError.h>
      36             : #include <casacore/casa/Arrays/ArrayMath.h>
      37             : #include <casacore/casa/Arrays/ArrayLogical.h>
      38             : #include <casacore/casa/Arrays/VectorIter.h>
      39             : #include <casacore/casa/Logging/LogOrigin.h>
      40             : #include <casacore/casa/Exceptions/Error.h>
      41             : #include <casacore/casa/Utilities/Assert.h>
      42             : #include <casacore/casa/iostream.h> 
      43             : #include <casacore/casa/System/Choice.h>
      44             : 
      45             : using namespace casacore;
      46             : namespace casa { //# NAMESPACE CASA - BEGIN
      47             : 
      48             : //# These are the definitions of the fortran functions
      49             : 
      50             : #define NEED_FORTRAN_UNDERSCORES
      51             : 
      52             : #if defined(NEED_FORTRAN_UNDERSCORES)
      53             : #define getbigf getbigf_
      54             : #define getbig2f getbig2f_
      55             : #define getbig4f getbig4f_
      56             : #define abshisf abshisf_
      57             : #define abshis2f abshis2f_
      58             : #define abshis4f abshis4f_
      59             : #define absmaxf absmaxf_
      60             : #define absmax2f absmax2f_
      61             : #define absmax4f absmax4f_
      62             : #define subcomf subcomf_
      63             : #define subcom2f subcom2f_
      64             : #define subcom4f subcom4f_
      65             : #define maxabsf maxabsf_
      66             : #define maxabs2f maxabs2f_
      67             : #define maxabs4f maxabs4f_
      68             : #define maxabmf maxabmf_
      69             : #define maxabm2f maxabm2f_
      70             : #define maxabm4f maxabm4f_
      71             : #define abshimf abshimf_
      72             : #define abshim2f abshim2f_
      73             : #define abshim4f abshim4f_
      74             : #define getbimf getbimf_
      75             : #define getbim2f getbim2f_
      76             : #define getbim4f getbim4f_
      77             : #endif
      78             : 
      79             : extern "C" {
      80             :   void getbigf(Float * pixVal, Int * pixPos, Int * maxPix, 
      81             :                const Float * fluxLimit, const Float * arr, 
      82             :                const Int * nx, const Int * ny);
      83             :   void getbig2f(Float * pixVal, Int * pixPos, Int * maxPix, 
      84             :                 const Float * fluxLimit, const Float * arr, 
      85             :                 const Int * nx, const Int * ny);
      86             :   void getbig4f(Float * pixVal, Int * pixPos, Int * maxPix, 
      87             :                 const Float * fluxLimit, const Float * arr, 
      88             :                 const Int * nx, const Int * ny);
      89             :   void abshisf(Int * hist, Float * minval, Float * maxval, 
      90             :                const Int * nbins, const Float * arr, const Int * npix);
      91             :   void abshis2f(Int * hist, Float * minval, Float * maxval, 
      92             :                 const Int * nbins, const Float * arr, const Int * npix);
      93             :   void abshis4f(Int * hist, Float * minval, Float * maxval, 
      94             :                 const Int * nbins, const Float * arr, const Int * npix);
      95             :   void absmaxf(Float * maxelem, Float * maxval, Int * maxpos, 
      96             :                const Float * arr, const Int * npix);
      97             :   void absmax2f(Float * maxelem, Float * maxval, Int * maxpos, 
      98             :                 const Float * arr, const Int * npix);
      99             :   void absmax4f(Float * maxelem, Float * maxval, Int * maxpos, 
     100             :                 const Float * arr, const Int * npix);
     101             :   void subcomf(Float * pixval, const Int * pixpos, const Int * npix, 
     102             :                const Float * maxpix, const Int * maxpos, 
     103             :                const Float * psf, const Int * nx, const Int * ny);
     104             :   void subcom2f(Float * pixval, const Int * pixpos, const Int * npix, 
     105             :                const Float * maxpix, const Int * maxpos, 
     106             :                const Float * psf, const Int * nx, const Int * ny);
     107             :   void subcom4f(Float * pixval, const Int * pixpos, const Int * npix, 
     108             :                const Float * maxpix, const Int * maxpos, 
     109             :                const Float * psf, const Int * nx, const Int * ny);
     110             :   void maxabsf(Float * maxval, const Float * arr, const Int * npix);
     111             :   void maxabs2f(Float * maxval, const Float * arr, const Int * npix);
     112             :   void maxabs4f(Float * maxval, const Float * arr, const Int * npix);
     113             :   void maxabmf(Float * maxval, const Float * arr, const Float * mask,
     114             :                const Int * npix);
     115             :   void maxabm2f(Float * maxval, const Float * arr, const Float * mask,
     116             :                 const Int * npix);
     117             :   void maxabm4f(Float * maxval, const Float * arr, const Float * mask,
     118             :                 const Int * npix);
     119             :   void abshimf(Int * hist, Float * minval, Float * maxval, const Int * nbins,
     120             :                const Float * arr, const Float * mask, const Int * npix);
     121             :   void abshim2f(Int * hist, Float * minval, Float * maxval, const Int * nbins,
     122             :                 const Float * arr, const Float * mask, const Int * npix);
     123             :   void abshim4f(Int * hist, Float * minval, Float * maxval, const Int * nbins,
     124             :                 const Float * arr, const Float * mask, const Int * npix);
     125             :   void getbimf(Float * pixVal, Int * pixPos, Int * maxPix, 
     126             :                const Float * fluxLimit, const Float * arr, const Float * mask, 
     127             :                const Int * nx, const Int * ny);
     128             :   void getbim2f(Float * pixVal, Int * pixPos, Int * maxPix, 
     129             :                 const Float * fluxLimit, const Float * arr, const Float * mask,  
     130             :                 const Int * nx, const Int * ny);
     131             :   void getbim4f(Float * pixVal, Int * pixPos, Int * maxPix, 
     132             :                 const Float * fluxLimit, const Float * arr, const Float * mask,  
     133             :                 const Int * nx, const Int * ny);
     134             : };
     135             : 
     136             : 
     137             : //----------------------------------------------------------------------
     138           0 : ClarkCleanModel::ClarkCleanModel()
     139             :   :ArrayModel<Float>(),
     140           0 :    theHistBins(1024), 
     141           0 :    theMaxExtPsf(0.0),
     142           0 :    theMaxNumberMinorIterations(10000),
     143           0 :    theInitialNumberIterations(0),
     144           0 :    theMaxNumberMajorCycles(-1),
     145           0 :    theMaxNumPix(32*1024),
     146           0 :    thePsfPatchSize(2,51,51),
     147           0 :    theSpeedup(0.0),
     148           0 :    theCycleSpeedup(-1.0),
     149           0 :    theChoose(false),
     150           0 :    theMask(),
     151           0 :    theLog(LogOrigin("ClarkCleanModel", "ClarkCleanModel()")),
     152           0 :    theIterCounter(0),
     153           0 :    itsProgressPtr(0),
     154           0 :    itsJustStarting(true)
     155             : {
     156           0 : };
     157             : //----------------------------------------------------------------------
     158           0 : ClarkCleanModel::ClarkCleanModel(Array<Float> & model)
     159             :   :ArrayModel<Float>(model),
     160           0 :    theHistBins(1024), 
     161           0 :    theMaxExtPsf(0.0),
     162           0 :    theMaxNumberMinorIterations(10000),
     163           0 :    theInitialNumberIterations(0),
     164           0 :    theMaxNumberMajorCycles(-1),
     165           0 :    theMaxNumPix(32*1024),
     166           0 :    thePsfPatchSize(2, 51, 51),
     167           0 :    theSpeedup(0.0), 
     168           0 :    theCycleSpeedup(-1.0), 
     169           0 :    theChoose(false),
     170           0 :    theMask(),
     171           0 :    theLog(LogOrigin("ClarkCleanModel", 
     172             :                     "ClarkCleanModel(const Array<Float> & model)")),
     173           0 :    theIterCounter(0),
     174           0 :    itsProgressPtr(0),
     175           0 :    itsJustStarting(true)
     176             : {
     177           0 :   AlwaysAssert(theModel.ndim() >= 2, AipsError);
     178           0 :   if (theModel.ndim() >= 3)
     179           0 :     AlwaysAssert(theModel.shape()(2) == 1 || theModel.shape()(2) == 2 || 
     180             :                  theModel.shape()(2) == 4, AipsError);
     181           0 :   if (theModel.ndim() >= 4)
     182           0 :     for (uInt i = 3; i < theModel.ndim(); i++)
     183           0 :       AlwaysAssert(theModel.shape()(i) == 1, AipsError);
     184             : //      theLog << LogOrigin("ClarkCleanModel", "ClarkCleanModel") 
     185             : //          << "Model shape is:" << theModel.shape() << endl;
     186           0 : };
     187             : //----------------------------------------------------------------------
     188           0 : ClarkCleanModel::ClarkCleanModel(Array<Float> & model, 
     189           0 :                                  Array<Float> & mask)
     190             :   :ArrayModel<Float>(model),
     191           0 :    theHistBins(1024), 
     192           0 :    theMaxExtPsf(0.0),
     193           0 :    theMaxNumberMinorIterations(10000),
     194           0 :    theInitialNumberIterations(0),
     195           0 :    theMaxNumberMajorCycles(-1),
     196           0 :    theMaxNumPix(32*1024),
     197           0 :    thePsfPatchSize(2, 51, 51),
     198           0 :    theSpeedup(0.0), 
     199           0 :    theCycleSpeedup(-1.0), 
     200           0 :    theChoose(false),
     201           0 :    theMask(mask),
     202           0 :    theLog(LogOrigin("ClarkCleanModel", 
     203             :                     "ClarkCleanModel(Array<Float> & model"
     204             :                     ", Array<Float> & mask)")),
     205           0 :    theIterCounter(0),
     206           0 :    itsProgressPtr(0),
     207           0 :    itsJustStarting(true)
     208             : {
     209           0 :      AlwaysAssert(theModel.ndim() >= 2, AipsError);
     210           0 :      if (theModel.ndim() >= 3)
     211           0 :        AlwaysAssert(theModel.shape()(2) == 1 || theModel.shape()(2) == 2 || 
     212             :                     theModel.shape()(2) == 4, AipsError);
     213           0 :      if (theModel.ndim() >= 4)
     214           0 :        for (uInt i = 3; i < theModel.ndim(); i++)
     215           0 :          AlwaysAssert(theModel.shape()(i) == 1, AipsError);
     216             : 
     217           0 :      AlwaysAssert(theMask.ndim() >= 2, AipsError);
     218           0 :      AlwaysAssert(theMask.shape()(0) == theModel.shape()(0), AipsError);
     219           0 :      AlwaysAssert(theMask.shape()(1) == theModel.shape()(1), AipsError);
     220           0 :      if (theMask.ndim() >= 3)
     221           0 :        for (uInt i = 2; i < theMask.ndim(); i++)
     222           0 :          AlwaysAssert(theMask.shape()(i) == 1, AipsError);
     223           0 : };
     224             : 
     225           0 : void ClarkCleanModel::getModel(Array<Float>& model) const{
     226           0 :   model = theModel;
     227           0 : };
     228           0 : void ClarkCleanModel::setModel(const Array<Float>& model){
     229           0 :   AlwaysAssert(model.ndim() >= 2, AipsError);
     230           0 :   if (model.ndim() >= 3)
     231           0 :     AlwaysAssert(model.shape()(2) == 1 || model.shape()(2) == 2 || 
     232             :                  model.shape()(2) == 4, AipsError);
     233           0 :   if (model.ndim() >= 4)
     234           0 :     for (uInt i = 3; i < model.ndim(); i++)
     235           0 :       AlwaysAssert(model.shape()(i) == 1, AipsError);
     236           0 :   theModel = model;
     237           0 : };
     238           0 : void ClarkCleanModel::setModel(Array<Float> & model){
     239           0 :   AlwaysAssert(model.ndim() >= 2, AipsError);
     240           0 :   if (model.ndim() >= 3)
     241           0 :     AlwaysAssert(model.shape()(2) == 1 || model.shape()(2) == 2 || 
     242             :                  model.shape()(2) == 4, AipsError);
     243           0 :   if (model.ndim() >= 4)
     244           0 :     for (uInt i = 3; i < model.ndim(); i++)
     245           0 :       AlwaysAssert(model.shape()(i) == 1, AipsError);
     246           0 :   theModel.reference(model);
     247           0 : };
     248             : 
     249           0 : void ClarkCleanModel::getMask(Array<Float>& mask) const{
     250           0 :   mask = theMask;
     251           0 : };
     252           0 : void ClarkCleanModel::setMask(const Array<Float>& mask){
     253           0 :   AlwaysAssert(mask.ndim() >= 2, AipsError);
     254           0 :   AlwaysAssert(mask.shape()(0) == theModel.shape()(0), AipsError);
     255           0 :   AlwaysAssert(mask.shape()(1) == theModel.shape()(1), AipsError);
     256           0 :   if (mask.ndim() >= 3)
     257           0 :     for (uInt i = 2; i < mask.ndim(); i++)
     258           0 :       AlwaysAssert(mask.shape()(i) == 1, AipsError);
     259           0 :   theMask = mask;
     260           0 : };
     261           0 : void ClarkCleanModel::setMask(Array<Float> & mask){
     262           0 :   AlwaysAssert(mask.ndim() >= 2, AipsError);
     263           0 :   AlwaysAssert(mask.shape()(0) == theModel.shape()(0), AipsError);
     264           0 :   AlwaysAssert(mask.shape()(1) == theModel.shape()(1), AipsError);
     265           0 :   if (mask.ndim() >= 3)
     266           0 :     for (uInt i = 2; i < mask.ndim(); i++)
     267           0 :       AlwaysAssert(mask.shape()(i) == 1, AipsError);
     268           0 :   theMask.reference(mask);
     269           0 : };
     270             : 
     271             : 
     272             : //----------------------------------------------------------------------
     273           0 : Bool ClarkCleanModel::solve(ConvolutionEquation & eqn){
     274           0 :   theLog << LogOrigin("ClarkCleanModel", "solve");
     275           0 :   AlwaysAssert(theModel.ndim() >= 2, AipsError);
     276           0 :   const IPosition dataShape = theModel.shape();
     277           0 :   Int npol = 1;
     278           0 :   if (theModel.ndim() >= 3)
     279           0 :     npol = dataShape(2);
     280           0 :   AlwaysAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
     281             :   
     282             :   // Determine the number of polarisations
     283             : //   theLog << "Data has " << npol << " polarisations" << LogIO::POST;
     284             :     
     285             :   // compute the current residual image (using an FFT)
     286           0 :   Array<Float> residual;
     287           0 :   eqn.residual(residual, *this);
     288             :   
     289             :   // Determine the psf patch to use 
     290           0 :   Matrix<Float> psfPatch;
     291             :   Float maxExtPsf;
     292           0 :   maxExtPsf = getPsfPatch(psfPatch, eqn);
     293             : //   theLog << "PsfPatch shape is: " << psfPatch.shape() 
     294             : //       << " and has a maximum exterior sidelobe of " 
     295             : //       << maxExtPsf << LogIO::POST;
     296             :   
     297             :   // Declare variables needed inside the following while loop
     298             :   Float minLimit;                 // the min flux limit when using the
     299             :                                   // maximum number of active pixels
     300             :   Int numPix;                     // the number of Active pixels
     301           0 :   Int maxNumPix = 0;              // The max. number of active pixels ever used
     302           0 :   uInt numIterations = theInitialNumberIterations;
     303             :                                   // Number of Iterations done so far
     304             :   uInt numMinorIterations;        // The number of minor iterations done/todo
     305           0 :   uInt numMajorCycles = 0;        // The number of major cycles done
     306           0 :   uInt maxNumberMinorIterations = 0;// The max. number of min. iterations
     307             :                                    // ever used
     308           0 :   Matrix<Float> pixelValue;       // cache of "active" pixel values
     309           0 :   Matrix<Int> pixelPos;           // cache of "active" pixel positions
     310           0 :   Float Fmn=1;                    // The "uncertainty" factor 
     311             :   Float fluxLimit;                // The fluxlimit for the current major cycle
     312           0 :   Float totalFlux = 0;
     313             : 
     314             :   // Note that a Matrix is used rather than say a Vector of IPositions as
     315             :   // it allows the inner loop (in doMinorIterations()) to be more highly
     316             :   // optimised (using pointers)
     317             : 
     318             :   // find its maximum value of the residual
     319           0 :   Float maxRes = maxResidual(residual);
     320             : 
     321           0 :   theLog << "Initial maximum residual: " << maxRes << LogIO::POST;
     322             :   // if flux limit or iteration limit reached then bail out. 
     323           0 :   Bool userHalt = false;
     324           0 :   while ((Int(numIterations) < numberIterations()) && 
     325           0 :          (maxRes > threshold()) &&
     326           0 :          ((theMaxNumberMajorCycles<0)||(numMajorCycles<(uInt)theMaxNumberMajorCycles)) &&
     327           0 :          userHalt == false){
     328             : 
     329             :     // determine the fluxlimit for this major cycle
     330             :     // choose fluxlimit for residuals to be considered in minor iterations
     331             :     // don't consider residuals below maxRes*(value of maxPsf at outside the 
     332             :     // patch)
     333           0 :     fluxLimit = maxRes * maxExtPsf;
     334             : //     theLog << "Fluxlimit determined using the Maximum exterior Psf: " 
     335             : //         << fluxLimit << LogIO::POST;
     336             :     // See if this flux limit needs to be modified because it selects too
     337             :     // many pixels.
     338           0 :     minLimit = biggestResiduals(maxRes, theMaxNumPix, fluxLimit, residual);
     339             : //     theLog << "Fluxlimit determined using the maximum number active pixels: " 
     340             : //         << minLimit << endl;
     341           0 :     fluxLimit = max(fluxLimit, minLimit);
     342           0 :     fluxLimit /=3.0; //This factor was found empirically as
     343             :                      // as it it was too conservative in the minor loop        
     344             : //     theLog << "Final Fluxlimit: " << fluxLimit << LogIO::POST;
     345             :     
     346             :     // Copy all the active pixels into separate areas for better memory
     347             :     // management and quicker indexing.
     348           0 :     numPix = cacheActivePixels(pixelValue, pixelPos, residual,
     349           0 :                       max(fluxLimit,threshold()));
     350             :     // The numpix calculated here frequently differs 
     351             :     // from the number calculated using the histogram, because of the
     352             :     // quantisation of the flux levels in the histogram, and the imposition
     353             :     // of an external fluxlevel.
     354           0 :     if (numPix > 0) {
     355             : //       theLog <<"Major cycle has "<< numPix << " active residuals, "
     356             : //           << "a Fluxlimit of " << max(fluxLimit,threshold()) << endl;
     357             :       // Start of minor cycles
     358           0 :       numMinorIterations = min(theMaxNumberMinorIterations,
     359           0 :                                numberIterations()-numIterations);
     360           0 :       doMinorIterations(theModel, pixelValue, pixelPos, numPix, 
     361             :                         psfPatch, fluxLimit, numMinorIterations, 
     362             :                         Fmn, numIterations, totalFlux);
     363           0 :       numIterations += numMinorIterations;
     364             : //       theLog << "Clean has used " << numIterations << " Iterations" ;
     365           0 :       maxNumberMinorIterations = max(maxNumberMinorIterations,
     366             :                                      numMinorIterations);
     367           0 :       maxNumPix = max(maxNumPix, numPix);
     368             :       // Now do a  major cycle
     369           0 :       eqn.residual(residual, *this);
     370             : 
     371             :       // find the new maximum residual 
     372           0 :       maxRes = maxResidual(residual);
     373           0 :       theLog << "Iteration: " << numIterations
     374           0 :              << ", Maximum residual=" << maxRes << LogIO::POST;
     375             : //           << " Flux limit=" << max(fluxLimit,threshold()) 
     376             : //           << ", " << numPix << " Active pixels" << LogIO::POST;
     377             :       
     378             : //       theLog << " to get to a maximum residual of " << maxRes << LogIO::POST;
     379             : 
     380             :       // Count the number of major cycles
     381           0 :       numMajorCycles++;
     382             :     }
     383             :     else{
     384           0 :       theLog << LogIO::WARN 
     385             :              << "Zero Pixels selected with a Fluxlimit of " << fluxLimit
     386           0 :              << " and a maximum Residual of " << maxRes << LogIO::POST;
     387           0 :       userHalt=true;
     388             :     }
     389           0 :     userHalt = userHalt || stopnow();
     390             :   }
     391           0 :   setThreshold(maxRes);
     392           0 :   setNumberIterations(numIterations);
     393           0 :   theMaxNumPix = maxNumPix;
     394           0 :   theMaxNumberMinorIterations = maxNumberMinorIterations;
     395           0 :   return true;
     396           0 : };
     397             : 
     398             : //----------------------------------------------------------------------
     399           0 : Bool ClarkCleanModel::singleSolve(ConvolutionEquation & eqn,
     400             :                                   Array<Float>& residual){
     401           0 :   theLog << LogOrigin("ClarkCleanModel", "singleSolve");
     402           0 :   AlwaysAssert(theModel.ndim() >= 2, AipsError);
     403           0 :   const IPosition dataShape = theModel.shape();
     404           0 :   Int npol = 1;
     405           0 :   if (theModel.ndim() >= 3)
     406           0 :     npol = dataShape(2);
     407           0 :   AlwaysAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
     408             :   
     409             :   // Determine the number of polarisations
     410             : //   theLog << "Data has " << npol << " polarisations" << LogIO::POST;
     411             :     
     412             :   // Determine the psf patch to use 
     413           0 :   Matrix<Float> psfPatch;
     414             :   Float maxExtPsf;
     415           0 :   maxExtPsf = getPsfPatch(psfPatch, eqn);
     416             : //   theLog << "PsfPatch shape is: " << psfPatch.shape() 
     417             : //       << " and has a maximum exterior sidelobe of " 
     418             : //       << maxExtPsf << LogIO::POST;
     419             :   
     420             :   // Declare variables needed inside the following while loop
     421             :   Float minLimit;                 // the min flux limit when using the
     422             :                                   // maximum number of active pixels
     423             :   Int numPix;                     // the number of Active pixels
     424           0 :   Int maxNumPix = 0;              // The max. number of active pixels ever used
     425           0 :   uInt numIterations = theInitialNumberIterations;
     426             :                                   // Number of Iterations done so far
     427             :   uInt numMinorIterations;        // The number of minor iterations done/todo
     428           0 :   uInt maxNumberMinorIterations = 0;// The max. number of min. iterations
     429             :                                    // ever used
     430           0 :   Matrix<Float> pixelValue;       // cache of "active" pixel values
     431           0 :   Matrix<Int> pixelPos;           // cache of "active" pixel positions
     432           0 :   Float Fmn=1;                    // The "uncertainty" factor 
     433             :   Float fluxLimit;                // The fluxlimit for the current major cycle
     434           0 :   Float totalFlux = 0;
     435             : 
     436             :   // Note that a Matrix is used rather than say a Vector of IPositions as
     437             :   // it allows the inner loop (in doMinorIterations()) to be more highly
     438             :   // optimised (using pointers)
     439             : 
     440             :   // find its maximum value of the residual
     441           0 :   Float maxRes = maxResidual(residual);
     442             : 
     443             :   // move this to later TT
     444             :   //theLog << "Initial maximum residual: " << maxRes << LogIO::POST;
     445             :   //
     446             :   // if flux limit or iteration limit reached then bail out. 
     447             :   
     448             :   // determine the fluxlimit for this major cycle
     449             :   // choose fluxlimit for residuals to be considered in minor iterations
     450             :   // don't consider residuals below maxRes*(value of maxPsf at outside the 
     451             :   // patch)
     452           0 :   fluxLimit = maxRes * maxExtPsf;
     453             :   //     theLog << "Fluxlimit determined using the Maximum exterior Psf: " 
     454             :   //       << fluxLimit << LogIO::POST;
     455             :   // See if this flux limit needs to be modified because it selects too
     456             :   // many pixels.
     457           0 :   minLimit = biggestResiduals(maxRes, theMaxNumPix, fluxLimit, residual);
     458             :   //     theLog << "Fluxlimit determined using the maximum number active pixels: " 
     459             :   //       << minLimit << endl;
     460           0 :   fluxLimit = max(fluxLimit, minLimit);
     461           0 :   fluxLimit /= 8.0; //emepirically found that fluxlimit was too
     462             :                     // too conservative  
     463             :   //     theLog << "Final Fluxlimit: " << fluxLimit << LogIO::POST;
     464             :   
     465             :   // Copy all the active pixels into separate areas for better memory
     466             :   // management and quicker indexing.
     467           0 :   numPix = cacheActivePixels(pixelValue, pixelPos, residual,
     468           0 :                              max(fluxLimit,threshold()));
     469             :   // The numpix calculated here frequently differs 
     470             :   // from the number calculated using the histogram, because of the
     471             :   // quantisation of the flux levels in the histogram, and the imposition
     472             :   // of an external fluxlevel.
     473           0 :   if (numPix > 0) {
     474             :     //       theLog <<"Major cycle has "<< numPix << " active residuals, "
     475             :     //       << "a Fluxlimit of " << max(fluxLimit,threshold()) << endl;
     476             :     // Start of minor cycles
     477           0 :     theLog << "Initial maximum residual: " << maxRes << LogIO::POST;
     478           0 :     numMinorIterations = min(theMaxNumberMinorIterations,
     479           0 :                              numberIterations()-numIterations);
     480           0 :     doMinorIterations(theModel, pixelValue, pixelPos, numPix, 
     481             :                       psfPatch, fluxLimit, numMinorIterations, 
     482             :                       Fmn, numIterations, totalFlux);
     483           0 :     numIterations += numMinorIterations;
     484             :     //       theLog << "Clean has used " << numIterations << " Iterations" ;
     485           0 :     maxNumberMinorIterations = max(maxNumberMinorIterations,
     486             :                                    numMinorIterations);
     487           0 :     maxNumPix = max(maxNumPix, numPix);
     488             :   }
     489             :   /*
     490             :   else
     491             :     theLog << LogIO::WARN 
     492             :            << "Zero Pixels selected with a Fluxlimit of " << fluxLimit
     493             :            << " and a maximum Residual of " << maxRes << LogIO::POST;
     494             :   */
     495           0 :   setNumberIterations(numIterations);
     496           0 :   theMaxNumPix = maxNumPix;
     497           0 :   theMaxNumberMinorIterations = maxNumberMinorIterations;
     498             : 
     499           0 :   return true;
     500           0 : };
     501             : //----------------------------------------------------------------------
     502           0 : void ClarkCleanModel::setPsfPatchSize(const IPosition & psfPatchSize){
     503           0 :   thePsfPatchSize=psfPatchSize;
     504           0 : }; 
     505             : //----------------------------------------------------------------------
     506           0 : IPosition ClarkCleanModel::getPsfPatchSize(){
     507           0 :   return thePsfPatchSize;
     508             : }; 
     509             : //----------------------------------------------------------------------
     510           0 : void ClarkCleanModel::setHistLength(const uInt HistBins ){
     511           0 :   theHistBins=HistBins;
     512           0 : }; 
     513             : //----------------------------------------------------------------------
     514           0 : uInt ClarkCleanModel::getHistLength(){
     515           0 :   return theHistBins;
     516             : }; 
     517             : //----------------------------------------------------------------------
     518           0 : void ClarkCleanModel::setMaxNumberMinorIterations(const uInt maxNumMinorIterations){
     519           0 :   theMaxNumberMinorIterations=maxNumMinorIterations;
     520           0 : }; 
     521             : //----------------------------------------------------------------------
     522           0 : uInt ClarkCleanModel::getMaxNumberMinorIterations(){
     523           0 :   return theMaxNumberMinorIterations;
     524             : };
     525             : //----------------------------------------------------------------------
     526           0 : void ClarkCleanModel::setInitialNumberIterations(const uInt initialNumberIterations){
     527           0 :   theInitialNumberIterations=initialNumberIterations;
     528           0 : }; 
     529             : //----------------------------------------------------------------------
     530           0 : uInt ClarkCleanModel::getInitialNumberIterations(){
     531           0 :   return theInitialNumberIterations;
     532             : };
     533             : //----------------------------------------------------------------------
     534           0 : void ClarkCleanModel::setMaxNumberMajorCycles(const uInt maxNumMajorCycles){
     535           0 :   theMaxNumberMajorCycles=maxNumMajorCycles;
     536           0 : }; 
     537             : //----------------------------------------------------------------------
     538           0 : uInt ClarkCleanModel::getMaxNumberMajorCycles(){
     539           0 :   return theMaxNumberMajorCycles;
     540             : };
     541             : //----------------------------------------------------------------------
     542           0 : void ClarkCleanModel::setMaxNumPix(const uInt maxNumPix ){
     543           0 :   theMaxNumPix=maxNumPix;
     544           0 : }; 
     545             : //----------------------------------------------------------------------
     546           0 : uInt ClarkCleanModel::getMaxNumPix(){
     547           0 :   return theMaxNumPix;
     548             : }; 
     549             : //----------------------------------------------------------------------
     550           0 : void ClarkCleanModel::setMaxExtPsf(const Float maxExtPsf ){
     551           0 :   theMaxExtPsf=maxExtPsf;
     552           0 : };
     553             : //----------------------------------------------------------------------
     554           0 : Float ClarkCleanModel::getMaxExtPsf(){
     555           0 :   return theMaxExtPsf;
     556             : }; 
     557             : //----------------------------------------------------------------------
     558           0 : void ClarkCleanModel::setSpeedup(const Float speedup ){
     559           0 :   theSpeedup=speedup;
     560           0 : }; 
     561             : //----------------------------------------------------------------------
     562           0 : Float ClarkCleanModel::getSpeedup(){
     563           0 :   return theSpeedup;
     564             : }; 
     565             : //----------------------------------------------------------------------
     566           0 : void ClarkCleanModel::setCycleSpeedup(const Float speedup ){
     567           0 :   theCycleSpeedup=speedup;
     568           0 : }; 
     569             : //----------------------------------------------------------------------
     570           0 : Float ClarkCleanModel::getCycleSpeedup(){
     571           0 :   return theCycleSpeedup;
     572             : }; 
     573             : //----------------------------------------------------------------------
     574           0 : void ClarkCleanModel::setChoose(const Bool choose ){
     575           0 :   theChoose=choose;
     576           0 : }; 
     577             : //----------------------------------------------------------------------
     578           0 : Bool ClarkCleanModel::getChoose(){
     579           0 :   return theChoose;
     580             : }; 
     581             : //----------------------------------------------------------------------
     582           0 : void ClarkCleanModel::doMinorIterations(Array<Float> & model, 
     583             :                                         Matrix<Float> & pixVal, 
     584             :                                         const Matrix<Int> & pixPos, 
     585             :                                         const Int numPix,
     586             :                                         Matrix<Float> & psfPatch,
     587             :                                         Float fluxLimit, 
     588             :                                         uInt & numberIterations, 
     589             :                                         Float Fmn, 
     590             :                                         const uInt totalIterations,
     591             :                                         Float &totalFlux){
     592           0 :   DebugAssert(model.ndim() >= 2, AipsError);
     593           0 :   DebugAssert(model.shape()(0) > 0, AipsError);
     594           0 :   DebugAssert(model.shape()(1) > 0, AipsError);
     595           0 :   Int npol = 1;
     596           0 :   if (model.ndim() >= 3)
     597           0 :     npol = model.shape()(2);
     598           0 :   DebugAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
     599           0 :   DebugAssert(model.shape()(3) == 1, AipsError);
     600           0 :   DebugAssert(Int(pixVal.nrow()) == npol, AipsError);
     601           0 :   DebugAssert(numPix <= Int(pixVal.ncolumn()), AipsError);
     602           0 :   DebugAssert(0 < numPix , AipsError);
     603           0 :   DebugAssert(pixPos.nrow() == 2, AipsError);
     604           0 :   DebugAssert(pixPos.ncolumn() == pixVal.ncolumn(), AipsError);
     605           0 :   DebugAssert(psfPatch.nrow() > 0, AipsError);
     606           0 :   DebugAssert(psfPatch.ncolumn() > 0, AipsError);
     607             :   
     608             : //   theLog << LogOrigin("ClarkCleanModel", "doMinorIterations");
     609             :   // Find the largest residual and its position.
     610           0 :   Vector<Float> maxRes(npol);
     611           0 :   Vector<Int> maxPos(2);
     612             :   Float absRes;
     613             :   Float signedAbsRes;
     614             :   Int offRes;
     615           0 :   maxVect(maxRes, absRes, offRes, pixVal, numPix);
     616           0 :   maxPos = pixPos.column(offRes);
     617             :   // declare variables used inside the main loop
     618           0 :   Int curIter = 0;
     619           0 :   Float iterFluxLimit = max(fluxLimit, threshold());
     620           0 :   Float Fac = pow(fluxLimit/absRes, theSpeedup);
     621           0 :   IPosition position(model.ndim(), 0);
     622             : //   theLog << "Initial maximum residual:" << maxRes 
     623             : //       << " (" << absRes << ") "
     624             : //       << " @ " << maxPos << endl;
     625             :   
     626             :   // Do the minor Iterations
     627           0 :   while ((curIter < Int(numberIterations)) && (absRes > iterFluxLimit)){
     628           0 :     iterFluxLimit = max(fluxLimit, threshold());  // threshold() changes now!
     629           0 :     maxRes *= gain();
     630           0 :     totalFlux += maxRes(0);
     631             :     // Add the new component to the current model
     632           0 :     position(0) = maxPos(0);
     633           0 :     position(1) = maxPos(1);
     634           0 :     if (model.ndim() >= 3)
     635           0 :       for (Int p = 0; p < npol; p++){
     636           0 :         position(2) = p;
     637             : //      theLog << "Model " << model(position) << " @ " << position;
     638           0 :         model(position) += maxRes(p);
     639             : //      theLog << " -> " << model(position);
     640             :       }
     641             :     else {
     642             : //       theLog << "Model " << model(position) << " @ " << position;
     643           0 :       model(position) += maxRes(0);
     644             : //       theLog << " -> " << model(position);
     645             :     }
     646             :     
     647             : //     theLog << " Subtracting:" << maxRes 
     648             : //         << " @ " << position;
     649             :     // Subtract the component from the current list of active pixels
     650           0 :     subtractComponent(pixVal, pixPos, numPix, 
     651             :                       maxRes, maxPos, psfPatch);
     652             :     // We have now done an iteration
     653           0 :     curIter++;
     654           0 :     theIterCounter++;
     655             :     // find the next residual
     656           0 :     maxVect(maxRes, absRes, offRes, pixVal, numPix);
     657           0 :     maxPos = pixPos.column(offRes);
     658             : //     theLog << " After Iteration: " << curIter 
     659             : //         << " the Maximum residual is:" << maxRes 
     660             : //         << " (" << absRes << ") "
     661             : //         << " @ " << maxPos << LogIO::POST;
     662             :     // Update the uncertainty factors and fluxlimits
     663           0 :     Fmn += Fac/Float(totalIterations+curIter);
     664           0 :     iterFluxLimit = max(fluxLimit * Fmn, threshold());
     665             : 
     666           0 :     if (itsProgressPtr) {
     667             :       try {
     668             :         // if this does not throw an exception, we are in business
     669           0 :         itsProgressPtr->hasPGPlotter();  
     670           0 :         signedAbsRes = absRes * maxRes(0)/abs( maxRes(0) );
     671           0 :         itsProgressPtr->
     672           0 :           info(false, (Int)(totalIterations+curIter),  (Int)numberIterations,
     673           0 :                signedAbsRes, IPosition(2,maxPos(0),maxPos(1)),
     674           0 :                totalFlux, false, itsJustStarting );
     675           0 :         itsJustStarting = false;
     676           0 :       } catch (AipsError x) {
     677             :         // if it throw an exception, do nothing
     678           0 :       } 
     679             :     }
     680             :   }
     681             :   // Data returned to the main routine
     682           0 :   numberIterations = curIter;
     683           0 :   fluxLimit = absRes;
     684           0 :   itsMaxRes = maxRes(0);
     685           0 : };
     686             : //----------------------------------------------------------------------
     687           0 : Int ClarkCleanModel::
     688             : cacheActivePixels(Matrix<Float> & pixVal, Matrix<Int> & pixPos, 
     689             :                   const Array<Float> & data, const Float fluxLimit){
     690           0 :   DebugAssert(data.ndim() >= 2, AipsError);
     691           0 :   const IPosition dataShape = data.shape();
     692           0 :   const Int nx = dataShape(0);
     693           0 :   const Int ny = dataShape(1);
     694           0 :   Int npol = 1;
     695           0 :   if (data.ndim() >= 3)
     696           0 :     npol = dataShape(2);
     697           0 :   DebugAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
     698           0 :   DebugAssert(nx > 0, AipsError);
     699           0 :   DebugAssert(ny > 0, AipsError);
     700           0 :   DebugAssert(pixVal.ncolumn() == pixPos.ncolumn(), AipsError);
     701             : 
     702           0 :   Int nBigPix = pixVal.ncolumn();
     703             :   Bool dataCopy, valCopy, posCopy;
     704           0 :   const Float * dataPtr = data.getStorage(dataCopy);
     705           0 :   Float * valPtr = pixVal.getStorage(valCopy);
     706           0 :   Int * posPtr = pixPos.getStorage(posCopy);
     707             : 
     708           0 :   if (theMask.nelements() == 0) {
     709           0 :     switch (npol){
     710           0 :     case 1:
     711           0 :       getbigf(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, &nx, &ny);
     712           0 :       break;
     713           0 :     case 2:
     714           0 :       getbig2f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, &nx, &ny);
     715           0 :       break;
     716           0 :     case 4:
     717           0 :       getbig4f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, &nx, &ny);
     718             :     }
     719           0 :     if (nBigPix > 0){ // I could be more efficient about this
     720           0 :       nBigPix += pixVal.ncolumn();
     721           0 :       pixVal.putStorage(valPtr, valCopy); pixPos.putStorage(posPtr, posCopy);
     722           0 :       pixVal.resize(npol, nBigPix);
     723           0 :       pixPos.resize(2, nBigPix);
     724           0 :       valPtr = pixVal.getStorage(valCopy); posPtr = pixPos.getStorage(posCopy);
     725           0 :       switch (npol){
     726           0 :       case 1:
     727           0 :         getbigf(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, &nx, &ny);
     728           0 :         break;
     729           0 :       case 2:
     730           0 :         getbig2f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, &nx, &ny);
     731           0 :         break;
     732           0 :       case 4:
     733           0 :         getbig4f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, &nx, &ny);
     734             :       }
     735           0 :       AlwaysAssert(nBigPix == 0, AipsError);
     736             :     }
     737             :   }
     738             :   else {
     739             :     Bool maskCopy;
     740           0 :     const Float * maskPtr = theMask.getStorage(maskCopy);
     741           0 :     switch (npol){
     742           0 :     case 1:
     743           0 :       getbimf(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, maskPtr, &nx, &ny);
     744           0 :       break;
     745           0 :     case 2:
     746           0 :       getbim2f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, maskPtr, &nx, &ny);
     747           0 :       break;
     748           0 :     case 4:
     749           0 :       getbim4f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, maskPtr, &nx, &ny);
     750             :     }
     751           0 :     if (nBigPix > 0){ // I could be more effecient about this
     752           0 :       nBigPix += pixVal.ncolumn();
     753           0 :       pixVal.putStorage(valPtr, valCopy); pixPos.putStorage(posPtr, posCopy);
     754           0 :       pixVal.resize(npol, nBigPix);
     755           0 :       pixPos.resize(2, nBigPix);
     756           0 :       valPtr = pixVal.getStorage(valCopy); posPtr = pixPos.getStorage(posCopy);
     757           0 :       switch (npol){
     758           0 :       case 1:
     759           0 :         getbimf(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, maskPtr, &nx, &ny);
     760           0 :         break;
     761           0 :       case 2:
     762           0 :         getbim2f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, maskPtr, &nx, &ny);
     763           0 :         break;
     764           0 :       case 4:
     765           0 :         getbim4f(valPtr, posPtr, &nBigPix, &fluxLimit, dataPtr, maskPtr, &nx, &ny);
     766             :       }
     767           0 :       AlwaysAssert(nBigPix == 0, AipsError);
     768             :     }
     769           0 :     theMask.freeStorage(maskPtr, dataCopy);
     770             :   }
     771           0 :   pixVal.putStorage(valPtr, valCopy);
     772           0 :   pixPos.putStorage(posPtr, posCopy);
     773           0 :   data.freeStorage(dataPtr, dataCopy);
     774           0 :   DebugAssert(nBigPix <= 0 && (nBigPix + Int(pixVal.ncolumn())) >= Int(0), AipsError);
     775           0 :   return pixVal.ncolumn() + nBigPix;
     776           0 : };
     777             : //----------------------------------------------------------------------
     778             : // make histogram of absolute values in array
     779           0 : void ClarkCleanModel::absHistogram(Vector<Int> & hist,
     780             :                                    Float & minVal, 
     781             :                                    Float & maxVal, 
     782             :                                    const Array<Float> & data) {
     783           0 :   DebugAssert(data.ndim() >= 2, AipsError);
     784           0 :   const IPosition dataShape = data.shape();
     785           0 :   const Int nx = dataShape(0);
     786           0 :   const Int ny = dataShape(1);
     787           0 :   Int npol = 1;
     788           0 :   if (data.ndim() >= 3)
     789           0 :     npol = dataShape(2);
     790           0 :   const Int npix = nx*ny;
     791           0 :   DebugAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
     792           0 :   DebugAssert(nx > 0, AipsError);
     793           0 :   DebugAssert(ny > 0, AipsError);
     794             :   Bool dataCopy, histCopy;
     795           0 :   const Int nbins = hist.nelements();
     796           0 :   const Float * dataPtr = data.getStorage(dataCopy);
     797           0 :   Int * histPtr = hist.getStorage(histCopy);
     798           0 :   hist = 0;
     799           0 :   if (theMask.nelements() == 0)
     800           0 :     switch (npol){
     801           0 :     case 1:
     802           0 :       abshisf(histPtr, &minVal, &maxVal, &nbins, dataPtr, &npix);
     803           0 :       break;
     804           0 :     case 2:
     805           0 :       abshis2f(histPtr, &minVal, &maxVal, &nbins, dataPtr, &npix);
     806           0 :       break;
     807           0 :     case 4:
     808           0 :       abshis4f(histPtr, &minVal, &maxVal, &nbins, dataPtr, &npix);
     809             :     }
     810             :   else{
     811             :     Bool maskCopy;
     812           0 :     const Float * maskPtr = theMask.getStorage(maskCopy);
     813           0 :     switch (npol){
     814           0 :     case 1:
     815           0 :       abshimf(histPtr, &minVal, &maxVal, &nbins, dataPtr, maskPtr, &npix);
     816           0 :       break;
     817           0 :     case 2:
     818           0 :       abshim2f(histPtr, &minVal, &maxVal, &nbins, dataPtr, maskPtr, &npix);
     819           0 :       break;
     820           0 :     case 4:
     821           0 :       abshim4f(histPtr, &minVal, &maxVal, &nbins, dataPtr, maskPtr, &npix);
     822             :     }
     823           0 :     theMask.freeStorage(maskPtr, dataCopy);
     824             :   }
     825           0 :   data.freeStorage(dataPtr, dataCopy);
     826           0 :   hist.putStorage(histPtr, histCopy);
     827             :   
     828           0 : };
     829             : //----------------------------------------------------------------------
     830             : // Determine the flux limit if we only select the maxNumPix biggest
     831             : // residuals. Flux limit is not exact due to quantising by the histogram
     832           0 : Float ClarkCleanModel::biggestResiduals(Float & maxRes,
     833             :                                         const uInt maxNumPix, 
     834             :                                         const Float fluxLimit,
     835             :                                         const Array<Float> & residual) {
     836             : //   theLog << LogOrigin("ClarkCleanModel", "biggestResiduals");
     837             :   // Calculate the histogram of the absolute value of the residuals
     838           0 :   Vector<Int> resHist(theHistBins); 
     839             : //   theLog << "Created a histogram with " << resHist.nelements() 
     840             : //       << " bins" << endl;;
     841             :   Float minRes;
     842           0 :   absHistogram(resHist, minRes, maxRes, residual);
     843             : //    theLog << "Min/Max residuals are: " << minRes << " -> " << maxRes<< endl;
     844             :   
     845             :   // Deteremine how far we need to scan the histogram, before we reach the
     846             :   // flux cutoff imposed by the maximum exterior psf.
     847             :   Int lowbin;
     848           0 :   if (fluxLimit <= minRes)
     849           0 :     lowbin = 0;
     850           0 :   else if (fluxLimit >= maxRes)
     851           0 :     lowbin = theHistBins - 1;
     852             :   else
     853           0 :     lowbin=Int(theHistBins*(fluxLimit-minRes)/(maxRes-minRes));
     854             : 
     855             : //   theLog << "Select at most " << maxNumPix 
     856             : //       << " pixels with the lowest bin being " << lowbin << endl;
     857             : 
     858           0 :   Int numPix = 0;
     859           0 :   Int curBin = theHistBins - 1;
     860           0 :   while (curBin >= lowbin && numPix <= Int(maxNumPix)){
     861           0 :     numPix += resHist(curBin);
     862           0 :     curBin--;
     863             :   }
     864           0 :   curBin++;
     865             :   
     866             :   // Try to ensure we have maxNumPix or fewer residuals selected UNLESS
     867             :   // the topmost bin contains more than maxNumPix pixels. Then use all the
     868             :   // pixels in the topmost bin.
     869           0 :   if (numPix > Int(maxNumPix) && curBin != Int(theHistBins - 1)){
     870           0 :     numPix -= resHist(curBin); 
     871           0 :     curBin++;
     872             :   }
     873             : //   theLog << "Selected " << numPix << " pixels from the top " 
     874             : //       << theHistBins - curBin << " bins" << LogIO::POST;
     875             :   
     876           0 :   return minRes+curBin*(maxRes-minRes)/Float(theHistBins);
     877           0 : }
     878             : //----------------------------------------------------------------------
     879             : // Work out the size of the Psf patch to use. 
     880           0 : Float ClarkCleanModel::getPsfPatch(Array<Float>& psfPatch, 
     881             :                                    ConvolutionEquation& eqn) {
     882             : 
     883             :   // Determine the maximum possible size that should be used. Sizes greater
     884             :   // than the maximum size cannot affect the cleaning and will not be used,
     885             :   // even if the user requests it!
     886           0 :   IPosition psfSize(eqn.psfSize());
     887           0 :   uInt ndim = psfSize.nelements();
     888           0 :   IPosition modelSize(theModel.shape().getFirst(ndim));
     889           0 :   IPosition maxSize(min(2*modelSize.asVector(), 
     890           0 :                         psfSize.asVector()));
     891             :   // See if the user has set a psfPatch size, and if it is less than the
     892             :   // maximum size use it.
     893           0 :   IPosition psfPatchSize;
     894           0 :   if (thePsfPatchSize.nelements() != 0) {
     895           0 :     psfPatchSize = casacore::min(maxSize.asVector(),
     896           0 :                        thePsfPatchSize.asVector());
     897             :   }
     898             :   else {
     899           0 :     psfPatchSize = maxSize;
     900             :   }
     901             :   // set the psf Patch size to what is actually used. So the user can find out.
     902           0 :   thePsfPatchSize = psfPatchSize;
     903             : 
     904             :   // Now calculate the maximum exterior psf value
     905             :   
     906             :   // This is calculated where possible, otherwise a user supplied value is
     907             :   // used.
     908             : 
     909             :   // Check if Psf is big enough to do a proper calculation
     910           0 :   Array<Float> psf;
     911           0 :   Float maxExtPsf(0);
     912           0 :   if (max((2*modelSize-psfSize).asVector()) <= 0){
     913           0 :     if (psfPatchSize.isEqual(2*modelSize)) {
     914           0 :       maxExtPsf = Float(0); // Here the PsfPatch is used is big enough so
     915             :                             // that exterior sidelobes are irrelevant
     916             :     }
     917             :     else { // Calculate the exterior sidelobes
     918           0 :       eqn.evaluate(psf, psfSize/2, Float(1), psfSize);
     919           0 :       maxExtPsf = absMaxBeyondDist(psfPatchSize/2, psfSize/2, psf);
     920             :     }
     921             :   }
     922             :   else { // psf is not big enough so try and estimate something sensible
     923           0 :     if (psfPatchSize.isEqual(psfSize)) {
     924           0 :       maxExtPsf = theMaxExtPsf; // must use the user supplied value as it is
     925             :                                 // impossible to estimate anything
     926             :     }
     927             :     else { // try and estimate the ext. Psf and use the maximum of this
     928             :            // value and the user supplied value
     929           0 :       eqn.evaluate(psf, psfSize/2, Float(1), psfSize);
     930           0 :       maxExtPsf = max(absMaxBeyondDist(psfPatchSize/2, psfSize/2, psf),
     931             :                       theMaxExtPsf);
     932             :     }
     933             :   }
     934           0 :   eqn.flushPsf(); // Tell the convolution equation to release the cached psf
     935             :   // set the max external psf Value to what is actually used. 
     936             :   // So the user can find out.
     937           0 :   theMaxExtPsf = maxExtPsf;
     938             :   // Now get a psf of the required size
     939           0 :   eqn.evaluate(psfPatch, psfPatchSize/2, Float(1), psfPatchSize);
     940           0 :   return maxExtPsf;
     941           0 : };
     942             : //----------------------------------------------------------------------
     943             : // The maximum residual is the absolute maximum.
     944           0 : Float ClarkCleanModel::maxResidual(const Array<Float> & residual) {
     945           0 :   DebugAssert(residual.ndim() >= 2, AipsError);
     946           0 :   const IPosition dataShape = residual.shape();
     947           0 :   const Int nx = dataShape(0);
     948           0 :   const Int ny = dataShape(1);
     949           0 :   Int npol = 1;
     950           0 :   if (residual.ndim() >= 3)
     951           0 :     npol = dataShape(2);
     952           0 :   const Int npix = nx*ny;
     953           0 :   DebugAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
     954           0 :   DebugAssert(nx > 0, AipsError);
     955           0 :   DebugAssert(ny > 0, AipsError);
     956             : 
     957             :   Float maxVal;
     958             :   Bool dataCopy;
     959           0 :   const Float * dataPtr = residual.getStorage(dataCopy);
     960           0 :   if (theMask.nelements() == 0)
     961           0 :     switch (npol){
     962           0 :     case 1:
     963           0 :       maxabsf(&maxVal, dataPtr, &npix);
     964           0 :       break;
     965           0 :     case 2:
     966           0 :       maxabs2f(&maxVal, dataPtr, &npix);
     967           0 :       break;
     968           0 :     case 4:
     969           0 :       maxabs4f(&maxVal, dataPtr, &npix);
     970             :     }
     971             :   else {
     972             :     Bool maskCopy;
     973           0 :     const Float * maskPtr = theMask.getStorage(maskCopy);
     974           0 :     switch (npol){
     975           0 :     case 1:
     976           0 :       maxabmf(&maxVal, dataPtr, maskPtr, &npix);
     977           0 :       break;
     978           0 :     case 2:
     979           0 :       maxabm2f(&maxVal, dataPtr, maskPtr, &npix);
     980           0 :       break;
     981           0 :     case 4:
     982           0 :       maxabm4f(&maxVal, dataPtr, maskPtr, &npix);
     983             :     }
     984           0 :     theMask.freeStorage(maskPtr, dataCopy);
     985             :   }
     986           0 :   residual.freeStorage(dataPtr, dataCopy);
     987           0 :   return maxVal;
     988           0 : };
     989             : //----------------------------------------------------------------------
     990           0 : void ClarkCleanModel::maxVect(Vector<Float> & maxVal, 
     991             :                               Float & absVal, 
     992             :                               Int & offset, 
     993             :                               const Matrix<Float> & pixVal, 
     994             :                               const Int numPix) {
     995           0 :   const Int npol = pixVal.nrow();
     996           0 :   DebugAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
     997           0 :   DebugAssert(numPix <= Int(pixVal.ncolumn()), AipsError);
     998           0 :   DebugAssert(0 < numPix , AipsError);
     999             : 
    1000             :   Bool dataCopy, maxCopy;
    1001           0 :   const Float * dataPtr = pixVal.getStorage(dataCopy);
    1002           0 :   Float * maxPtr = maxVal.getStorage(maxCopy);
    1003           0 :   switch (npol){
    1004           0 :   case 1:
    1005           0 :     absmaxf(maxPtr, &absVal, &offset, dataPtr, &numPix);
    1006           0 :     break;
    1007           0 :   case 2:
    1008           0 :     absmax2f(maxPtr, &absVal, &offset, dataPtr, &numPix);
    1009           0 :     break;
    1010           0 :   case 4:
    1011           0 :     absmax4f(maxPtr, &absVal, &offset, dataPtr, &numPix);
    1012             :   }
    1013           0 :   pixVal.freeStorage(dataPtr, dataCopy);
    1014           0 :   maxVal.putStorage(maxPtr, dataCopy);
    1015           0 : };
    1016             : //----------------------------------------------------------------------
    1017           0 : void ClarkCleanModel::subtractComponent(Matrix<Float> & pixVal, 
    1018             :                                         const Matrix<Int> & pixPos,
    1019             :                                         const Int numPix,
    1020             :                                         const Vector<Float> & maxVal,
    1021             :                                         const Vector<Int> & maxPos, 
    1022             :                                         const Matrix<Float> & psf){
    1023           0 :   const Int npol = pixVal.nrow();
    1024           0 :   DebugAssert(npol == 1 || npol == 2 || npol == 4, AipsError);
    1025           0 :   DebugAssert(numPix <= Int(pixVal.ncolumn()), AipsError);
    1026           0 :   DebugAssert(0 < numPix , AipsError);
    1027           0 :   DebugAssert(pixPos.nrow() == 2, AipsError);
    1028           0 :   DebugAssert(pixPos.ncolumn() == pixVal.ncolumn(), AipsError);
    1029           0 :   DebugAssert(Int(maxVal.nelements()) == npol, AipsError);
    1030           0 :   DebugAssert(maxPos.nelements() == 2, AipsError);
    1031           0 :   const Int nx = psf.nrow();
    1032           0 :   const Int ny = psf.ncolumn();
    1033           0 :   DebugAssert(nx > 0, AipsError);
    1034           0 :   DebugAssert(ny > 0, AipsError);
    1035             :   
    1036             :   Bool pixValCopy, pixPosCopy, maxValCopy, maxPosCopy, psfCopy;
    1037           0 :   Float * pixValPtr = pixVal.getStorage(pixValCopy);
    1038           0 :   const Int * pixPosPtr = pixPos.getStorage(pixPosCopy);
    1039           0 :   const Float * maxValPtr = maxVal.getStorage(maxValCopy);
    1040           0 :   const Int * maxPosPtr = maxPos.getStorage(maxPosCopy);
    1041           0 :   const Float * psfPtr = psf.getStorage(psfCopy);
    1042           0 :   switch (npol){
    1043           0 :   case 1:
    1044           0 :     subcomf(pixValPtr, pixPosPtr, &numPix, maxValPtr, maxPosPtr, 
    1045             :             psfPtr, &nx, &ny);
    1046           0 :     break;
    1047           0 :   case 2:
    1048           0 :     subcom2f(pixValPtr, pixPosPtr, &numPix, maxValPtr, maxPosPtr, 
    1049             :              psfPtr, &nx, &ny);
    1050           0 :     break;
    1051           0 :   case 4:
    1052           0 :     subcom4f(pixValPtr, pixPosPtr, &numPix, maxValPtr, maxPosPtr, 
    1053             :              psfPtr, &nx, &ny);
    1054             :   }
    1055           0 :   psf.freeStorage(psfPtr, psfCopy);
    1056           0 :   maxPos.freeStorage(maxPosPtr, maxPosCopy);
    1057           0 :   maxVal.freeStorage(maxValPtr, maxValCopy);
    1058           0 :   pixPos.freeStorage(pixPosPtr, pixPosCopy);
    1059           0 :   pixVal.putStorage(pixValPtr, pixValCopy);
    1060           0 : };
    1061             : //----------------------------------------------------------------------
    1062             : // For an Array make a vector which gives the peak beyond distance n, p(n):
    1063             : // p(0)= central value, p(n)=max value outside hypercube with side 2n-1
    1064             : // Distance is measured from the point centre in the array
    1065           0 : Float ClarkCleanModel::absMaxBeyondDist(const IPosition &maxDist, 
    1066             :                                         const IPosition &centre,
    1067             :                                         const Array<Float> &array){
    1068           0 :   if (maxDist.nelements() != array.ndim()) {
    1069           0 :     throw(ArrayError("Vector<Float> absMaxBeyondDist("
    1070             :                      "const IPosition &maxDist,const IPosition &centre,"
    1071             :                      "const Array<Float> &array) - "
    1072           0 :                      "maxDist dimensionality inconsistent with array"));
    1073             :   }
    1074           0 :   if (array.nelements() == 0) {
    1075           0 :     throw(ArrayError("Vector<Float> absMaxBeyondDist("
    1076             :                      "const IPosition &maxDist,const IPosition &centre,"
    1077             :                      "const Array<Float> &array) - "
    1078           0 :                      "Array has no elements"));     
    1079             :   }
    1080             :   { 
    1081           0 :     Vector<Int> tmp1 = (centre-maxDist).asVector();
    1082           0 :     Vector<Int> tmp2 = (centre+maxDist-array.endPosition()).asVector();
    1083           0 :     if (min(tmp1)<0 || max(tmp2)>0) {
    1084           0 :       throw(ArrayError("Vector<Float> absMaxBeyondDist("
    1085             :                        "const IPosition &maxDist,const IPosition &centre,"
    1086             :                        "const Array<Float> &array) - "
    1087           0 :                        "maxDist too large for Array"));       
    1088             :     }
    1089           0 :   }
    1090             :   // Initialize
    1091           0 :   ReadOnlyVectorIterator<Float> ai(array);
    1092           0 :   Float maxVal(0);
    1093           0 :   uInt n = ai.vector().nelements();
    1094           0 :   uInt start = centre(0) - maxDist(0);
    1095           0 :   uInt end = centre(0) + maxDist(0) + 1;
    1096           0 :   IPosition vecPos(array.ndim());
    1097           0 :   IPosition vecDist(array.ndim());
    1098             :   uInt i;
    1099             : 
    1100             :   // loop though array accumulating maxima for each distance
    1101           0 :   while (! ai.pastEnd()) {
    1102             :     // find the distance of the current vector to the midpoint of the array
    1103           0 :     vecPos=ai.pos(); vecPos(0)=centre(0);
    1104           0 :     vecDist=abs((vecPos-centre).asVector());
    1105             :     // skip if current vector too far from midpoint in any dimension
    1106           0 :     if (max((vecDist-maxDist).asVector()) > 0)
    1107           0 :       for (i=0; i<n; i++) {
    1108           0 :         maxVal=max(maxVal, Float(abs(ai.vector()(i))));
    1109             :       }
    1110             :     else {
    1111           0 :       for (i=0; i<start; i++) {
    1112           0 :         maxVal=max(maxVal, Float(abs(ai.vector()(i))));
    1113             :       }
    1114           0 :       for (i=end; i<n; i++) {
    1115           0 :         maxVal=max(maxVal, Float(abs(ai.vector()(i))));
    1116             :       }
    1117             :     }
    1118           0 :     ai.next();
    1119             :   }
    1120           0 :   return maxVal;
    1121           0 : };
    1122             : 
    1123           0 : Bool ClarkCleanModel::stopnow() {
    1124           0 :   if(theChoose) {
    1125           0 :     Vector<String> choices(2);
    1126           0 :     choices(0)="Continue";
    1127           0 :     choices(1)="Stop Now";
    1128           0 :     choices(2)="Don't ask again";
    1129             :     String choice = Choice::choice("Do you want to continue or stop?",
    1130           0 :                                    choices);
    1131           0 :     if (choice==choices(0)) {
    1132           0 :       return false;
    1133             :     }
    1134           0 :     else if (choice==choices(2)) {
    1135           0 :       setChoose(false);
    1136           0 :       theLog << "Continuing: won't ask again" << LogIO::POST;
    1137           0 :       return false;
    1138             :     }
    1139             :     else {
    1140           0 :       theLog << "Clark clean stopped at user request" << LogIO::POST;
    1141           0 :       return true;
    1142             :     }
    1143           0 :   }
    1144             :   else {
    1145           0 :     return false;
    1146             :   }
    1147             : }
    1148             : 
    1149           0 : Float ClarkCleanModel::threshold()
    1150             : {
    1151           0 :   Float thresh = Iterate::threshold();
    1152           0 :   if (theCycleSpeedup > 0.0) {
    1153           0 :     thresh = thresh * pow(2.0, ((Double)(theIterCounter)/theCycleSpeedup) );
    1154             :   }
    1155           0 :   return thresh;
    1156             : };
    1157             : 
    1158             : } //# NAMESPACE CASA - END
    1159             : 

Generated by: LCOV version 1.16