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