casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
IncCEMemModel.h
Go to the documentation of this file.
00001 //# IncCEMemModel.h: this defines IncCEMemModel
00002 //# Copyright (C) 1996,1997,1998,1999,2000
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //# $Id$
00027 
00028 #ifndef SYNTHESIS_INCCEMEMMODEL_H
00029 #define SYNTHESIS_INCCEMEMMODEL_H
00030 
00031 
00032 #include <casa/aips.h>
00033 #include <casa/Arrays/Matrix.h>
00034 #include <casa/Arrays/Vector.h>
00035 #include <casa/Arrays/Array.h>
00036 #include <lattices/Lattices/Lattice.h>
00037 #include <images/Images/PagedImage.h>
00038 #include <synthesis/MeasurementEquations/IncEntropy.h>
00039 #include <synthesis/MeasurementEquations/LinearEquation.h>
00040 #include <synthesis/MeasurementEquations/LinearModel.h>
00041 #include <casa/Logging/LogIO.h>
00042 
00043 
00044 namespace casa { //# NAMESPACE CASA - BEGIN
00045 
00046 // Forward declaration
00047 class LatConvEquation;
00048 class CEMemProgress;
00049 
00050 
00051 // <summary> performs MEM algorithm incrementally </summary>
00052 
00053 // <use visibility=export>
00054 
00055 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00056 // </reviewed>
00057 
00058 // <prerequisite> 
00059 // <li> ResidualEquation/ConvolutionEquation 
00060 // <li> LinearModel/LinearEquation Paradigm 
00061 // </prerequisite>
00062 //
00063 // <etymology>
00064 // This class is called CEMemModel because it uses the Cornwell and
00065 // Evans MEM algorithm to deconvolve the model.  The "Inc" is from Incremental,
00066 // as the gradient is calculated from an incremental dirty image, but the
00067 // entropy is calculated from the previous model plus the deltaModel
00068 // </etymology>
00069 //
00070 // <synopsis>
00071 // This class is used to perform the  Cornwell and Evans MEM Algorithm on an
00072 // Array. Only the deconvolved model of the sky are directly stored by this
00073 // class. The point spread function (psf) and convolved (dirty) image are
00074 // stored in a companion class which is must be derived from
00075 // ResidualEquation. 
00076 // 
00077 // The deconvolution works like this. The user constructs a CEMemModel by
00078 // specifying an initial model of the sky. This can by be
00079 // one,two,three... dimensional depending on the dimension of the psf (see
00080 // below). The user then constructs a class which implements the forward
00081 // equation between the model and the dirty image. Typically this will be
00082 // the ConvolutionEquation class, although any class which has a
00083 // ResidualEquation interface will work (but perhaps very slowly, as the
00084 // ConvolutionEquation class has member functions optimised for CLEAN and MEM)
00085 //
00086 // The user then calls the solve() function (with the appropriate equation
00087 // class as an arguement), and this class will perform the MEM deconvolution.
00088 // The various MEM parameters are set (prior to calling solve) using the
00089 // functions derived from the Iterate class, in particular
00090 // setNumberIterations().
00091 // 
00092 // The solve() function does not return either the deconvolved model or the
00093 // residuals. The solved model can be obtained using the getModel() function
00094 // (derived from ArrayModel()) and the residual can be obtained using the
00095 // residual() member function of the Convolution/Residual Equation Class.
00096 // 
00097 // The size and shape of the model used in this class MUST be the same as
00098 // the convolved data (Dirty Image), stored in the companion
00099 // ResidualEquation Class. However the model (and convolved data) can have
00100 // more dimensions than the psf, as well as a different size (either larger
00101 // or smaller). When the dimensionality is different the deconvolution is done
00102 // independendtly in each "plane" of the model. (Note this has not
00103 // been implemented yet but is relatively simple to do if necessary). 
00104 //
00105 // StokesVectors are not yet implemented.
00106 //
00107 // A companion class to this one is MaskedCEMemModel. This provides
00108 // the same functionality but is used with MaskedArrays which indicate which
00109 // regions of the NewtonRaphson (residual) image to apply when forming the
00110 // step image (MaskedCEMemModel is not yet implemented).
00111 //
00112 // </synopsis>
00113 //
00114 // <example>
00115 // <srcblock>
00116 // Matrix<Float> psf(12,12), dirty(10,10), initialModel(10,10);
00117 // ...put appropriate values into psf, dirty, & initialModel....
00118 // CEMemModel<Float> deconvolvedModel(initialModel); 
00119 // ConvolutionEquation convEqn(psf, dirty);
00120 // deconvolvedModel.setSigma(0.001); 
00121 // deconvolvedModel.setTargetFlux(-2.500); 
00122 // deconvolvedModel.setNumberIterations(30);
00123 // Bool convWorked = deconvolvedModel.solve(convEqn);
00124 // Array<Float> finalModel, residuals;
00125 // if (convWorked){
00126 //   finalModel = deconvolvedModel.getModel();
00127 //   ConvEqn.residual(deconvolvedModel, finalResidual);
00128 // }
00129 // </srcblock> 
00130 // </example>
00131 //
00132 // <motivation>
00133 // This class is needed to deconvolve extended images.  
00134 // In time, the MEM algorithm will be a principle player in the 
00135 // mosaicing stuff.
00136 // </motivation>
00137 //
00138 // <templating arg=T>
00139 //    For testing:
00140 //    <li> Float: lets try it first
00141 //    <li> StokesVector: will require lots more work
00142 // </templating>
00143 //
00144 // <todo asof="1998/12/02">
00145 //   <li> We need to implement soft Masking
00146 // </todo>
00147 
00148 class IncCEMemModel: public LinearModel< Lattice<Float> > 
00149 {
00150 
00151   // Any new entropies derived from Entropy must sign the friend list:
00152 friend class IncEntropy;
00153 friend class IncEntropyI;
00154 friend class IncEntropyEmptiness;
00155 
00156 
00157 public:
00158 
00159   // Construct the CEMemModel object and initialise the model.
00160   IncCEMemModel(IncEntropy &ent, 
00161                 Lattice<Float> & model,      // previous model, logically const
00162                 Lattice<Float> & deltaModel, // this one changes 
00163                 uInt nIntegrations = 10,
00164                 Float sigma = 0.001,
00165                 Float targetFlux = 1.0,
00166                 Bool useFluxConstraint = False,
00167                 Bool initializeModel = True,
00168                 Bool imagePlane = False);
00169 
00170   // Construct the CEMemModel object, initialise the model and Prior images.
00171   IncCEMemModel(IncEntropy &ent, 
00172                 Lattice<Float> & model,
00173                 Lattice<Float> & deltaModel,
00174                 Lattice<Float> & prior,
00175                 uInt nIntegrations = 10,
00176                 Float sigma = 0.001,
00177                 Float targetFlux = 1.0,
00178                 Bool useFluxConstraint = False,
00179                 Bool initializeModel = True,
00180                 Bool imagePlane = False);
00181   
00182   // Construct the CEMemModel object, initialise the model and 
00183   // and mask images.
00184   IncCEMemModel(IncEntropy &ent, 
00185                 Lattice<Float> & model, 
00186                 Lattice<Float> & deltaModel, 
00187                 uInt nIntegrations,
00188                 Lattice<Float> & mask,
00189                 Float sigma = 0.001,
00190                 Float targetFlux = 1.0,
00191                 Bool useFluxConstraint = False,
00192                 Bool initializeModel = True,
00193                 Bool imagePlane = False);
00194 
00195   // Construct the CEMemModel object, initialise the model, Prior,
00196   // and mask images.
00197   IncCEMemModel(IncEntropy &ent, 
00198                 Lattice<Float> & model, 
00199                 Lattice<Float> & deltaModel, 
00200                 Lattice<Float> & prior,
00201                 Lattice<Float> & mask,
00202                 uInt nIntegrations = 10,
00203                 Float sigma = 0.001,
00204                 Float targetFlux = 1.0,
00205                 Bool useFluxConstraint = False,
00206                 Bool initializeModel = True,
00207                 Bool imagePlane = False);
00208 
00209 
00210   // destructor
00211   virtual ~IncCEMemModel();
00212 
00213   
00214   // solve the convolution equation
00215   // returns True if converged
00216 
00217   // Gives information about the state of the CEMem
00218   // (ie, using mask image, using prior image; more work here!)
00219   void state();
00220 
00221 
00222   //  This needs to be "ResidualEquation", using LatConvEquation as
00223   //  polymorphism is broken
00224   Bool solve(ResidualEquation<Lattice<Float> >  & eqn);
00225 
00226   // Set and get various state images and classes
00227   // <group>
00228   // set or get the Entropy class
00229   void setEntropy(IncEntropy &myEntropy ) {itsEntropy_ptr = &myEntropy;}
00230   void getEntropy(IncEntropy &myEntropy ) {myEntropy = *itsEntropy_ptr;}
00231 
00232   // set or get the Model image
00233   Lattice<Float>& getModel() const 
00234     { return (*(itsDeltaModel_ptr)); }
00235   void setModel(const Lattice<Float> & model)
00236     { itsDeltaModel_ptr = model.clone(); }
00237 
00238   // set or get the Prior image
00239   Lattice<Float>& getPrior() const 
00240     { return (*(itsPrior_ptr->clone())); }
00241   void setPrior(Lattice<Float> & prior);
00242 
00243   // set or get the Mask image
00244   Lattice<Float>& getMask() const 
00245     { return (*(itsMask_ptr->clone())); }
00246   void setMask(Lattice<Float> & mask);
00247   // </group>
00248 
00249 
00250   // set and get alpha, beta, and Q
00251   // <group>
00252   Float getAlpha() const { return itsAlpha; }
00253   Float getBeta() const { return itsBeta; }
00254   void setAlpha(Float alpha) {itsAlpha = alpha; }
00255   void setBeta(Float beta) {itsBeta = beta; }
00256   // </group>
00257 
00258   // Set various controlling parameters
00259   // (The most popular controlling parameters are 
00260   // set in the constructor)
00261   // <group>
00262   Float getTolerance() {return itsTolerance; }
00263   void  setTolerance(Float x) { itsTolerance = x; }
00264   Float getQ() {return itsQ; }
00265   void  setQ(Float x) { itsQ= x; }
00266   Float getGain() {return itsGain; }
00267   void  setGain(Float x) { itsGain = x; }
00268   Float getMaxNormGrad() {return itsMaxNormGrad; }
00269   void  setMaxNormGrad(Float x) { itsMaxNormGrad = x; }
00270   Int getInitialNumberIterations() {return itsFirstIteration; }
00271   void  setInitialNumberIterations(Int x) { itsFirstIteration = x; }
00272   // </group>
00273 
00274   // The convergence can also be in terms of the maximum residual
00275   // (ie, for use in stopping in a major cycle).
00276   void setThreshold (const Float x ) { itsThreshold0 = x; }
00277   // Thresh doubles in iter iterations
00278   void setThresholdSpeedup (const Float iter) {itsThresholdSpeedup = iter; }
00279   Float getThreshold();
00280 
00281   // Set/get the progress display 
00282   // <group>
00283   virtual void setProgress(CEMemProgress& ccp) { itsProgressPtr = &ccp; }
00284   virtual CEMemProgress& getProgress() { return *itsProgressPtr; }
00285   // </group>
00286 
00287   // return the number of iterations completed
00288   Int numberIterations () { return itsIteration; }
00289 
00290 protected:
00291 
00292 
00293   // Perform One Iteration
00294   void oneIteration();
00295 
00296   // apply mask to a lattice; returns True if mask is available, 
00297   // False if not
00298   Bool applyMask( Lattice<Float> & lat );
00299 
00300   // Helper functions that interface with Entropy routines
00301   // Access to the entropy should be through this interface; the
00302   // points at which the Entropy is mentioned is then limited to
00303   // these lines right here, and to the constructors which set the
00304   // Entropy.  The entropy should not ever change the private
00305   // 
00306   // <group>
00307   void formEntropy() { itsEntropy = itsEntropy_ptr->formEntropy(); }
00308 
00309   void  formGDG() { itsEntropy_ptr->formGDG( itsGDG ); }
00310 
00311   void  formGDGStep() { itsEntropy_ptr->formGDGStep( itsGDG ); }
00312 
00313   void formGDS() { itsGradDotStep1=itsEntropy_ptr->formGDS(); }
00314 
00315   void entropyType(String &str) { itsEntropy_ptr->entropyType(str); }
00316 
00317   void relaxMin() { itsRequiredModelMin = itsEntropy_ptr->relaxMin(); }
00318 
00319   Bool testConvergence() { return itsEntropy_ptr->testConvergence(); }
00320 
00321   // </group>
00322 
00323 
00324   // protected generic constrcutor: DON'T USE IT!
00325   IncCEMemModel();
00326 
00327   // Set entropy pointer to zero: called by Entropy's destructor
00328   void letEntropyDie() { itsEntropy_ptr = 0; }
00329 
00330   // initialize itsStep and itsResidual and other stuff
00331   Bool initStuff();
00332 
00333 
00334   // controls how to change Alpha and Beta
00335   // <group>
00336   void changeAlphaBeta ();
00337   // initialize Alpha-Beta (called by changeAlphaBeta)
00338   void initializeAlphaBeta();
00339   // update Alpha-Beta (called by changeAlphaBeta)
00340   void updateAlphaBeta();
00341   // </group>
00342 
00343 
00344 
00345 
00346   // Generic utility functions
00347   // <group>
00348   // check that a single image is onf plausible shape
00349   Bool checkImage(const Lattice<Float> *);
00350   // check that the lattices and the underlying tile sizes are consistent
00351   Bool checkImages(const Lattice<Float> *one, const Lattice<Float> *other);
00352   // check that all is well in Denmark:
00353   //     ensure all images are the same size,
00354   //     ensure we have an entropy,
00355   //     ensure state variables have reasonable values
00356   Bool ok();
00357   // </group>
00358   
00359 
00360 
00361 
00362   // Helper functions for oneIteration:
00363   // <group>
00364   // calculate size of step
00365   void calculateStep();
00366 
00367   // take one step: clipped addition of
00368   // wt1*itsModel + wt2*itsStep
00369   void takeStep(Float wt1, Float wt2);
00370 
00371   // Calculate the flux, itsModMin, and itsModMax
00372   Float formFlux();
00373   // </group>
00374 
00375   // Determine if the peak residual is less than the getThreshold()
00376   Bool testConvergenceThreshold();
00377 
00378   // ------------Private Member Data---------------------
00379   // functional form of the entropy
00380   IncEntropy  *itsEntropy_ptr;   
00381 
00382   // form of the Residual method
00383   ResidualEquation< Lattice<Float> > * itsResidualEquation_ptr;
00384 
00385   // Images:
00386   Lattice<Float> * itsModel_ptr;
00387   Lattice<Float> * itsDeltaModel_ptr;
00388   Lattice<Float> * itsPrior_ptr;
00389   Lattice<Float> * itsMask_ptr;
00390   // Our OWN internal temp images; delete these upon destruction
00391   Lattice<Float> * itsStep_ptr;
00392   Lattice<Float> * itsResidual_ptr;
00393 
00394 
00395   // Controlling parameters
00396   // <group>
00397   Bool itsInitializeModel;
00398   uInt itsNumberIterations;
00399   Bool  itsDoInit;
00400   Float itsSigma;
00401   Float itsTargetFlux;  
00402   Float itsDefaultLevel;
00403   Float itsTargetChisq;
00404   // tolerance for convergence
00405   Float itsTolerance;   
00406   // N points per beam
00407   Float itsQ;           
00408   // gain for adding step image
00409   Float itsGain;        
00410   Float itsMaxNormGrad;
00411   // constrain flux or not?
00412   Bool  itsUseFluxConstraint;  
00413   // is this an image plane problem (like Single Dish or Optical?)
00414   Bool  itsDoImagePlane;
00415   Float itsThreshold0;
00416   Float itsThresholdSpeedup;
00417   // </group>
00418 
00419   // State variables
00420   // <group>  
00421   Float itsAlpha;
00422   Float itsBeta;
00423   Float itsNormGrad;
00424   // note that            itsModelFlux + itsDeltaFlux = itsFlux
00425   Float itsFlux;       // this is the total Flux
00426   Float itsModelFlux;  // this is the flux of image itsModel_ptr
00427   Float itsDeltaFlux;  // this is the flux of image itsDeltaModel_ptr
00428   Float itsChisq;
00429   // sqrt( chi^2/target_chi^2 )
00430   Float itsFit;        
00431   // sqrt( chi^2/ Npixels )
00432   Float itsAFit;       
00433   // numerical value of entropy
00434   Float itsEntropy;    
00435   // Model is constrained to be >= itsNewMin
00436   Float itsRequiredModelMin; 
00437   // maximum pixel value in model
00438   Float itsModelMax;   
00439   // minimum pixel value n model
00440   Float itsModelMin;   
00441   Float itsLength;
00442   Double itsGradDotStep0;
00443   Double itsGradDotStep1;
00444   uInt   itsIteration;
00445   uInt   itsFirstIteration;
00446   // matrix of gradient dot products
00447   Matrix<Double> itsGDG;  
00448   Float itsCurrentPeakResidual;
00449   // </group>
00450   Float itsNumberPixels;
00451 
00452 
00453   // Accesories
00454   // <group>  
00455   Bool itsChoose;
00456   LogIO itsLog;
00457   // </group>  
00458 
00459   // Enumerate the different Gradient subscript types
00460   enum GradientType {
00461     // Entropy
00462     H=0,
00463     // Chi_sq
00464     C=1,
00465     // Flux
00466     F=2,
00467     // Objective function J
00468     J=3
00469   };
00470 
00471   CEMemProgress* itsProgressPtr;
00472  
00473 
00474 };
00475 
00476 
00477 
00478 } //# NAMESPACE CASA - END
00479 
00480 #endif
00481