casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ImageMoments.h
Go to the documentation of this file.
00001 //# ImageMoments.h: generate moments from images
00002 //# Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003
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: ImageMoments.h 20299 2008-04-03 05:56:44Z gervandiepen $
00027 
00028 #ifndef IMAGES_IMAGEMOMENTS_H
00029 #define IMAGES_IMAGEMOMENTS_H
00030 
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <coordinates/Coordinates/CoordinateSystem.h>
00035 #include <casa/Quanta/QMath.h>
00036 #include <casa/Quanta/Quantum.h>
00037 #include <measures/Measures/MDoppler.h>
00038 #include <casa/System/PGPlotter.h>
00039 #include <casa/Logging/LogIO.h>
00040 #include <casa/Arrays/Vector.h>
00041 #include <casa/iosfwd.h>
00042 #include <imageanalysis/ImageAnalysis/MomentsBase.h>
00043 
00044 namespace casa { //# NAMESPACE CASA - BEGIN
00045 
00046 //# Forward Declarations
00047 template <class T> class Matrix;
00048 template <class T> class MomentCalcBase;
00049 template <class T> class SubImage;
00050 template <class T> class ImageInterface;
00051 template <class T> class MaskedLattice;
00052 template <class T> class Lattice;
00053 template <class T> class PtrHolder;
00054 class IPosition;
00055 class String;
00056 class Unit;
00057 class ImageMomentsProgressMonitor;
00058 //template <class T> class MomentsBase;
00059 
00060 // <summary>
00061 // This class generates moments from an image.
00062 // </summary>
00063 
00064 // <use visibility=export>
00065 
00066 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00067 // </reviewed>
00068 
00069 // <prerequisite>
00070 //   <li> <linkto class="ImageInterface">ImageInterface</linkto>
00071 //   <li> <linkto class="MomentsBase">MomentsBase</linkto>
00072 //   <li> <linkto class="LatticeApply">LatticeApply</linkto>   
00073 //   <li> <linkto class="MomentCalcBase">MomentCalcBase</linkto>
00074 // </prerequisite>
00075 
00076 // <etymology>
00077 //   This class computes moments from images
00078 // </etymology>
00079 
00080 // <synopsis>
00081 //  The primary goal of this class is to help spectral-line astronomers analyze 
00082 //  their multi-dimensional images by generating moments of a specified axis.
00083 //  The word "moment" is used loosely here.  It refers to collapsing an axis
00084 //  to one pixel and putting the value of that pixel (for all of the other 
00085 //  non-collapsed axes) to something computed from the data values along
00086 //  the moment axis.  For example, take an RA-DEC-Velocity cube, collapse
00087 //  the velocity axis by computing the mean intensity at each RA-DEC
00088 //  pixel.  This class offers many different moments and a variety of
00089 //  interactive and automatic ways to compute them.
00090 //
00091 //  This class only accepts images of type <src>Float</src> and <src>Double</src>.
00092 //  This restriction is because of the plotting capabilities which are a
00093 //  bit awkward for other types.
00094 //
00095 //  This class makes a distinction between a "moment" and a "method". This
00096 //  boundary is a little blurred, but it claims to refer to the distinction 
00097 //  of what you are computing, as to how the pixels that were included in the 
00098 //  computation were selected.  For example,  a "moment" would be the average value 
00099 //  of some pixels.  A method for selecting those pixels would be a simple range 
00100 //  specifying  a range for which pixels should be included.
00101 //
00102 //  The default state of this class is to do nothing.  If you specify an image via
00103 //  the <src>setImage</src> function then invoking the <src>createMoments</src>
00104 //  function will cause it to compute the integrated itensity along the 
00105 //  spectral axis of the image (if it can find one).  You can change the 
00106 //  computational state of the class from this basic form via the remaining
00107 //  <src>set</src> functions.  You can call any number of these functions to 
00108 //  suit your needs.
00109 //
00110 //  Because there are a wide variety of methods available, if you specify an
00111 //  invalid combination, a table showing the available methods is listed. It
00112 //  is reproduced below for convenience.  
00113 //
00114 //  The basic method is to just compute moments directly from the pixel intensities.  
00115 //  This can be modified by applying pixel intensity inclusion or exclusion ranges.  
00116 //  You can then also smooth the image and compute a mask based on the inclusion or 
00117 //  exclusion ranges applied to the smoothed image.  This mask is then applied to 
00118 //  the unsmoothed data for moment computation.
00119 //
00120 //  The window method does no pixel intensity range selection.  Instead a spectral
00121 //  window is found (hopefully surrounding the spectral line feature) and only the 
00122 //  pixels in that window are used for computation.  This window can be found from the 
00123 //  smoothed or unsmoothed data.  The moments are always computed from the unsmoothed 
00124 //  data.  For each spectrum, the window can be found interactively or automatically.
00125 //  There are two interactive methods.  Either you just mark the window with the
00126 //  cursor, or you interactively fit a Gaussian to the profile and the +/- 3-sigma
00127 //  window is returned.  There are two automatic methods.  Either Bosma's converging
00128 //  mean algorithm is used, or an automatically  fit Gaussian +/- 3-sigma window
00129 //  is returned.
00130 //
00131 //  The fitting method fits Gaussians to spectral features either automatically
00132 //  or interactively.  The moments are then computed from the Gaussian fits
00133 //  (not the data themselves).
00134 //
00135 //  When an output image is created, it will have N-1 axes, where the input image
00136 //  has N axes.  In the output image, the physical axis corresponding to the moment
00137 //  axis will have been removed, but the coordinate information will be retained 
00138 //  for future coordinate transformations. For example, if you have a RA-DEC-VELOCITY 
00139 //  image and you collapsed axis 2 (the DEC axis) the output images would be 
00140 //  RA-VELOCITY with the coordinate information retained for the DEC axis so that 
00141 //  the coupled nature of RA/DEC coordinates is preserved.    
00142 //
00143 //  Output images are created with an all True (good) mask.  If, for a given
00144 //  pixel, the moment calculation fails, then the mask is set to F.
00145 //
00146 //  When making plots, the order in which the spectra are  displayed is determined
00147 //  by the tiling sequence of the image (for optimum speed of access).  
00148 //
00149 //
00150 // <srcblock>
00151 //                   Allowed Methods
00152 //                   ---------------
00153 //
00154 //   Smooth    Window      Fit   in/exclude   Interactive 
00155 //   -----------------------------------------------------
00156 //     N          N         N        N            N       
00157 //     Y/N        N         N        Y            N       
00158 // 
00159 //     Y/N        Y         N        N            Y       
00160 //     Y/N        Y         N        N            N       
00161 //     Y/N        Y         Y        N            Y/N     
00162 //
00163 //     N          N         Y        N            Y/N     
00164 //   ----------------------------------------------------
00165 // </srcblock>
00166 //
00167 // <note role=caution>
00168 // Note that the <src>MEDIAN_COORDINATE</src> moment is not very robust.
00169 // It is very useful for generating quickly a velocity field in a way
00170 // that is not sensitive to noise.    However, it will only give sensible
00171 // results under certain conditions.   It treats the spectrum as a
00172 // probability distribution, generates the cumulative distribution for
00173 // the selected pixels (via an <src>include</src> or <src>exclude</src>
00174 // pixel range, and finds the (interpolated) coordinate coresponding to 
00175 // the 50% value.  The generation of the cumulative distribution and the
00176 // finding of the 50% level really only makes sense if the cumulative
00177 // distribution is monotonically increasing.  This essentially means only
00178 // selecting pixels which are positive or negative.  For this reason, this
00179 // moment type is *only* supported with the basic method (i.e. no smoothing,
00180 // no windowing, no fitting) with a pixel selection range that is either
00181 // all positive, or all negative.
00182 // </note>
00183 //
00184 // <note role=tip>
00185 // If you ignore return error statuses from the functions that set the
00186 // state of the class, the internal status of the class is set to bad.
00187 // This means it will just  keep on returning error conditions until you
00188 // explicitly recover the situation.  A message describing the last
00189 // error condition can be recovered with function errorMessage.
00190 // </note>
00191 // </synopsis>
00192 
00193 // <example>
00194 // <srcBlock>
00196 //
00197 //      Vector<Int> moments(2);
00198 //      moments(0) = ImageMoments<Float>::AVERAGE;
00199 //      moments(1) = ImageMoments<Float>::WEIGHTED_MEAN_COORDINATE;
00200 //      Vector<int> methods(2);
00201 //      methods(0) = ImageMoments<Float>::WINDOW;
00202 //      methods(1) = ImageMoments<Float>::INTERACTIVE;
00203 //      Vector<Int> nxy(2);
00204 //      nxy(0) = 3;
00205 //      nxy(1) = 3;
00206 //
00208 //     
00209 //      PagedImage<Float> inImage(inName);  
00210 //
00212 //
00213 //      LogOrigin or("myClass", "myFunction(...)", WHERE);
00214 //      LogIO os(or);
00215 //      ImageMoments<Float> moment(SubImage<Float>(inName), os);
00216 //
00218 //
00219 //      if (!moment.setMoments(moments)) return 1;
00220 //      if (!moment.setWinFitMethod(methods)) return 1;
00221 //      if (!moment.setMomentAxis(3)) return 1;
00222 //      if (!moment.setPlotting("/xs", nxy)) return 1;
00223 //
00225 //
00226 //      if (!moment.createMoments()) return 1;
00227 // </srcBlock>
00228 // In this example, we generate two moments (average intensity and intensity
00229 // weighted mean coordinate -- usually the velocity field) of axis 3 by the 
00230 // interactive window method.  The interactive plotting is done on the PGPLOT 
00231 // device called <src>/xs</src>.   We put 9 subplots on each page.  The output 
00232 // file names are constructed by the class from the input file name plus some 
00233 // internally generated suffixes.
00234 // </example>
00235 
00236 // <motivation>
00237 //  This is a fundamental and traditional piece of spectral-line image analysis.
00238 // </motivation>
00239 
00240 // <todo asof="1996/11/26">
00241 //   <li> more control over histogram of image noise at start (pixel
00242 //        range and number of bins)
00243 //   <li> better algorithm for seeing if spectrum is pure noise
00244 //   <li> Make this class extensible so users could add their own method.
00245 // </todo>
00246  
00247 
00248 template <class T> class ImageMoments : public MomentsBase<T>
00249 {
00250 public:
00251 
00252 // Note that if I don't put MomentCalcBase as a forward declaration
00253 // and use instead  "friend class MomentCalcBase<T>"  The gnu compiler
00254 // fails with a typedef problem.  But I can't solve it with say
00255 // <src>typedef MomentCalcBase<T> gpp_type;</src>  because you can only do a 
00256 // typedef with an actual type, not a <tt>T</tt> !
00257    friend class MomentCalcBase<T>;
00258 
00259 // Constructor takes an image and a <src>LogIO</src> object for logging purposes.
00260 // You specify whether output images are  automatically overwritten if pre-existing,
00261 // or whether an intercative choice dialog widget appears (overWriteOutput=F)
00262 // You may also determine whether a progress meter is displayed or not.
00263    ImageMoments (ImageInterface<T>& image, 
00264                  LogIO &os,
00265                  Bool overWriteOutput=False,
00266                  Bool showProgress=True);
00267 
00268 // Copy constructor.  Uses copy semantics.
00269    ImageMoments(const ImageMoments<T> &other);
00270 
00271 // Copy constructor.  Uses copy semantics.
00272    ImageMoments(ImageMoments<T> &other);
00273 
00274 // Destructor
00275   ~ImageMoments();
00276 
00277 // Assignment operator. USes copy semantics.
00278    ImageMoments<T> &operator=(const ImageMoments<T> &other);
00279 
00280 // Set the moment axis (0 relative).  A return value of <src>False</src> 
00281 // indicates that the axis was not contained in the image. If you don't
00282 // call this function, the default state of the class is to set the 
00283 // moment axis to the spectral axis if it can find one.  Otherwise 
00284 // an error will result.
00285    void setMomentAxis (const Int momentAxis);
00286 
00287 // This function invokes smoothing of the input image.  Give <src>Int</src> 
00288 // arrays for the axes (0 relative) to be smoothed and the smoothing kernel 
00289 // types (use the <src>enum KernelTypes</src>) for each axis.  Give a
00290 // <src>Double</src> array for the widths (full width for BOXCAR and full 
00291 // width at half maximum for GAUSSIAN) in pixels of the smoothing kernels for
00292 // each axis.  For HANNING smoothing, you always get the quarter-half-quarter
00293 // kernel (no matter what you might ask for).  A return value of <src>False</src>
00294 // indicates that you have given an inconsistent or invalid set of smoothing 
00295 // parameters.  If you don't call this function the default state of the
00296 // class is to do no smoothing.  The kernel types are specified with
00297 // the VectorKernel::KernelTypes enum
00298    Bool setSmoothMethod(const Vector<Int>& smoothAxes,
00299                         const Vector<Int>& kernelTypes,
00300                         const Vector<Quantum<Double> >& kernelWidths);
00301    Bool setSmoothMethod(const Vector<Int>& smoothAxes,
00302                         const Vector<Int>& kernelTypes,
00303                         const Vector<Double>& kernelWidths);
00304 
00305 // This is the function that does all the computational work.  It should be called
00306 // after the <src>set</src> functions.  A return value of  <src>False</src>
00307 // indicates that additional checking of the combined methods that you
00308 // have requested has shown that you have not given consistent state to the class.
00309 // If the axis being collapsed comes from a coordinate with one axis only,
00310 // the axis and its coordinate are physically removed from the output image.  Otherwise,
00311 // if <src>removeAxes=True</src> then the output axis is logically removed from the
00312 // the output CoordinateSystem.  If <src>removeAxes=False</src> then the axis
00313 // is retained with shape=1 and with its original coordinate information (which
00314 // is probably meaningless).
00315 //
00316 // The output PtrBlock will hold PagedImages or TempImages (doTemp=True).
00317 // It is your responsibility to delete the pointers.  
00318 // If doTemp is True, the outFileName is irrelevant.
00319 //
00320 // If you create PagedImages, outFileName is the root name for 
00321 // the output files.  Suffixes will be made up internally to append 
00322 // to this root.  If you only ask for one moment,
00323 // this will be the actual name of the output file.  If you don't set this
00324 // variable, the default state of the class is to set the output name root to 
00325 // the name of the input file.  
00326    void createMoments(PtrBlock<MaskedLattice<T>* >& images,
00327                       Bool doTemp, const String& outFileName, 
00328                       Bool removeAxes=True);
00329 
00330 // Set a new image.  A return value of <src>False</src> indicates the 
00331 // image had an invalid type (this class only accepts Float or Double images).
00332    Bool setNewImage (ImageInterface<T>& image);
00333 
00334 // Get CoordinateSystem
00335    CoordinateSystem coordinates() {return _image->coordinates();};
00336 
00337 
00338 // Get shape 
00339    IPosition getShape() { return _image->shape() ; } ;
00340 
00341    //Set an ImageMomentsProgressMonitor interested in getting updates on the
00342    //progress of the collapse process.
00343    void setProgressMonitor( ImageMomentsProgressMonitor* progressMonitor );
00344 
00345 private:
00346 
00347    std::auto_ptr<ImageInterface<T> > _image;
00348 
00349 // Smooth an image   
00350    Bool smoothImage (PtrHolder<ImageInterface<T> >& pSmoothedImage,
00351                      String& smoothName);
00352 
00353 // Determine the noise by fitting a Gaussian to a histogram 
00354 // of the entire image above the 25% levels.  If a plotting
00355 // device is set, the user can interact with this process.
00356    Bool whatIsTheNoise (T& noise,
00357                         ImageInterface<T>& image);
00358 
00359    ImageMomentsProgressMonitor* progressMonitor;
00360 
00361 protected:
00362   using MomentsBase<T>::os_p;
00363   using MomentsBase<T>::showProgress_p;
00364   using MomentsBase<T>::momentAxisDefault_p;
00365   using MomentsBase<T>::peakSNR_p;
00366   using MomentsBase<T>::stdDeviation_p;
00367   using MomentsBase<T>::yMin_p;
00368   using MomentsBase<T>::yMax_p;
00369   using MomentsBase<T>::out_p;
00370   using MomentsBase<T>::smoothOut_p;
00371   using MomentsBase<T>::goodParameterStatus_p;
00372   using MomentsBase<T>::doWindow_p; 
00373   using MomentsBase<T>::doFit_p;
00374   using MomentsBase<T>::doAuto_p;
00375   using MomentsBase<T>::doSmooth_p;
00376   using MomentsBase<T>::noInclude_p;
00377   using MomentsBase<T>::noExclude_p;
00378   using MomentsBase<T>::fixedYLimits_p;
00379   using MomentsBase<T>::momentAxis_p;
00380   using MomentsBase<T>::worldMomentAxis_p;
00381   using MomentsBase<T>::kernelTypes_p;
00382   using MomentsBase<T>::kernelWidths_p;   
00383   using MomentsBase<T>::nxy_p;
00384   using MomentsBase<T>::moments_p;
00385   using MomentsBase<T>::selectRange_p;
00386   using MomentsBase<T>::smoothAxes_p;
00387   using MomentsBase<T>::plotter_p;
00388   using MomentsBase<T>::overWriteOutput_p;
00389   using MomentsBase<T>::error_p;
00390   using MomentsBase<T>::convertToVelocity_p;
00391   using MomentsBase<T>::velocityType_p;
00392   using MomentsBase<T>::checkMethod;
00393 };
00394 
00395 
00396 } //# NAMESPACE CASA - END
00397 
00398 #ifndef CASACORE_NO_AUTO_TEMPLATES
00399 #include <imageanalysis/ImageAnalysis/ImageMoments.tcc>
00400 #endif //# CASACORE_NO_AUTO_TEMPLATES
00401 #endif