ImageFit1D.h

Go to the documentation of this file.
00001 
00002 //# ImageFit1D.h: Class to fit profiles to vectors from images
00003 //# Copyright (C) 2004
00004 //# Associated Universities, Inc. Washington DC, USA.
00005 //#
00006 //# This library is free software; you can redistribute it and/or modify it
00007 //# under the terms of the GNU Library General Public License as published by
00008 //# the Free Software Foundation; either version 2 of the License, or (at your
00009 //# option) any later version.
00010 //#
00011 //# This library is distributed in the hope that it will be useful, but WITHOUT
00012 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00014 //# License for more details.
00015 //#
00016 //# You should have received a copy of the GNU Library General Public License
00017 //# along with this library; if not, write to the Free Software Foundation,
00018 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00019 //#
00020 //# Correspondence concerning AIPS++ should be addressed as follows:
00021 //#        Internet email: aips2-request@nrao.edu.
00022 //#        Postal address: AIPS++ Project Office
00023 //#                        National Radio Astronomy Observatory
00024 //#                        520 Edgemont Road
00025 //#                        Charlottesville, VA 22903-2475 USA
00026 //#
00027 //#   $Id: ImageFit1D.h 20229 2008-01-29 15:19:06Z gervandiepen $
00028 
00029 #ifndef IMAGES_IMAGEFIT1D_H
00030 #define IMAGES_IMAGEFIT1D_H
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <casa/Arrays/Vector.h>
00035 #include <scimath/Mathematics/NumericTraits.h>
00036 #include <measures/Measures/MDirection.h>
00037 #include <measures/Measures/MFrequency.h>
00038 #include <measures/Measures/MDoppler.h>
00039 #include <coordinates/Coordinates/CoordinateSystem.h>
00040 #include <components/SpectralComponents/ProfileFit1D.h>
00041 
00042 #include <memory>
00043 
00044 namespace casa {
00045 
00046 class SpectralElement;
00047 class SpectralList;
00048 class ImageRegion;
00049 template<class T> class ImageInterface;
00050 
00051 
00052 // <summary>
00053 // Fit spectral components to a Vector of data from an image
00054 // </summary>
00055 
00056 // <use visibility=export>
00057 
00058 // <reviewed reviewer="" date="" tests="tImageFit1D.cc">
00059 // </reviewed>
00060 
00061 // <prerequisite>
00062 //   <li> <linkto class="SpectralElement">SpectralElement</linkto> 
00063 //   <li> <linkto class="SpectralList">SpectralList</linkto> 
00064 //   <li> <linkto class="SpectralFit">SpectralFit</linkto> 
00065 //   <li> <linkto class="ProfileFit1D">ProfileFit1D</linkto> 
00066 // </prerequisite>
00067 
00068 // <synopsis> 
00069 // Fit lists (held in class SpectralList) of SpectralElements to a Vector of data 
00070 // from the image.  Each SpectralElement can  be one from a variety of types.
00071 // The values of the parameters for each SpectralElement provide the initial 
00072 // starting guesses for the fitting process.  
00073 //
00074 // You specify the domain in which the fit is to be done via the 
00075 // enum AbcissaType.  The CoordinateSystem in the image is used
00076 // to convert the pixel coordinates to the desired abcissa.  
00077 // You can change the units of the CoordinateSystem if you want
00078 // to fit in different units.  If you set an estimate yourself
00079 // (function setElements or addElement) it is the callers responsibility
00080 // that the elements are in the correct abcissa domain.  Function
00081 // setGaussianElements will automatically make an estimate in the 
00082 // correct domain.
00083 //
00084 // Also, a SpectralElement object holds a mask indicating whether 
00085 // a parameter should be held fixed or solved for.   After the 
00086 // fitting is done, a new SpectralList holding SpectralElements with 
00087 // the fitted parameters is created.  
00088 //
00089 // For all the functions that return a status Bool, True is good. If
00090 // False is returned, an error message can be recovered with function
00091 // <src>errorMessage</src>,  You should not proceed if False is returned.
00092 // 
00093 // Exceptions will be thrown if you do not set the Image and axis 
00094 // via the constructor or <src>setImage</src> function.
00095 // </synopsis> 
00096 
00097 // <example>
00098 // <srcblock>
00099 // PagedImage<Float> im("myimage");
00100 // Int axis = 2;
00101 // ImageFit1D<Float> fitter(image, axis);
00102 // IPosition pos(in.ndim(),0);
00103 // fitter.setData(pos, ImageFit1D<Float>::IM_NATIVE);     // Fit in native coordinate space
00104 // fitter.setGaussianElements(3);                      // FIt 3 Gaussians
00105 // if (fitter.fit()) {
00106 //    cerr << fitter.getList() << endl;                // Print result
00107 // }
00108 // 
00109 // </srcblock>
00110 // </example>
00111 
00112 // <todo asof="2004/07/10">
00113 //   <li> Add constraints
00114 // </todo>
00115 
00116 
00117 template <class T> class ImageFit1D {
00118 public:
00119 
00120 using FitterType = typename NumericTraits<T>::PrecisionType;
00121 
00122     enum AbcissaType {
00123        PIXEL = 0,
00124        IM_NATIVE = 1,
00125        VELOCITY = 2,
00126        N_TYPES};
00127 
00128 
00129     // Constructor.  Fitting weights are assumed all unity.
00130     ImageFit1D(SHARED_PTR<const ImageInterface<T> > image, uInt axis=0);
00131 
00132     // Constructor with fitting weights image.  The data and weights images must
00133     // be the same shape.
00134     ImageFit1D(
00135         SHARED_PTR<const ImageInterface<T> > image,
00136         SHARED_PTR<const ImageInterface<T> > weights, uInt axis=0
00137     );
00138 
00139     // Destructor
00140     ~ImageFit1D();
00141 
00142     // Copy constructor.  Uses reference semantics.
00143     ImageFit1D(const ImageFit1D& other);
00144 
00145     // Assignment operator. Uses reference semantics.
00146     ImageFit1D& operator=(const ImageFit1D& other);
00147 
00148 
00149     // Set the data to be fit.  All non-profile axes data are averaged.
00150     // For the profile axis, the full spectrum is taken.  The abscissa
00151     // world values are computed when you call these functions unless they
00152     // have been set previously by a call to setAbscissa() in which case
00153     // the values that were passed to that method are used. Use the first
00154     // form of setData() in this case. The domain of the
00155     // abscissa values is controlled by <src>AbcissaType</src> and
00156     // <src>doAbs</src> (absolute coordinates).  The CoordinateSystem in
00157     // the image is used to convert from pixels to world values.
00158     // If <src>type</src>=IN_NATIVE and <src>abscissaDivisor</src> is not null,
00159     // the world abscissa values will be divided by the value pointed to by
00160     // <src>abscissaDivisor</src>. This mitigates having very large or very small
00161     // abscissa values when fitting. If xfunc and/or yfunc is not NULL, the x and/or
00162     // y values are fed to the specified function and the resultant values are what
00163     // are used for the x and/or y values in the fit. If xfunc is not NULL and
00164     // setAbscissa values has been called prior, no abscissa value transformation occurs.
00165     // Thus if you want to apply a function to the abscissa values, the caller should
00166     // pass the result of that function into setAbscissaValues.
00167     // <group>
00168     void setData (
00169         const IPosition& pos, /*const ImageFit1D<T>::AbcissaType type,
00170         const Bool doAbs=True, const Double* const &abscissaDivisor=0,
00171         Array<Double> (*xfunc)(const Array<Double>&)=0, */
00172         Array<FitterType> (*yfunc)(const Array<FitterType>&)=0
00173     );
00174 
00175     void setData (
00176         const IPosition& pos, const ImageFit1D<T>::AbcissaType type,
00177         const Bool doAbs=True, const Double* const &abscissaDivisor=0,
00178         Array<Double> (*xfunc)(const Array<Double>&)=0,
00179         Array<FitterType> (*yfunc)(const Array<FitterType>&)=0
00180     );
00181 
00182     /*
00183     Bool setData (
00184         const ImageRegion& region, const ImageFit1D<T>::AbcissaType type,
00185         Bool doAbs=True
00186     );
00187     */
00188     // </group>
00189 
00190     // Set a SpectralList of SpectralElements to fit for.    These elements
00191     // must be in the correct abcissa domain set in function <src>setData</src>.
00192     // You must have already called <src>setData</src> to call this function.
00193     // The SpectralElements in the list hold the
00194     // initial estimates.  They also contain the information about whether
00195     // specific parameters are to be held fixed or allowed to vary in
00196     // the fitting process.
00197     // You can recover the list of elements with function getList.
00198     void setElements (const SpectralList& list) {_fitter.setElements(list);};
00199 
00200     // Add new SpectralElement(s) to the SpectralList (can be empty)
00201     // of SpectralElements to be fit for.  
00202     // You must have already called <src>setData</src> to call this function.
00203     //<group>
00204     void addElement (const SpectralElement& el) {_fitter.addElement(el);};
00205     void addElements (const SpectralList& list) {_fitter.addElements(list);};
00206     // </group>
00207 
00208     // Set a SpectralList of Gaussian SpectralElements to fit for.  
00209     // The initial estimates for the Gaussians will be automatically determined
00210     // in the correct abcissa domain.
00211     // All of the parameters created by this function will be solved for
00212     // by default. You can recover the list of elements with function getList.
00213     // Status is returned, if False, error message can be recovered with <src>errorMessage</src>
00214     void setGaussianElements (uInt nGauss);
00215 
00216     // Clear the SpectralList of elements to be fit for
00217     void clearList () {_fitter.clearList();};
00218 
00219     // Do the fit and return convergence status.  Errors in the fitting
00220     // process will generate an AipsError exception and you should catch
00221     // these yourself.
00222     Bool fit ();
00223 
00224     // Get Chi Squared of fit
00225     Double getChiSquared () const {return _fitter.getChiSquared();}
00226 
00227     // Get number of iterations for last fit
00228     Double getNumberIterations () const {return _fitter.getNumberIterations();}
00229 
00230     // Recover the list of elements.  You can get the elements
00231     // as initially estimated (fit=False), or after fitting 
00232     // (fit=True).  In the latter case, the SpectralElements
00233     // hold the parameters and errors of the fit.
00234     const SpectralList& getList (Bool fit=True) const {return _fitter.getList(fit);};
00235 
00236     // Recover vectors for the estimate, fit and residual.
00237     // If you don't specify which element, all elements are included
00238     // If the Vectors are returned with zero length, it means an error
00239     // condition exists (e.g. asking for fit before you do one). In this
00240     // case an error message can be recovered with function <src>errorMessage</src>.
00241     //<group>
00242     Vector<T> getEstimate (Int which=-1) const;
00243     Vector<T> getFit (Int which=-1) const;
00244     Vector<T> getResidual (Int which=-1, Bool fit=True)  const;
00245     //</group>
00246 
00247     Bool setXMask(const std::set<uInt>& indices, Bool specifiedPixelsAreGood) {
00248         return _fitter.setXMask(indices, specifiedPixelsAreGood);
00249     }
00250 
00251     // get data mask
00252     Vector<Bool> getDataMask () const {return _fitter.getDataMask();};
00253 
00254     // Get Total Mask (data and range mask)
00255     Vector<Bool> getTotalMask () const {return _fitter.getTotalMask();};
00256 
00257     // did the fit succeed? should only be called after fit().
00258     Bool succeeded() const;
00259 
00260     // did the fit converge? should only be called after fit().
00261     Bool converged() const;
00262 
00263     // Helper function.  Sets up the CoordinateSystem to reflect the choice of
00264     // abcissa unit and the doppler (if the axis is spectral).
00265     static Bool setAbcissaState (String& errMsg, ImageFit1D<T>::AbcissaType& type,
00266                                  CoordinateSystem& cSys, const String& xUnit,
00267                                  const String& doppler, uInt pixelAxis);
00268 
00269 
00270     // flag the solution as invalid based on external criteria.
00271     void invalidate();
00272 
00273     // is the solution valid? If False, some external logic has
00274     // called invalidate()
00275     Bool isValid() const;
00276 
00277     // Set the abscissa values prior to running setData. If this is done, then
00278     // the abscissa values will not be recomputed when setData is called.
00279     // This can imporove performance if, for example, you are looping over several fitters for
00280     // which you know the abscissa values do not change.
00281     void setAbscissa(const Vector<Double>& x) { _x.assign(x); }
00282 
00283     // make the abscissa values, <src>x</src>. If <src>type</src>=IN_NATIVE
00284     // and <src>abscissaDivisor is not null, then divide the native values
00285     // by the value pointed to by <src>abscissaDivisor</src> in making the abscissa
00286     // values.
00287     Vector<Double> makeAbscissa (
00288                    ImageFit1D<T>::AbcissaType type,
00289                    Bool doAbs, const Double* const &abscissaDivisor
00290    );
00291 private:
00292    SHARED_PTR<const ImageInterface<T> > _image, _weights;
00293    uInt _axis;
00294 
00295 // In the future I will be able to template the fitter on T. For now
00296 // it must be Double.
00297 
00298    ProfileFit1D<FitterType> _fitter;
00299    Bool _converged, _success, _isValid;
00300    Vector<Double> _x, _unityWeights, _weightSlice;
00301    IPosition _sliceShape;
00302    
00303    // Disallow default constructor
00304    ImageFit1D() {}
00305 
00306    void check() const;
00307    void checkType() const;
00308    void _construct();
00309    void copy (const ImageFit1D<T>& other);
00310 
00311    //void setWeightsImage (const ImageInterface<T>& im);
00312 
00313    // reset the fitter, for example if we've done a fit and want to move
00314    // to the next position in the image
00315    void _resetFitter();
00316 
00317 
00318    // Set Image(s) and axis
00319    // <group>
00320    // void setImage (const ImageInterface<T>& im, const ImageInterface<T>& weights, uInt pixelAxis);
00321    // void setImage (const ImageInterface<T>& im, uInt pixelAxis);
00322    // </group>
00323 
00324 };
00325 
00326 } //#End casa namespace
00327 
00328 #ifndef CASACORE_NO_AUTO_TEMPLATES
00329 #include <imageanalysis/ImageAnalysis/ImageFit1D.tcc>
00330 #endif //# CASACORE_NO_AUTO_TEMPLATES
00331 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 31 Aug 2016 for casa by  doxygen 1.6.1