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