casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
GaussianNDParam.h
Go to the documentation of this file.
00001 //# GaussianNDParam.h: Multidimensional Gaussian class parameters
00002 //# Copyright (C) 2001,2002,2004,2005
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: GaussianNDParam.h 21024 2011-03-01 11:46:18Z gervandiepen $
00027 
00028 #ifndef SCIMATH_GAUSSIANNDPARAM_H
00029 #define SCIMATH_GAUSSIANNDPARAM_H
00030 
00031 //# Includes
00032 #include <casa/aips.h>
00033 #include <scimath/Functionals/Function.h>
00034 #include <casa/Arrays/Matrix.h>
00035 #include <casa/Arrays/Vector.h>
00036 #include <casa/BasicSL/String.h>
00037 
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 
00040 // <summary> A Multi-dimensional Gaussian parameter handling. </summary>
00041 
00042 // <use visibility=local>
00043 
00044 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="tGaussianND" demos="dGaussianND">
00045 // </reviewed>
00046 
00047 // <prerequisite>
00048 //   <li> <linkto class="FunctionParam">FunctionParam</linkto> class
00049 //   <li> <linkto class="Function">Function</linkto> class
00050 // </prerequisite>
00051 
00052 // <synopsis> 
00053 // A <src>GaussianND</src> is used to calculate Gaussian functions of any
00054 // dimension. A <linkto class=Gaussian1D> Gaussian1D </linkto> class exists
00055 // which is more appropriate for one dimensional Gaussian functions, and a
00056 // <linkto class=Gaussian2D> Gaussian2D </linkto> class exists for two
00057 // dimensional functions.
00058 //
00059 // A statistical description of the multi-dimensional Gaussian is used (see
00060 // Kendall & Stuart "The Advanced Theory of Statistics").  A Gaussian is
00061 // defined in terms of its height, mean (which is the location of the peak
00062 // value), variance, (a measure of the width of the Gaussian), and
00063 // covariance which skews the distribution with respect to the Axes.
00064 //
00065 // In the general description the variance and covariance are specified
00066 // using a covariance matrix.  This is defined as (for a 4 dimensional
00067 // Gaussian):
00068 // <srcblock>
00069 //  V = |     s1*s1 r12*s1*s2 r13*s1*s3 r14*s1*s4 | 
00070 //      | r12*s1*s2     s2*s2 r23*s2*s3 r24*s2*s4 |
00071 //      | r13*s1*s3 r23*s2*s3     s3*s3 r34*s3*s4 |
00072 //      | r14*s1*s4 r24*s2*s4 r34*s3*s4     s4*s4 |
00073 // </srcblock>
00074 // where s1 (<src>sigma1</src>) is the standard deviation of the Gaussian with
00075 // respect to the first axis, and r12 (<src>rho12</src>) is the correlation
00076 // between the the first and second axis. The correlation MUST be between -1
00077 // and 1, and this class checks this as well as ensuring that the diagonal
00078 // is positive. 
00079 //
00080 // <note role=warning> It is possible to have symmetric matrices that are of
00081 // the above described form (ie. symmetric with <src>-1 <= rho(ij) <=1</src>)
00082 // that do
00083 // not generate a Gaussian function. This is because the Matrix is NOT
00084 // positive definite (The limits on <src>rho(ij)</src> are upper limits).
00085 // This class
00086 // does check that the covariance Matrix is positive definite and will throw
00087 // an exception (AipsError) if it is not.</note>
00088 //
00089 // The covariance Matrix can be specified by only its upper or lower
00090 // triangular regions (ie. with zeros in the other triangle), otherwise it
00091 // MUST be symmetric.
00092 //
00093 // The Gaussian that is constructed from this covariance Matrix (V), along
00094 // with mean (u) and height (h) is:
00095 // <srcblock>
00096 //  f(x) = h*exp( -1/2 * (x-u) * V^(-1) * (x-u))
00097 // </srcblock>
00098 // where x, and u are vectors whose length is the dimensionality of the
00099 // Gaussian and V^(-1) is the inverse of the covariance Matrix defined
00100 // above. For a two dimensional Gaussian with zero mean this expression
00101 // reduces to:
00102 // <srcblock>
00103 // f(x) = h*exp(-1/(2*(1-r12^2))*(x1^2/s1^2 - 2*r12*x1*x2/(s1*s2) + x2^2/s2^2))
00104 // </srcblock>
00105 //
00106 // The amplitude of the Gaussian can be defined in two ways, either using
00107 // the peak height (as is done in the constructors, and the setHeight
00108 // function) or using the setFlux function. The flux in this context is the
00109 // analytic integral of the Gaussian over all dimensions. Using the setFlux
00110 // function does not modify the shape of the Gaussian just its height. 
00111 //
00112 // All the parameters of the Gaussian except its dimensionality can be
00113 // modified using the set/get functions.
00114 //
00115 // The parameter interface (see 
00116 // <linkto class="FunctionParam">FunctionParam</linkto> class), 
00117 // is used to provide an interface to the
00118 // <linkto module="Fitting"> Fitting </linkto> classes. 
00119 // There are always 4 parameter sets. 
00120 // <note role=warning> Note that the actual variance/covariance
00121 // parameters are the inverse matrix of the variance/covariance matrix given
00122 // by the user</note>.
00123 // The actual parameters are in order:
00124 // <ol>
00125 // <li> height (1 term). No assumptions on what quantity the height
00126 //      represents, and it can be negative (enumerated by <src>HEIGHT</src>)
00127 // <li> mean (ndim terms) (enumerated by <src>CENTER</src>).
00128 // <li> variance (ndim terms). The variance is always positive, and an
00129 //      exception (AipsError) will be thrown if you try to set a negative
00130 //      value. 
00131 // <li> covariance (ndim*(ndim-1)/2 terms) The order is (assuming ndim=5)
00132 //      v12,v13,v14,v15,v23,v24,v25,v34,v35,v45. The restrictions described
00133 //      above for the covariance (ie. -1 < r12 < +1) are enforced. 
00134 // </ol>
00135 // </synopsis> 
00136 
00137 // <example>
00138 // Construct a two dimensional Gaussian with mean=(0,1), variance=(.1,7) and
00139 // height = 1;
00140 // <srcblock>
00141 // uInt ndim = 2;
00142 // Float height = 1;
00143 // Vector<Float> mean(ndim); mean(0) = 0, mean(1) = 1;
00144 // Vector<Float> variance(ndim); variance(0) = .1, variance(1) = 7;
00145 // GaussianND<Float> g(ndim, height, mean, variance); 
00146 // Vector<Float> x(ndim); x = 0;
00147 // cout << "g("<< x <<") = " << g(x) <<endl; // g([0,0])=1*exp(-1/2*1/7);
00148 // x(1)++;
00149 // cout << "g("<< x <<") = " <<g(x) <<endl;  // g([0,1])= 1
00150 // cout << "Height: " << g.height() <<endl;    // Height: 1
00151 // cout << "Flux: " << g.flux() << endl;       // Flux: 2*Pi*Sqrt(.1*7)
00152 // cout << "Mean: " << g.mean() << endl;  // Mean: [0, -1]
00153 // cout << "Variance: " << g.variance() <<endl;  // Variance: [.1, 7]
00154 // cout << "Covariance: "<< g.covariance()<<endl;// Covariance: [.1, 0]
00155 //                                                       //             [0,  7]
00156 // g.setFlux(1);
00157 // cout << "g("<< x <<") = " <<g(x) <<endl;  //g([0,1])=1/(2*Pi*Sqrt(.7))
00158 // cout << "Height: " << g.height() <<endl;    // Height: 1/(2*Pi*Sqrt(.7))
00159 // cout << "Flux: " << g.flux() << endl;       // Flux: 1
00160 // cout << "Mean: " << g.mean() << endl;  // Mean: [0, -1]
00161 // cout << "Variance: " << g.variance() <<endl;  // Variance: [.1, 7]
00162 // cout << "Covariance: "<< g.covariance()<<endl;// Covariance: [.1, 0]
00163 //                                               //             [0,  7]
00164 // </srcblock>
00165 // </example>
00166 
00167 // <motivation>
00168 // A Gaussian Functional was needed for modeling the sky with a series of
00169 // components. It was later realised that it was too general and Gaussian2D
00170 // was written.  
00171 // </motivation>
00172 
00173 // <templating arg=T>
00174 //  <li> T should have standard numerical operators and exp() function. Current
00175 //      implementation only tested for real types.
00176 // </templating>
00177 
00178 // <todo asof="2001/08/19">
00179 //  <li> Nothing I know off, apart from possible optimization
00180 // </todo>
00181 
00182 template<class T> class GaussianNDParam : public Function<T>
00183 {
00184 public:
00185   //# Enumerations
00186   enum { HEIGHT=0, CENTER};
00187 
00188   //# Constructors
00189   // Constructs a Gaussian using the indicated height, mean, variance &
00190   // covariance.
00191   // ndim defaults to 2, 
00192   // mean defaults to 0, 
00193   // height to <src> Pi^(-ndim/2)</src> (the flux is unity)
00194   // variance defaults to 1.0, 
00195   // covariance defaults to 0.0, 
00196   // <group>
00197   GaussianNDParam();
00198   explicit GaussianNDParam(uInt ndim);
00199   GaussianNDParam(uInt ndim, const T &height);
00200   GaussianNDParam(uInt ndim, const T &height, const Vector<T> &mean);
00201   GaussianNDParam(uInt ndim, const T &height, const Vector<T> &mean,
00202                   const Vector<T> &variance);
00203   GaussianNDParam(uInt ndim, const T &height, const Vector<T> &mean,
00204                   const Matrix<T> &covar);
00205   // </group>
00206 
00207   // Copy constructor (deep copy)
00208   // <group>
00209   GaussianNDParam(const GaussianNDParam &other);
00210   template <class W>
00211     GaussianNDParam(const GaussianNDParam<W> &other) :
00212     Function<T>(other),
00213     itsDim(other.itsDim), itsFlux2Hgt(other.itsFlux2Hgt) {}
00214    // </group>
00215 
00216   // Copy assignment (deep copy)
00217   GaussianNDParam<T> &operator=(const GaussianNDParam<T> &other);
00218     
00219   // Destructor
00220   virtual ~GaussianNDParam();
00221 
00222   //# Operators    
00223 
00224   //# Member functions
00225   // Give name of function
00226   virtual const String &name() const { static String x("gaussiannd");
00227   return x; }
00228 
00229    // Variable dimensionality
00230   virtual uInt ndim() const { return itsDim; }
00231 
00232   // Get or set the peak height of the Gaussian
00233   // <group>
00234   T height() const { return param_p[HEIGHT]; }
00235   void setHeight(const T &height) { param_p[HEIGHT] = height; }
00236   // </group>
00237 
00238   // The analytical integrated area underneath the Gaussian. Use these 
00239   // functions as an alternative to the height functions.
00240   // <group>
00241   T flux() const;
00242   void setFlux(const T &flux);
00243   // </group>
00244 
00245   // The center ordinate of the Gaussian
00246   // <group>
00247   Vector<T> mean() const;
00248   void setMean(const Vector<T> &mean);
00249   // </group>
00250 
00251   // The FWHM of the Gaussian is <src>sqrt(8*variance*log(2))</src>.
00252   // The variance MUST be positive 
00253   // <group>
00254   Vector<T> variance() const;
00255   void setVariance(const Vector<T> &variance);
00256   // </group> 
00257 
00258   //The covariance Matrix defines the correlations between all the axes.
00259   //<group>
00260   Matrix<T> covariance() const;
00261   void setCovariance(const Matrix<T> &covar);
00262   // </group>
00263     
00264 protected:
00265   //# Data
00266   // dimensionality
00267   uInt itsDim;
00268   // factor to convert from flux to height 
00269   T itsFlux2Hgt;
00270 
00271   //# Methods
00272   // Functions to convert between internal Vector of parameters
00273   // and the Covariance
00274   // Matrix 
00275   // <group>
00276   void repack(Matrix<T> &covar) const;
00277   void unpack(const Matrix<T> &covar);
00278   // </group>
00279 
00280   //# Make members of parent classes known.
00281 protected:
00282   using Function<T>::param_p;
00283 public:
00284   using Function<T>::nparameters;
00285 };
00286 
00287 
00288 } //# NAMESPACE CASA - END
00289 
00290 #ifndef CASACORE_NO_AUTO_TEMPLATES
00291 #include <scimath/Functionals/GaussianNDParam.tcc>
00292 #endif //# CASACORE_NO_AUTO_TEMPLATES
00293 #endif