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