casa
$Rev:20696$
|
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