LCOV - code coverage report
Current view: top level - synthesis/MeasurementComponents - CSCleanImageSkyModel.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 303 0.0 %
Date: 2024-11-06 17:42:47 Functions: 0 6 0.0 %

          Line data    Source code
       1             : //# CSCleanImageSkyModel.cc: Implementation of CSCleanImageSkyModel class
       2             : //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,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 <casacore/casa/Arrays/ArrayMath.h>
      29             : #include <casacore/casa/Arrays/Matrix.h>
      30             : #include <synthesis/MeasurementComponents/CSCleanImageSkyModel.h>
      31             : #include <casacore/coordinates/Coordinates/DirectionCoordinate.h>
      32             : #include <casacore/images/Images/PagedImage.h>
      33             : #include <casacore/casa/OS/File.h>
      34             : #include <casacore/lattices/LEL/LatticeExpr.h>
      35             : #include <casacore/lattices/LEL/LatticeExprNode.h>
      36             : #include <casacore/lattices/Lattices/LatticeStepper.h>
      37             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      38             : #include <synthesis/MeasurementEquations/SkyEquation.h>
      39             : #include <casacore/casa/Exceptions/Error.h>
      40             : #include <casacore/casa/BasicSL/String.h>
      41             : #include <casacore/casa/Utilities/Assert.h>
      42             : 
      43             : #include <sstream>
      44             : 
      45             : #include <casacore/casa/Logging/LogMessage.h>
      46             : #include <casacore/casa/Logging/LogSink.h>
      47             : #include <casacore/casa/Logging/LogIO.h>
      48             : 
      49             : #include <msvis/MSVis/StokesVector.h>
      50             : #include <synthesis/MeasurementEquations/LatConvEquation.h>
      51             : #include <synthesis/MeasurementEquations/ClarkCleanLatModel.h>
      52             : #include <casacore/lattices/Lattices/SubLattice.h>
      53             : #include <casacore/lattices/LRegions/LCBox.h>
      54             : 
      55             : using namespace casacore;
      56             : namespace casa {
      57             : 
      58           0 : Int CSCleanImageSkyModel::add(ImageInterface<Float>& image,
      59             :                               const Int maxNumXfr)
      60             : {
      61           0 :   return CleanImageSkyModel::add(image, maxNumXfr);
      62             : };
      63             : 
      64           0 : Bool CSCleanImageSkyModel::addMask(Int image,
      65             :                                    ImageInterface<Float>& mask)
      66             : {
      67           0 :   return CleanImageSkyModel::addMask(image, mask);
      68             : };
      69             : 
      70           0 : Bool CSCleanImageSkyModel::addResidual(Int image,
      71             :                                        ImageInterface<Float>& residual) 
      72             : {
      73           0 :   return ImageSkyModel::addResidual(image, residual);
      74             : };
      75             : 
      76             : // Clean solver
      77           0 : Bool CSCleanImageSkyModel::solve(SkyEquation& se) {
      78             : 
      79           0 :   LogIO os(LogOrigin("CSCleanImageSkyModel","solve"));
      80           0 :   Bool converged=true;
      81           0 :   if(modified_p) {
      82           0 :     makeNewtonRaphsonStep(se, false, (numberIterations()<1)?true:False);
      83             :   }
      84             : 
      85           0 :   if( numberIterations() < 1)
      86           0 :     return true;
      87             :   //Make the PSFs, one per field
      88             : 
      89             :   os << LogIO::NORMAL    // Loglevel PROGRESS
      90           0 :      << "Making approximate Point Spread Functions" << LogIO::POST;
      91           0 :   if(!donePSF_p)
      92           0 :     makeApproxPSFs(se);
      93             :   //
      94             :   // Quite a few lines of code required to pull out co-ordinate info.
      95             :   // from an image, one would think.
      96             :   //
      97           0 :   CoordinateSystem psfCoord=PSF(0).coordinates();
      98           0 :   Int dirIndex = psfCoord.findCoordinate(Coordinate::DIRECTION);
      99           0 :   DirectionCoordinate dc=psfCoord.directionCoordinate(dirIndex);
     100           0 :   Vector<Double> incr=dc.increment();
     101             :   //
     102             :   // The fitted beam params. are in arcsec.  Increments returned
     103             :   // by the coordinate system are in radians.
     104             :   //
     105           0 :   incr *= 3600.0*180.0/M_PI;
     106           0 :   incr = abs(incr);
     107             : 
     108             :   // Validate PSFs for each field
     109           0 :   Vector<Float> psfmax(numberOfModels()); psfmax=0.0;
     110           0 :   Vector<Float> psfmaxouter(numberOfModels()); psfmaxouter=0.0;
     111           0 :   Vector<Float> psfmin(numberOfModels()); psfmin=1.0;
     112           0 :   Block<Vector<Float> > resmax(numberOfModels());
     113           0 :   Block<Vector<Float> > resmin(numberOfModels());
     114             : 
     115           0 :   Float maxSidelobe=0.0;
     116             :   Int model;
     117           0 :   os << LogIO::NORMAL1;   // Loglevel INFO
     118           0 :   for (model=0;model<numberOfModels();model++) {
     119           0 :     if(isSolveable(model)) {
     120             : 
     121           0 :       IPosition blc(PSF(model).shape().nelements(), 0);
     122           0 :       IPosition trc(PSF(model).shape()-1);
     123           0 :       blc(2) = 0;  trc(2) = 0;
     124           0 :       blc(3) = 0;  trc(3) = 0;
     125             : 
     126           0 :       SubLattice<Float> subPSF;
     127           0 :       Int k =0;
     128           0 :       Int numchan= PSF(model).shape()(3);
     129             :       //PSF of first non zero plane
     130           0 :       while(psfmax(model) < 0.1 && k< numchan){
     131           0 :         blc(3)= k;
     132           0 :         trc(3)=k;
     133           0 :         LCBox onePlane(blc, trc, PSF(model).shape());
     134           0 :         subPSF=SubLattice<Float> ( PSF(model), onePlane, true);
     135             :         {
     136           0 :           LatticeExprNode node = max(subPSF);
     137           0 :           psfmax(model) = node.getFloat();
     138           0 :         }
     139           0 :         ++k;
     140           0 :       }
     141             :       // {
     142             :       //   LatticeExprNode node = min(subPSF);
     143             :       //   psfmin(model) = node.getFloat();
     144             :       // }
     145             :       // // 4 pixels:  pretty arbitrary, but only look for sidelobes
     146             :       // // outside the inner (2n+1) * (2n+1) square
     147             :       // // Changed the algorithm now..so that 4 is not used
     148             :       // Int mainLobeSizeInPixels = (Int)(max(beam(0)[0]/incr[0],beam(0)[1]/incr[1]));
     149             :       // //psfmaxouter(model) = maxOuter(subPSF, 4);  
     150             :       // psfmaxouter(model) = maxOuter(subPSF, mainLobeSizeInPixels);  
     151             : 
     152             :       //
     153             :       // Since for CS-Clean anyway uses only a small fraction of the
     154             :       // inner part of the PSF matter, find the PSF outer
     155             :       // min/max. using only the inner quater of the PSF.
     156             :       //
     157           0 :       GaussianBeam elbeam0=beam(0)(0,0);
     158           0 :       Int mainLobeSizeInPixels = (Int)(max(elbeam0.getMajor("arcsec")/incr[0],elbeam0.getMinor("arcsec")/incr[1]));
     159           0 :       Vector<Float> psfOuterMinMax(2);
     160           0 :       psfOuterMinMax = outerMinMax(subPSF, mainLobeSizeInPixels);
     161           0 :       psfmaxouter(model)=psfOuterMinMax(1);
     162           0 :       psfmin(model) = psfOuterMinMax(0);
     163             : 
     164             :       
     165             :       os << "Model " << model+1 << ": Estimated size of the PSF mainlobe = " 
     166           0 :          << (Int)(elbeam0.getMajor("arcsec")/incr[0]+0.5) << " X " << (Int)(elbeam0.getMinor("arcsec")/incr[1] + 0.5) << " pixels" 
     167           0 :          << endl;
     168             :       os << "Model " << model+1 << ": PSF Peak, min, max sidelobe = "
     169           0 :          << psfmax(model) << ", " << psfmin(model) << ", " <<
     170           0 :         psfmaxouter(model) << endl;
     171           0 :       if(abs(psfmin(model))>maxSidelobe) maxSidelobe=abs(psfmin(model));
     172           0 :       if(psfmaxouter(model) > maxSidelobe) maxSidelobe= psfmaxouter(model );
     173           0 :     }
     174             :   }
     175           0 :   os << LogIO::POST;
     176             :         
     177           0 :   Float absmax=threshold();
     178           0 :   Float oldmax=absmax;
     179           0 :   Float cycleThreshold=0.0;
     180           0 :   Block< Vector<Int> > iterations(numberOfModels());
     181           0 :   Int maxIterations=0;
     182           0 :   Int oldMaxIterations=0;
     183             :     
     184             :   // Loop over major cycles
     185           0 :   Int cycle=0;
     186           0 :   Bool stop=false;
     187             : 
     188           0 :   if (displayProgress_p) {
     189           0 :     progress_p = new ClarkCleanProgress( pgplotter_p );
     190             :   } else {
     191           0 :     progress_p = 0;
     192             :   }
     193           0 :   Bool lastCycleWriteModel=false;
     194           0 :   while((absmax>=threshold())&& (maxIterations<numberIterations()) &&!stop) {
     195             : 
     196             :     os << LogIO::NORMAL << "*** Starting major cycle " << cycle + 1 
     197           0 :        << LogIO::POST;  // Loglevel PROGRESS
     198           0 :     cycle++;
     199             : 
     200             :     // Make the residual images. We do an incremental update
     201             :     // for cycles after the first one. If we have only one
     202             :     // model then we use convolutions to speed the processing
     203             :     //os << LogIO::NORMAL2         // Loglevel PROGRESS
     204             :     //   << "Starting major cycle : making residual images for all fields"
     205             :     //   << LogIO::POST;
     206           0 :     if(modified_p) {
     207           0 :       Bool incremental(cycle>1);
     208           0 :       if (incremental&&(itsSubAlgorithm == "fast")) {
     209             :         os << LogIO::NORMAL1         // Loglevel INFO
     210             :            << "Using XFR-based shortcut for residual calculation"
     211           0 :            << LogIO::POST;
     212           0 :         makeNewtonRaphsonStep(se, false);
     213             :       }
     214             :       else {
     215             :         os << LogIO::NORMAL1         // Loglevel INFO
     216             :            << "Using visibility-subtraction for residual calculation"
     217           0 :            << LogIO::POST;
     218           0 :         makeNewtonRaphsonStep(se, false);
     219             :       }
     220             :       os << LogIO::NORMAL2         // Loglevel PROGRESS
     221             :          << "Finished update of residuals"
     222           0 :          << LogIO::POST;
     223             :     }
     224             : 
     225           0 :     oldmax=absmax;
     226           0 :     absmax=maxField(resmax, resmin);
     227           0 :     if(cycle==1) oldmax=absmax;
     228             : 
     229           0 :     for (model=0;model<numberOfModels();model++) {
     230             :       os << LogIO::NORMAL         // Loglevel INFO
     231             :          << "Model " << model+1 << ": max, min residuals = "
     232           0 :          << max(resmax[model]) << ", " << min(resmin[model]) << endl;
     233             :     }
     234           0 :     os << LogIO::POST;
     235             : 
     236             :     // Can we stop?
     237           0 :     if(absmax<threshold()) {
     238             :       os << LogIO::NORMAL         // Loglevel INFO
     239           0 :          << "Reached stopping peak residual = " << absmax << LogIO::POST;
     240           0 :       stop=true;
     241           0 :       if(cycle >1)
     242           0 :         lastCycleWriteModel=true;
     243             :     }
     244             :     else {
     245           0 :       if(oldmax < absmax){
     246             :         //Diverging?  Let's increase the cyclefactor 
     247           0 :         cycleFactor_p=1.5*cycleFactor_p;
     248           0 :         oldmax=absmax;
     249             :       }
     250             :       // Calculate the threshold for this cycle. Add a safety factor
     251             :       // This will be fixed someday by an option for an increasing threshold
     252           0 :       Float fudge = cycleFactor_p * maxSidelobe;
     253           0 :       if (fudge > 0.8) fudge = 0.8;   // painfully slow!
     254             : 
     255           0 :       cycleThreshold=max(threshold(), fudge * absmax);
     256             :       os << LogIO::NORMAL         // Loglevel INFO
     257             :          << "Maximum residual = " << absmax << ", cleaning down to "
     258           0 :          << cycleThreshold << LogIO::POST;
     259             :       
     260           0 :       for (model=0;model<numberOfModels();model++) {
     261             :         
     262           0 :         Int nx=image(model).shape()(0);
     263           0 :         Int ny=image(model).shape()(1);
     264           0 :         Int npol=image(model).shape()(2);
     265           0 :         Int nchan=image(model).shape()(3);
     266             :         
     267           0 :         AlwaysAssert((npol==1)||(npol==2)||(npol==4), AipsError);
     268             :             
     269           0 :         if(cycle==1) {
     270           0 :           iterations[model].resize(nchan);
     271           0 :           iterations[model]=0;
     272             :         }
     273             :           
     274             :         // Initialize delta image
     275           0 :         deltaImage(model).set(0.0);
     276             : 
     277             :         // Only process solveable models
     278           0 :         if(isSolveable(model)&&psfmax(model)>0.0) {
     279             :           
     280           0 :           if((max(abs(resmax[model]))>cycleThreshold)||
     281           0 :              (max(abs(resmin[model]))>cycleThreshold)) {
     282             :             
     283             :             os << LogIO::NORMAL         // Loglevel PROGRESS
     284           0 :                << "Processing model " << model+1 << LogIO::POST;
     285             :             
     286           0 :             IPosition onePlane(4, nx, ny, 1, 1);
     287             :             
     288           0 :             IPosition oneCube(4, nx, ny, npol, 1);
     289             :             
     290             :             // Loop over all channels. We only want the PSF for the first
     291             :             // polarization so we iterate over polarization LAST
     292             :             
     293             :             // Now clean each channel
     294           0 :             for (Int chan=0;chan<nchan;++chan) {
     295           0 :               if(nchan>1) {
     296             :                 os << LogIO::NORMAL         // Loglevel PROGRESS
     297             :                    <<"Processing channel number "<<chan<<" of "<<nchan 
     298           0 :                    << " channels" <<LogIO::POST;
     299             :               }
     300           0 :               if((abs(resmax[model][chan])>cycleThreshold) ||
     301           0 :                  (abs(resmin[model][chan])>cycleThreshold)) {
     302           0 :                 LCBox psfbox(IPosition(4, 0, 0, 0, chan), 
     303           0 :                              IPosition(4, nx-1, ny-1, 0, chan),
     304           0 :                              PSF(model).shape());
     305           0 :                 SubLattice<Float>  psf_sl (PSF(model), psfbox, false);
     306             :                 
     307           0 :                 LCBox imagebox(IPosition(4, 0, 0, 0, chan), 
     308           0 :                                IPosition(4, nx-1, ny-1, npol-1, chan), 
     309           0 :                                residual(model).shape());
     310             :                 
     311             :                 
     312           0 :                 SubLattice<Float>  residual_sl (residual(model), imagebox, true);
     313           0 :                 SubLattice<Float>  image_sl (image(model), imagebox, true);
     314           0 :                 SubLattice<Float>  deltaimage_sl (deltaImage(model), imagebox, true);
     315             :                 // Now make a convolution equation for this
     316             :                 // residual image and psf and then clean it
     317             :                 {
     318           0 :                   LatConvEquation eqn(psf_sl, residual_sl);
     319           0 :                   ClarkCleanLatModel cleaner(deltaimage_sl);
     320           0 :                   cleaner.setResidual(residual_sl);
     321           0 :                   cleaner.setGain(gain());
     322           0 :                   cleaner.setNumberIterations(numberIterations());
     323           0 :                   cleaner.setInitialNumberIterations(iterations[model](chan));
     324           0 :                   cleaner.setThreshold(cycleThreshold);
     325           0 :                   cleaner.setPsfPatchSize(IPosition(2,51)); 
     326           0 :                   cleaner.setMaxNumberMajorCycles(1);
     327           0 :                   cleaner.setMaxNumberMinorIterations(100000);
     328           0 :                   cleaner.setHistLength(1024);
     329           0 :                   cleaner.setCycleFactor(cycleFactor_p);
     330           0 :                   cleaner.setMaxNumPix(32*1024);
     331           0 :                   cleaner.setChoose(false);
     332           0 :                   if(cycleSpeedup_p >1)
     333           0 :                     cleaner.setSpeedup(cycleSpeedup_p);
     334             :                   else
     335           0 :                     cleaner.setSpeedup(0.0);
     336             :                   //Be a bit more conservative with pathologically bad PSFs
     337           0 :                   if(maxSidelobe > 0.5)
     338           0 :                     cleaner.setMaxNumberMinorIterations(5);
     339           0 :                   else if(maxSidelobe > 0.35)
     340           0 :                     cleaner.setMaxNumberMinorIterations(50);
     341             :                   
     342             :                   //cleaner.setSpeedup(0.0);
     343           0 :                   if ( displayProgress_p ) {
     344           0 :                     cleaner.setProgress( *progress_p );
     345             :                   }
     346             :                   os << LogIO::NORMAL         // Loglevel PROGRESS
     347           0 :                      << "Starting minor cycle of Clean" << LogIO::POST;
     348           0 :                   SubLattice<Float> mask_sl;
     349           0 :                   if(hasMask(model)) {
     350           0 :                     mask_sl=SubLattice<Float>  (mask(model), psfbox, true);
     351           0 :                     cleaner.setMask(mask_sl);
     352             :                   }
     353             :                 
     354           0 :                   modified_p= cleaner.singleSolve(eqn, residual_sl) || modified_p;
     355             :                   
     356             : 
     357           0 :                   if(modified_p){
     358             :                     os << LogIO::NORMAL    // Loglevel PROGRESS (See CAS-2017)
     359             :                        << "Finished minor cycle of Clean"
     360           0 :                        << LogIO::POST;
     361             :                     
     362           0 :                     if (cleaner.numberIterations()>0) {
     363             :                       os << LogIO::NORMAL    // Loglevel INFO
     364             :                          << "Clean used " << cleaner.numberIterations()
     365             :                          << " iterations to approach a threshold of "
     366           0 :                          << cycleThreshold << LogIO::POST;
     367             :                     }
     368             :                   }
     369             :                   
     370           0 :                   iterations[model](chan)=cleaner.numberIterations();
     371           0 :                   maxIterations=(iterations[model](chan)>maxIterations) ?
     372           0 :                     iterations[model](chan) : maxIterations;
     373             :                   
     374             :                   os << LogIO::NORMAL2    // Loglevel PROGRESS
     375           0 :                      << "Adding increment to existing model" << LogIO::POST;
     376           0 :                   LatticeExpr<Float> expr=image_sl+deltaimage_sl;
     377           0 :                   image_sl.copyData(expr);
     378           0 :                 }
     379           0 :               }
     380             :             }// channel loop
     381           0 :             if(!modified_p){
     382             :               os << LogIO::WARN 
     383             :                  << "No clean component found below threshold of "
     384             :                  << cycleThreshold 
     385           0 :                  << "\n in region selected to clean in model " << model << LogIO::POST;
     386             :               
     387             :             }
     388             : 
     389           0 :             if(maxIterations==0) {
     390           0 :               stop=true;
     391             :             }
     392             :             else{
     393           0 :               stop=false;
     394             :             }
     395             :             os << LogIO::NORMAL    // Loglevel INFO
     396             :                << "Model " << model << " has "
     397           0 :                << LatticeExprNode(sum(image(model))).getFloat() 
     398             :                << " Jy in clean components." 
     399           0 :                << LogIO::POST; 
     400           0 :           }
     401             :           else {
     402             :             os << LogIO::NORMAL    // Loglevel INFO
     403             :                <<"Skipping model "<<model<<" :peak residual below threshold"
     404           0 :                <<LogIO::POST;
     405             :           }
     406             :         }
     407             :       }
     408           0 :       if(maxIterations != oldMaxIterations)
     409           0 :         oldMaxIterations=maxIterations;
     410             :       else {
     411             :         os << LogIO::NORMAL    // Loglevel INFO
     412           0 :            << "No more cleaning occured in this major cycle - stopping now" << LogIO::POST;
     413           0 :         stop=true;
     414           0 :         converged=true;
     415             :       }
     416             :     }
     417             :   }
     418           0 :   if (progress_p) delete progress_p;
     419             :   
     420             :   
     421           0 :   if(modified_p || lastCycleWriteModel) {
     422             :     os << LogIO::NORMAL    // Loglevel INFO
     423           0 :        << LatticeExprNode(sum(image(0))).getFloat() 
     424           0 :        << " Jy is the sum of the clean components " << LogIO::POST;
     425             :     os << LogIO::NORMAL    // Loglevel PROGRESS
     426           0 :        << "Finalizing residual images for all fields" << LogIO::POST;
     427           0 :     makeNewtonRaphsonStep(se, false, true);
     428           0 :     Float finalabsmax=maxField(resmax, resmin);
     429             : 
     430             :     os << LogIO::NORMAL    // Loglevel INFO
     431           0 :        << "Final maximum residual = " << finalabsmax << LogIO::POST;
     432           0 :     converged=(finalabsmax < threshold());
     433           0 :     for (model=0;model<numberOfModels();model++) {
     434             :       os << LogIO::NORMAL    // Loglevel INFO
     435             :          << "Model " << model+1 << ": max, min residuals = "
     436           0 :          << max(resmax[model]) << ", " << min(resmin[model]) << endl;
     437             :     }
     438           0 :   }
     439             :   else {
     440             :     os << LogIO::NORMAL    // Loglevel INFO
     441           0 :        << "Residual images for all fields are up-to-date" << LogIO::POST;
     442             :   }
     443             : 
     444           0 :   os << LogIO::POST;
     445             : 
     446           0 :   return(converged);
     447           0 : };
     448             :   
     449             :   
     450             : // Find maximum residual
     451           0 : Float CSCleanImageSkyModel::maxField(Block<Vector<Float> >& imagemax,
     452             :                                      Block<Vector<Float> >& imagemin) {
     453             : 
     454           0 :   LogIO os(LogOrigin("ImageSkyModel","maxField"));
     455             :   
     456           0 :   Float absmax=0.0;
     457             : 
     458             :   // Loop over all models
     459           0 :   for (Int model=0;model<numberOfModels();model++) {
     460             : 
     461           0 :     imagemax[model].resize(image(model).shape()(3));
     462           0 :     imagemin[model].resize(image(model).shape()(3));
     463             :     // Remember that the residual image can be either as specified
     464             :     // or created specially.
     465           0 :     ImageInterface<Float>* imagePtr=0;
     466           0 :     if(residual_p[model]) {
     467           0 :       imagePtr=residual_p[model];
     468             :     }
     469             :     else {
     470           0 :       imagePtr=(ImageInterface<Float> *)residualImage_p[model];
     471             :     }
     472           0 :     AlwaysAssert(imagePtr, AipsError);
     473           0 :     AlwaysAssert(imagePtr->shape().nelements()==4, AipsError);
     474           0 :     Int nx=imagePtr->shape()(0);
     475           0 :     Int ny=imagePtr->shape()(1);
     476           0 :     Int npol=imagePtr->shape()(2);
     477             :     
     478           0 :     AlwaysAssert((npol==1)||(npol==2)||(npol==4), AipsError);
     479             :     
     480             :     // Loop over all channels
     481           0 :     IPosition onePlane(4, nx, ny, 1, 1);
     482           0 :     LatticeStepper ls(imagePtr->shape(), onePlane, IPosition(4, 0, 1, 2, 3));
     483           0 :     RO_LatticeIterator<Float> imageli(*imagePtr, ls);
     484             :     
     485             :     // If we are using a mask then reset the region to be
     486             :     // cleaned
     487           0 :     Array<Float> maskArray;
     488           0 :     RO_LatticeIterator<Float> maskli;
     489           0 :     if(hasMask(model)) {
     490           0 :       Int mx=mask(model).shape()(0);
     491           0 :       Int my=mask(model).shape()(1);
     492           0 :       Int mpol=mask(model).shape()(2);
     493             :       //AlwaysAssert(mx==nx, AipsError);
     494             :       //AlwaysAssert(my==ny, AipsError);
     495             :       //AlwaysAssert(mpol==npol, AipsError);
     496           0 :       if((mx != nx) || (my != ny) || (mpol != npol)){
     497           0 :         throw(AipsError("Mask image shape is not the same as dirty image"));
     498             :       }
     499           0 :       LatticeStepper mls(mask(model).shape(), onePlane,
     500           0 :                          IPosition(4, 0, 1, 2, 3));
     501             :       
     502           0 :       maskli=RO_LatticeIterator<Float> (mask(model), mls);
     503           0 :       maskli.reset();
     504           0 :       if (maskli.cursor().shape().nelements() > 1) maskArray=maskli.cursor();
     505           0 :     }
     506             :     
     507           0 :     Int chan=0;
     508           0 :     Int polpl=0;
     509             :     Float imax, imin;
     510           0 :     imax=-1E20; imagemax[model]=imax;
     511           0 :     imin=+1E20; imagemin[model]=imin;
     512           0 :     imageli.reset();
     513             : 
     514           0 :     for (imageli.reset();!imageli.atEnd();imageli++) {
     515           0 :       imax=-1E20;
     516           0 :       imin=+1E20;
     517           0 :       IPosition imageposmax(imageli.cursor().ndim());
     518           0 :       IPosition imageposmin(imageli.cursor().ndim());
     519             :       
     520             :       // If we are using a mask then multiply by it
     521           0 :       if (hasMask(model)) {
     522           0 :         Array<Float> limage=imageli.cursor();
     523             :         //limage*=maskArray;
     524           0 :         minMaxMasked(imin, imax, imageposmin, imageposmax, limage, maskArray);
     525           0 :         maskli++;
     526           0 :         if (maskli.cursor().shape().nelements() > 1) maskArray=maskli.cursor();
     527             :       
     528           0 :       }
     529             :       
     530             :       else {
     531           0 :         minMax(imin, imax, imageposmin, imageposmax, imageli.cursor());
     532             :       }
     533           0 :       if(abs(imax)>absmax) absmax=abs(imax);
     534           0 :       if(abs(imin)>absmax) absmax=abs(imin);
     535           0 :       if(imin<imagemin[model][chan]) imagemin[model][chan]=imin;
     536           0 :       if(imax>imagemax[model][chan]) imagemax[model][chan]=imax;
     537           0 :       ++polpl;
     538           0 :       if(polpl==npol){
     539           0 :         ++chan;
     540           0 :         polpl=0;          
     541             :       }
     542           0 :     }
     543           0 :   }
     544           0 :   return absmax;
     545           0 : };
     546             :     
     547             : 
     548           0 : Vector<Float> CSCleanImageSkyModel::outerMinMax(Lattice<Float> & lat, const uInt nCenter ) 
     549             : {
     550           0 :   Array<Float> arr = lat.get();
     551           0 :   IPosition pos( arr.shape() );
     552           0 :   uInt nx = lat.shape()(0);
     553           0 :   uInt ny = lat.shape()(1);
     554           0 :   uInt innerx = lat.shape()(0)/4;
     555           0 :   uInt innery = lat.shape()(1)/4;
     556           0 :   uInt nxc = 0;
     557           0 :   uInt nyc = 0;
     558           0 :   Float amax = 0.0;
     559           0 :   Vector<Float> amax2,minMax(2);
     560             :   //
     561             :   // First locate the location of the peak
     562             :   //
     563           0 :   for (uInt ix = 0; ix < nx; ix++) 
     564           0 :     for (uInt iy = 0; iy < ny; iy++) 
     565           0 :       if (arr(IPosition(4, ix, iy, 0, 0)) > amax) 
     566             :         {
     567           0 :           nxc = ix;
     568           0 :           nyc = iy;
     569           0 :           amax = arr(IPosition(4, ix, iy, 0, 0));
     570             :         }
     571             :   //
     572             :   // Now exclude the mainlobe center on the location of the peak to
     573             :   // get the max. outer sidelobe.
     574             :   //
     575           0 :   Float myMax=0.0;
     576           0 :   Float myMin=0.0;
     577             : 
     578           0 :   uInt nxL = nxc - nCenter;
     579           0 :   uInt nxH = nxc + nCenter;
     580           0 :   uInt nyL = nyc - nCenter;
     581           0 :   uInt nyH = nyc + nCenter;
     582           0 :   uInt nx0 = nxc - innerx/2, nx1 = nxc + innerx/2;
     583           0 :   uInt ny0 = nyc - innery/2, ny1 = nyc + innery/2;
     584             :   
     585             :   //
     586             :   // Search only in the square with innerx and innery pixels on each side.
     587             :   //
     588           0 :   for (uInt ix = nx0; ix < nx1; ix++) {
     589           0 :     for (uInt iy = ny0; iy < ny1; iy++) {
     590           0 :       if ( !(ix >= nxL && ix <= nxH &&  iy >= nyL && iy <= nyH) ) {
     591           0 :         if (arr(IPosition(4, ix, iy, 0, 0)) > myMax) 
     592           0 :           myMax = arr(IPosition(4, ix, iy, 0, 0));
     593           0 :         if (arr(IPosition(4, ix, iy, 0, 0)) < myMin)
     594           0 :           myMin = arr(IPosition(4, ix, iy, 0, 0));
     595             :       }
     596             :     }
     597             :   }
     598             : 
     599             :   // Float absMax = max( abs(myMin), myMax );
     600             :   // return absMax;
     601           0 :   minMax(0) = myMin;
     602           0 :   minMax(1) = max( abs(myMin), myMax );
     603           0 :   return minMax;
     604           0 : };
     605             : 
     606             : } //#End casa namespace

Generated by: LCOV version 1.16