LCOV - code coverage report
Current view: top level - synthesis/MeasurementEquations - CEMemModel.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 229 337 68.0 %
Date: 2024-12-11 20:54:31 Functions: 18 23 78.3 %

          Line data    Source code
       1             : //# CEMemModel.cc:  this implements CEMemModel
       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/CEMemModel.h>
      29             : #include <synthesis/MeasurementEquations/CEMemProgress.h>
      30             : #include <synthesis/MeasurementEquations/LatConvEquation.h>
      31             : #include <casacore/casa/Arrays/IPosition.h>
      32             : #include <casacore/lattices/LEL/LatticeExpr.h>
      33             : #include <casacore/lattices/LEL/LatticeExprNode.h>
      34             : #include <casacore/lattices/Lattices/TiledLineStepper.h>
      35             : #include <casacore/lattices/Lattices/TempLattice.h>
      36             : #include <casacore/lattices/Lattices/LatticeIterator.h>
      37             : #include <casacore/casa/Arrays/Slice.h>
      38             : #include <casacore/casa/Arrays/Matrix.h>
      39             : #include <casacore/casa/Arrays/Vector.h>
      40             : #include <casacore/casa/Arrays/Array.h>
      41             : #include <casacore/casa/Arrays/ArrayError.h>
      42             : #include <casacore/casa/Arrays/ArrayMath.h>
      43             : #include <casacore/casa/Arrays/VectorIter.h>
      44             : #include <casacore/casa/Logging/LogOrigin.h>
      45             : #include <casacore/casa/BasicMath/Math.h>
      46             : #include <casacore/casa/Exceptions/Error.h>
      47             : #include <casacore/casa/Utilities/Assert.h>
      48             : #include <casacore/casa/System/PGPlotter.h>
      49             : #include <iostream> 
      50             : #include <sstream>
      51             : 
      52             : 
      53             : using namespace casacore;
      54             : namespace casa { //# NAMESPACE CASA - BEGIN
      55             : 
      56             : //----------------------------------------------------------------------
      57           2 : CEMemModel::CEMemModel(Entropy &ent, 
      58             :                        Lattice<Float> & model,
      59             :                        uInt nIntegrations,
      60             :                        Float sigma,
      61             :                        Float targetFlux,
      62             :                        Bool useFluxConstraint,
      63             :                        Bool initializeModel,
      64           2 :                        Bool doImageplane) :
      65           2 :   itsEntropy_ptr(&ent),
      66           2 :   itsResidualEquation_ptr(0),
      67           2 :   itsModel_ptr(&model),
      68           2 :   itsPrior_ptr(0),
      69           2 :   itsMask_ptr(0),
      70           2 :   itsInitializeModel(initializeModel),
      71           2 :   itsNumberIterations(nIntegrations),
      72           2 :   itsSigma(sigma),
      73           2 :   itsTargetFlux(targetFlux),
      74           2 :   itsUseFluxConstraint(useFluxConstraint),
      75           2 :   itsDoImagePlane(doImageplane),
      76           2 :   itsThreshold0(0.0),
      77           2 :   itsThresholdSpeedup(0.0),
      78           2 :   itsCycleFlux(0.0),
      79           2 :   itsFirstIteration(0),
      80           2 :   itsChoose(false),
      81           2 :   itsLog(LogOrigin("CEMemModel", 
      82             :                    "CEMemModel(const Lattice<Float> & model)")),
      83           2 :   itsProgressPtr(0)
      84             : {
      85           2 :   initStuff();
      86           2 : };
      87             : 
      88             : //----------------------------------------------------------------------
      89           0 : CEMemModel::CEMemModel(Entropy &ent, 
      90             :                        Lattice<Float> & model,
      91             :                        Lattice<Float> & prior,
      92             :                        uInt nIntegrations,
      93             :                        Float sigma,
      94             :                        Float targetFlux,
      95             :                        Bool useFluxConstraint,
      96             :                        Bool initializeModel,
      97           0 :                        Bool doImageplane) :
      98           0 :   itsEntropy_ptr(&ent),
      99           0 :   itsResidualEquation_ptr(0),
     100           0 :   itsModel_ptr(&model),
     101           0 :   itsPrior_ptr(&prior),
     102           0 :   itsMask_ptr(0),
     103           0 :   itsInitializeModel(initializeModel),
     104           0 :   itsNumberIterations(nIntegrations),
     105           0 :   itsSigma(sigma),
     106           0 :   itsTargetFlux(targetFlux),
     107           0 :   itsUseFluxConstraint(useFluxConstraint),
     108           0 :   itsDoImagePlane(doImageplane),
     109           0 :   itsThreshold0(0.0),
     110           0 :   itsThresholdSpeedup(0.0),
     111           0 :   itsCycleFlux(0.0),
     112           0 :   itsFirstIteration(0),
     113           0 :   itsChoose(false),
     114           0 :   itsLog(LogOrigin("CEMemModel", 
     115             :                    "CEMemModel(const Lattice<Float> & model)")),
     116           0 :    itsProgressPtr(0)
     117             : {
     118           0 :   initStuff();
     119           0 : };
     120             : 
     121             : //----------------------------------------------------------------------
     122           0 : CEMemModel::CEMemModel(Entropy &ent, 
     123             :                        Lattice<Float> & model,
     124             :                        Lattice<Float> & prior,
     125             :                        Lattice<Float> & mask,
     126             :                        uInt nIntegrations,
     127             :                        Float sigma,
     128             :                        Float targetFlux,
     129             :                        Bool useFluxConstraint,
     130             :                        Bool initializeModel,
     131           0 :                        Bool doImageplane)
     132             :   :
     133           0 :   itsEntropy_ptr(&ent),
     134           0 :   itsResidualEquation_ptr(0),
     135           0 :   itsModel_ptr(&model),
     136           0 :   itsPrior_ptr(&prior),
     137           0 :   itsMask_ptr(&mask),
     138           0 :   itsInitializeModel(initializeModel),
     139           0 :   itsNumberIterations(nIntegrations),
     140           0 :   itsSigma(sigma),
     141           0 :   itsTargetFlux(targetFlux),
     142           0 :   itsUseFluxConstraint(useFluxConstraint),
     143           0 :   itsDoImagePlane(doImageplane),
     144           0 :   itsThreshold0(0.0),
     145           0 :   itsThresholdSpeedup(0.0),
     146           0 :   itsCycleFlux(0.0),
     147           0 :   itsFirstIteration(0),
     148           0 :   itsChoose(false), 
     149           0 :   itsLog(LogOrigin("CEMemModel", 
     150             :                    "CEMemModel(const Lattice<Float> & model)")),
     151           0 :   itsProgressPtr(0)
     152             : 
     153             : {
     154           0 :   initStuff();
     155           0 : };
     156             : 
     157             : 
     158             : //----------------------------------------------------------------------
     159           2 : CEMemModel::~CEMemModel()
     160             : {
     161           2 :   delete itsStep_ptr;
     162           2 :   delete itsResidual_ptr;
     163           2 : };
     164             : 
     165             : 
     166             : 
     167             : //----------------------------------------------------------------------
     168           0 : void CEMemModel::setPrior(Lattice<Float> & prior)
     169             : {
     170           0 :   checkImages(itsModel_ptr, &prior); 
     171           0 :   itsPrior_ptr = &prior; 
     172           0 :   initStuff();
     173           0 : }
     174             : 
     175             : //----------------------------------------------------------------------
     176           9 : Float CEMemModel::getThreshold()
     177             : {
     178           9 :   if (itsThresholdSpeedup<= 0.0) {
     179           9 :     return itsThreshold0;
     180             :   } else {
     181           0 :     Float factor = (1 + (Float)(itsIteration - itsFirstIteration)/((Float)(itsThresholdSpeedup)) );
     182           0 :     return (itsThreshold0 * factor);
     183             :   }
     184             : };
     185             : 
     186             : 
     187             : //----------------------------------------------------------------------
     188           4 : Bool CEMemModel::initStuff()
     189             : {
     190           4 :   checkImage(itsModel_ptr);
     191             : 
     192             :   // initialize various parameters
     193             : 
     194           4 :   if (itsMask_ptr) {
     195           2 :     LatticeExprNode LEN = sum(*itsMask_ptr);
     196           2 :     itsNumberPixels = LEN.getFloat();
     197           2 :   } else {
     198           2 :     itsNumberPixels = itsModel_ptr->nelements();
     199             :   }
     200             : 
     201           4 :   formFlux();
     202           4 :   itsDefaultLevel = abs(itsTargetFlux) / itsNumberPixels;
     203             : 
     204           4 :   Float clipVal = 1.0e-7;
     205           4 :   if (itsPrior_ptr != 0) {
     206           0 :     itsDefaultLevel = 0.0;
     207           0 :     Lattice<Float> &prior = *itsPrior_ptr;
     208           0 :     prior.copyData(  (LatticeExpr<Float>) (iif(prior < clipVal, clipVal, prior)) );     
     209             :   }
     210             : 
     211           4 :   Lattice<Float> &model = *itsModel_ptr;
     212           4 :   if (itsInitializeModel) {
     213           4 :     if (itsDefaultLevel > 0.0) {
     214           4 :       model.set(itsDefaultLevel);
     215             :     } else {
     216           0 :       model.set(itsSigma/10.0);
     217             :     }
     218             :   } else {
     219             :     // use the model passed in, but clip it to avoid negativity
     220           0 :      model.copyData( (LatticeExpr<Float>) (iif(model<clipVal, clipVal, model)) );     
     221             :   }
     222             : 
     223           4 :   applyMask( model );  // zero out masked pixels in model
     224             :    
     225           4 :   itsTolerance = 0.05;
     226           4 :   itsQ = 10;
     227           4 :   itsGain = 0.3;
     228           4 :   itsMaxNormGrad = 100.0;
     229             : 
     230           4 :   itsDoInit = true;
     231           4 :   itsAlpha = 0;
     232           4 :   itsBeta = 0;
     233           4 :   Bool isOK = true;
     234             : 
     235             :   //Create temporary images
     236             : 
     237           4 :   itsStep_ptr = new TempLattice<Float> (itsModel_ptr->shape(), 2);
     238           4 :   itsResidual_ptr = new TempLattice<Float> (itsModel_ptr->shape(), 2);
     239           4 :   if (itsStep_ptr &&  itsResidual_ptr) {
     240           4 :     itsStep_ptr->set(0.0);
     241           4 :     itsResidual_ptr->set(0.0);
     242             :   } else {
     243           0 :     isOK = false;
     244             :   }
     245             : 
     246             :   // We have been given an Entropy object, now we have to
     247             :   // tell it about US
     248           4 :   itsEntropy_ptr->setMemModel( *this );
     249             : 
     250           4 :   return isOK;
     251             : };
     252             : 
     253             : 
     254             : //----------------------------------------------------------------------
     255           2 : void CEMemModel::initializeAlphaBeta()
     256             : {
     257             :   // Note: in practice, this routine seems to never get called;
     258             :   // included for consistency with SDE MEM routine
     259           2 :   if (! itsUseFluxConstraint) {
     260           2 :     itsAlpha = max(0.0,  itsGDG(H,C)/ itsGDG(C,C) );
     261           2 :     itsBeta = 0.0;
     262             :   } else {
     263           0 :     Double det = itsGDG(C,C)*itsGDG(F,F) - itsGDG(C,F)*itsGDG(C,F);
     264           0 :     itsAlpha = (itsGDG(F,F)*itsGDG(H,C) - itsGDG(C,F)*itsGDG(H,F) )/det;
     265           0 :     itsBeta =  (itsGDG(C,C)*itsGDG(H,F) - itsGDG(C,F)*itsGDG(H,C) )/det;
     266             :   }
     267           2 : };
     268             : 
     269             : 
     270             : 
     271             : //----------------------------------------------------------------------
     272          10 : void CEMemModel::updateAlphaBeta()
     273             : {
     274             : 
     275             :   // code stolen from SDE's mem.f
     276          10 :   Double a = itsGDG(C,J)/itsGDG(C,C);
     277          10 :   Double b = square(a) - (itsGDG(J, J) - itsGain*itsLength)/ itsGDG(C, C);
     278             : 
     279             :   Double dAMax;
     280             :   Double dAMin;
     281             :   Double dBMax;
     282             :   Double dBMin;
     283             : 
     284          10 :   if (b > 0.0) {
     285          10 :     b = sqrt(b);
     286          10 :     dAMax = a + b;
     287          10 :     dAMin = a - b;
     288             :   } else {
     289           0 :     dAMax = 0.0;
     290           0 :     dAMin = 0.0;
     291             :   }
     292             : 
     293             :   Double dChisq;
     294             :   Double dAlpha;
     295             :   Double dBeta;
     296             :   Double dFlux;
     297             : 
     298          10 :   if ( ! itsUseFluxConstraint ) {
     299          10 :     dChisq =  itsChisq -  itsTargetChisq + itsGDG (C, J);
     300          10 :     dAlpha = dChisq/itsGDG(C, C);
     301             : 
     302          10 :     dAlpha = max(dAMin, min(dAMax, dAlpha));
     303          10 :     itsAlpha = max(0.0, itsAlpha + dAlpha);
     304             :   } else {
     305           0 :     a = itsGDG(F,J)/itsGDG(F,F);
     306           0 :     b = square(a) - (itsGDG(J, J) - itsGain*itsLength)/itsGDG(F,F);
     307           0 :     if ( b > 0.0) {
     308           0 :       b = sqrt((double)b);
     309           0 :       dBMax = a + b;
     310           0 :       dBMin = a - b;
     311             :     } else {
     312           0 :       dBMax = 0.0;
     313           0 :       dBMin = 0.0;
     314             :     }
     315             :     
     316           0 :     dChisq = itsChisq - itsTargetChisq + itsGDG(C, J);
     317           0 :     dFlux = itsFlux - itsTargetFlux +  itsGDG(F, J);
     318           0 :     Double det = itsGDG(C, C)*itsGDG(F, F) - square(itsGDG(F, C));
     319           0 :     dAlpha = (itsGDG(F, F)*dChisq - itsGDG(C, F)*dFlux)/det;
     320           0 :     dBeta =  (itsGDG(C, C)*dFlux  - itsGDG(C, F)*dChisq)/det;
     321             :     
     322           0 :     dAlpha = max(dAMin, min(dAMax, dAlpha));
     323           0 :     itsAlpha = max(0.0, itsAlpha + dAlpha);
     324           0 :     dBeta    = max(dBMin, min(dBMax, dBeta));
     325           0 :     itsBeta  = itsBeta + dBeta;
     326             :   }
     327             : 
     328          10 : };
     329             : 
     330             : 
     331             : 
     332             : //----------------------------------------------------------------------
     333          12 : void CEMemModel::changeAlphaBeta()
     334             : {
     335          12 :   formGDG();
     336          12 :   itsLength = itsGDG(H,H) + square(itsAlpha) * itsGDG(C,C) 
     337          12 :     + square(itsBeta) * itsGDG(F,F);
     338          12 :   if (itsAlpha == 0.0 && itsBeta == 0.0) {
     339           2 :     itsLength = itsGDG(F,F);
     340             :   }
     341          12 :   itsNormGrad = itsGDG(J,J) / itsLength;
     342          12 :   if (itsAlpha == 0.0) 
     343           2 :     itsNormGrad = 0.0;
     344          12 :   if (itsNormGrad < itsGain) {
     345          10 :     updateAlphaBeta();
     346             :   } else {
     347           2 :     initializeAlphaBeta();
     348             :   }
     349          12 : };
     350             : 
     351             : 
     352             : 
     353             : //----------------------------------------------------------------------
     354          14 : Bool CEMemModel::checkImage(const Lattice<Float>* /*im*/)
     355             : {
     356             :   // I guess we don't have anything to do
     357          14 :   return true;
     358             : };
     359             : 
     360             : 
     361             : 
     362             : //----------------------------------------------------------------------
     363          32 : Bool CEMemModel::checkImages(const Lattice<Float> *one, const Lattice<Float> *other)
     364             : {
     365          32 :   Bool isOK = true;
     366             : 
     367         160 :   for (uInt i = 0; i < one->ndim(); i++) {
     368         128 :     AlwaysAssert(one->shape()(i) == other->shape()(i), AipsError);
     369             :   }
     370          32 :   return isOK;
     371             : };
     372             : 
     373             : 
     374             : //----------------------------------------------------------------------
     375          10 : Bool CEMemModel::ok() 
     376             : {
     377          10 :   Bool isOK = true;
     378          10 :   if (!itsModel_ptr) {
     379           0 :     isOK = false;
     380             :   } else {
     381          10 :     isOK = checkImage(itsModel_ptr);
     382          10 :     if (itsPrior_ptr) {
     383           0 :       checkImages(itsModel_ptr, itsPrior_ptr);
     384             :     }
     385          10 :     if (itsMask_ptr) {
     386          10 :       checkImages(itsModel_ptr, itsMask_ptr);
     387             :     }
     388          10 :     if (itsStep_ptr) {
     389          10 :       checkImages(itsModel_ptr, itsStep_ptr);
     390             :     }
     391          10 :     if (itsResidual_ptr) {
     392          10 :       checkImages(itsModel_ptr, itsResidual_ptr);
     393             :     }
     394          10 :     if (! itsEntropy_ptr) {
     395           0 :       isOK = false;
     396             :     }
     397             : 
     398             :     // Also need to check state variables in the future!
     399             :   }
     400          10 :   return isOK;
     401             : };
     402             : 
     403           2 : void CEMemModel::setMask(Lattice<Float> & mask)
     404             : { 
     405           2 :   checkImages(itsModel_ptr, &mask); 
     406           2 :   itsMask_ptr = &mask;
     407           2 :   initStuff();
     408           2 : }
     409             : 
     410             : 
     411           2 : void CEMemModel::state()
     412             : {
     413           2 :    if (itsPrior_ptr == 0) {
     414           2 :     itsLog << "Using blank prior image" << LogIO::POST;
     415             :   } else {
     416           0 :     itsLog << "Using prior image "  << LogIO::POST;
     417             :   }
     418           2 :   if (itsMask_ptr != 0) {
     419           2 :     itsLog << "Using mask to restrict emission" << LogIO::POST;
     420             :   }
     421           2 : }
     422             : 
     423             : //----------------------------------------------------------------------
     424           2 : Bool CEMemModel::solve(ResidualEquation<Lattice<Float> >  & eqn) 
     425             : {
     426           2 :   itsResidualEquation_ptr = &eqn;
     427           2 :   Bool converged = false;
     428           2 :   Bool endNow = false;
     429           2 :   state();
     430             : 
     431           2 :   itsEntropy_ptr->infoBanner();
     432             : 
     433           2 :   for (itsIteration = itsFirstIteration;
     434          12 :        ( (itsIteration < itsNumberIterations) && !endNow);
     435          10 :        itsIteration++) {
     436          10 :     if (itsDoImagePlane) {
     437          10 :       itsTargetChisq = square(itsSigma) * itsNumberPixels;
     438             :     } else {
     439           0 :       itsTargetChisq = square(itsSigma) * itsNumberPixels / itsQ;
     440             :     }
     441             : 
     442          10 :     oneIteration();
     443             : 
     444          10 :     itsFit = sqrt((double)( itsChisq / itsTargetChisq) );
     445          10 :     itsAFit = max(itsFit, 1.0f) * 
     446          10 :       sqrt((double)( itsTargetChisq / itsNumberPixels) );
     447          10 :     itsEntropy_ptr->infoPerIteration(itsIteration);
     448             : 
     449          10 :     converged = itsEntropy_ptr->testConvergence();
     450          10 :     if (! converged && getThreshold() > 0.0) {
     451           0 :       converged = testConvergenceThreshold();
     452             :     }
     453             : 
     454          10 :     if (itsNormGrad > itsMaxNormGrad) {
     455           0 :       endNow = true;
     456           0 :       itsLog << " Excessive gradient: stopping now" << LogIO::EXCEPTION;
     457             :     }
     458             : 
     459          10 :     if (converged) {
     460           1 :       endNow = true;;
     461           1 :       itsLog << "Converged at iteration " << itsIteration+1 << LogIO::POST;
     462             :     }
     463             : 
     464             :   }
     465           2 :   if (!converged) {
     466           2 :     itsLog << "MEM failed to converge after " <<  itsNumberIterations+1 
     467           1 :            << " iterations" << LogIO::POST;
     468             :   }    
     469             : 
     470           2 :   formFlux();
     471           2 :   return converged;
     472             : };
     473             : 
     474           0 : Bool CEMemModel::testConvergenceThreshold()
     475             : { 
     476           0 :   Bool less = false; 
     477           0 :   if (getThreshold() > 0.0) {
     478           0 :    if (itsCurrentPeakResidual < getThreshold() ) {
     479           0 :      less = true;
     480             :    }
     481             :   }
     482           0 :   return less;
     483             : };
     484             : 
     485          34 : Bool CEMemModel::applyMask( Lattice<Float> & lat ) {
     486          34 :   if (itsMask_ptr) {
     487          64 :     LatticeExpr<Float> exp = ( (*itsMask_ptr) * (lat) );
     488          32 :     lat.copyData( exp );
     489          32 :     return true;
     490          32 :   } else {
     491           2 :     return false;
     492             :   }
     493             : };
     494             : 
     495             : 
     496          10 : void  CEMemModel::oneIteration()
     497             : {
     498          10 :   ok();
     499          10 :   if (itsDoInit) {
     500           2 :     itsDoInit = false;
     501             :     // passing *this reverts to the LinearModel from which we are derived
     502           2 :     itsResidualEquation_ptr->residual( *itsResidual_ptr, 
     503           2 :                                        itsChisq,
     504             :                                        *this);
     505           2 :     applyMask( *itsResidual_ptr );
     506             : 
     507           2 :     if (!itsDoImagePlane) itsChisq /= itsQ;  
     508             : 
     509           2 :     if (itsAlpha == 0.0 || itsBeta == 0.0)
     510           2 :       changeAlphaBeta();
     511             :   }
     512             : 
     513             : 
     514          10 :   calculateStep();
     515          10 :   relaxMin();
     516             :   
     517             :   // limit the step to less than the gain
     518          10 :   Float scale = 1.0;
     519          10 :   Float scalem = 1.0;
     520          10 :   if (itsNormGrad > 0.0)
     521          10 :     scalem = itsGain/itsNormGrad;
     522          10 :   scale = min(1.0f, scalem);
     523             : 
     524          10 :   takeStep(1.0, scale);
     525             : 
     526             :   // passing *this reverts to the LinearModel from which we are derived
     527          10 :   itsResidualEquation_ptr->residual( *itsResidual_ptr, 
     528          10 :                                      itsChisq,
     529             :                                      *this);
     530          10 :   applyMask( *itsResidual_ptr );
     531          10 :   if (!itsDoImagePlane) itsChisq /= itsQ;  
     532             : 
     533          10 :   if (itsThreshold0 > 0.0) {
     534           0 :     LatticeExprNode LEN = max(*itsResidual_ptr);
     535           0 :     Float rmax = LEN.getFloat();
     536           0 :     LEN = min(*itsResidual_ptr);
     537           0 :     Float rmin = LEN.getFloat();
     538           0 :     itsCurrentPeakResidual =  max (abs(rmax), abs(rmin));
     539           0 :   }
     540             : 
     541             :   // form Gradient dot Step
     542          10 :   formGDS();
     543             :   
     544             : 
     545             :   // determine optimal step
     546          10 :   Double eps = 1.0;
     547          10 :   if (itsGradDotStep0 != itsGradDotStep1) 
     548          10 :     eps = itsGradDotStep0/(itsGradDotStep0-itsGradDotStep1);
     549          10 :   if (scale != 0.0f) eps = min(eps, (Double)(scalem/scale) );
     550          10 :   if (eps <= 0.0) {
     551           0 :     eps = 1.0;
     552           0 :     itsLog << "warning: eps = 0.0" << LogIO::WARN;
     553             :   }
     554             :   
     555             :   // Step to optimum point
     556             :   
     557          10 :   if (abs(eps-1.0) > itsGain) {
     558           4 :     takeStep(1.0, scale*(eps-1.0));
     559             :     // passing *this reverts to the LinearModel from which we are derived
     560           4 :     itsResidualEquation_ptr->residual( *itsResidual_ptr, 
     561           4 :                                        itsChisq,
     562             :                                        *this);                                 
     563           4 :     applyMask( *itsResidual_ptr );
     564           4 :     if (!itsDoImagePlane) itsChisq /= itsQ;  
     565             : 
     566           4 :     if (itsThreshold0 > 0.0) {
     567           0 :       LatticeExprNode LEN = max(*itsResidual_ptr);
     568           0 :       Float rmax = LEN.getFloat();
     569           0 :       LEN = min(*itsResidual_ptr);
     570           0 :       Float rmin = LEN.getFloat();
     571           0 :       itsCurrentPeakResidual =  max (abs(rmax), abs(rmin));
     572           0 :     }
     573             :     
     574             :   }
     575             : 
     576          10 :   formEntropy();
     577             :   //  formFlux();
     578             : 
     579             :   // readjust beam volume
     580          10 :   itsQ = itsQ*(1.0/max(0.5, min(2.0,eps))+1.0)/2.0;
     581             : 
     582          10 :   changeAlphaBeta();
     583          10 : };
     584             : 
     585             : 
     586             : 
     587             : //----------------------------------------------------------------------
     588          10 : void CEMemModel::calculateStep()
     589             : {
     590             :   
     591          10 :   formGDGStep();
     592             : 
     593          10 :   formFlux();
     594          10 :   itsGradDotStep0 = itsGDG(J,J);
     595          10 :   itsLength = itsGDG(H,H) + square(itsAlpha) * itsGDG(C,C) 
     596          10 :     + square(itsBeta) * itsGDG(F,F);
     597          10 :   if (itsLength <= 0.0) {
     598           0 :     itsLength = itsGDG(F,F);
     599             :   }
     600          10 :   itsNormGrad = itsGDG(J,J) / itsLength;
     601          10 : };
     602             : 
     603             : 
     604             : //----------------------------------------------------------------------
     605          14 : void CEMemModel::takeStep(Float wt1, Float wt2)
     606             : {
     607          14 :   Lattice<Float> &model = *itsModel_ptr;
     608          14 :   Lattice<Float> &step  = *itsStep_ptr;
     609          14 :   LatticeExprNode  node;
     610             : 
     611          14 :   applyMask( step );
     612             : 
     613          14 :   node = max ( (wt1*model  + wt2*step), itsRequiredModelMin);
     614          14 :   model.copyData( (LatticeExpr<Float>)node);
     615          14 : };
     616             : 
     617             : 
     618             : 
     619             : //----------------------------------------------------------------------
     620          16 : Float CEMemModel::formFlux()
     621             : {
     622          16 :   itsFlux = 0.0;
     623          16 :   itsModelMin =  1e+20;
     624          16 :   itsModelMax = -1e+20;
     625             : 
     626          16 :   Lattice<Float> &model = *itsModel_ptr;
     627          32 :   TiledLineStepper mtls(model.shape(), model.niceCursorShape(), 0);
     628          16 :   RO_LatticeIterator<Float> mod( model, mtls); 
     629        3216 :   for (mod.reset(); !mod.atEnd(); mod++) {
     630      643200 :     for (uInt i=0;i<mod.vectorCursor().nelements();i++) {
     631      640000 :       itsFlux +=  mod.vectorCursor()(i);
     632      640000 :       if (mod.vectorCursor()(i) > itsModelMax)
     633        2788 :         itsModelMax = mod.vectorCursor()(i);
     634      640000 :       if (mod.vectorCursor()(i) < itsModelMin)
     635        3938 :         itsModelMin = mod.vectorCursor()(i);
     636             :     }
     637             :   }
     638          16 :   return itsFlux;
     639          16 : };
     640             : 
     641             : 
     642             : 
     643             : } //# NAMESPACE CASA - END
     644             : 

Generated by: LCOV version 1.16