casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
LatticeConvolver.h
Go to the documentation of this file.
00001 //# Convolver.h: this defines Convolver a class for doing convolution
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 //#
00027 //# $Id: LatticeConvolver.h 20229 2008-01-29 15:19:06Z gervandiepen $
00028 
00029 #ifndef LATTICES_LATTICECONVOLVER_H
00030 #define LATTICES_LATTICECONVOLVER_H
00031 
00032 //# Includes
00033 #include <casa/aips.h>
00034 #include <scimath/Mathematics/NumericTraits.h>
00035 #include <lattices/Lattices/TempLattice.h>
00036 #include <casa/Arrays/IPosition.h>
00037 
00038 namespace casa { //# NAMESPACE CASA - BEGIN
00039 
00040 //# Forward Declarations
00041 //template <class T> class LatticeConvolver;
00042 class IPosition;
00043 
00044 // <summary>Lists the different types of Convolutions that can be done</summary>
00045 // <synopsis>This enumerator is brought out as a separate class because g++
00046 // currently cannot handle enumerators in a templated class. When it can this
00047 // class will go away and this enumerator moved into the Convolver
00048 // class</synopsis>
00049 class ConvEnums {
00050 public:
00051   enum ConvType {
00052     // Linear convolution
00053     LINEAR,
00054     // Circular Convolution
00055     CIRCULAR
00056     //# Assume the point spread function is symmetric
00057     //#REALSYMMETRIC
00058   };
00059 };
00060 
00061 // <summary>A class for doing multi-dimensional convolution</summary>
00062 
00063 // <use visibility=export>
00064 
00065 // <reviewed reviewer="" date="yyyy/mm/dd" tests="tLatticeConvolver">
00066 // </reviewed>
00067 
00068 // <prerequisite>
00069 //  <li> The mathematical concept of convolution
00070 // </prerequisite>
00071 //
00072 // <etymology>
00073 // The LatticeConvolver class will convolve Lattices. This class
00074 // complements the Convolver class which will convolve Arrays.  
00075 // </etymology>
00076 //
00077 // <synopsis>
00078 // This class performs linear or circular convolution on Lattices. See the
00079 // <linkto class="Convolver">Convolver</linkto> class description of the
00080 // difference between linear and circular convolution. 
00081 
00082 // This class does convolutions by multiplying the Fourier transforms of the
00083 // supplied Lattices and returning the inverse transform of the product. This
00084 // is the best algorithm to use when the point spread function is large. This
00085 // class does all the padding with zeros necessary to implement this
00086 // algorithm. Hence the 
00087 
00088 // </synopsis>
00089 //
00090 // <example>
00091 // <srcblock>
00092 // 
00093 // </srcblock> 
00094 // </example>
00095 //
00096 // <motivation>
00097 // </motivation>
00098 //
00099 // <thrown>
00100 // <li> AipsError: if psf and model have a differing numbers of dimensions
00101 // </thrown>
00102 //
00103 // <todo asof="yyyy/mm/dd">
00104 //   <li> the class should detect if the psf or image is small and do the
00105 //        convolution directly rather than use the Fourier domain
00106 //   <li> Allow the psf to be specified with a
00107 //       <linkto class=Function>Function</linkto>. 
00108 // </todo>
00109 
00110 template<class T> class LatticeConvolver
00111 {
00112 public:
00113   // The default constructor creates a LatticeConvolver that will convolve your
00114   // data with a point spread function (psf) that zero everywhere except at the
00115   // centre where it is one. Convolving with this psf will not change your
00116   // data.
00117   LatticeConvolver();
00118 
00119   // Create a convolver that is initialised to do circular convolution with the
00120   // specified point spread function. It is assumed that the supplied model
00121   // will be the same shape as the point spread function.
00122   LatticeConvolver(const Lattice<T> & psf, Bool doFast=False);
00123 
00124   // Create a convolver that is initialised to do linear convolution with the
00125   // specified point spread function. The size of the model you will convolve
00126   // with must be specified.
00127   LatticeConvolver(const Lattice<T> & psf, const IPosition & modelShape, 
00128                    Bool doFast=False);
00129 
00130   // Create a convolver that is initialised to do the specified type of
00131   // convolution with the specified point spread function. The size of the
00132   // model you expect to convolve with must be specified.
00133   LatticeConvolver(const Lattice<T> & psf, const IPosition & modelShape,
00134                    ConvEnums::ConvType type, Bool doFast=False);
00135 
00136   // The copy constructor uses reference semantics
00137   LatticeConvolver(const LatticeConvolver<T> & other);
00138 
00139   // The assignment operator also uses reference semantics
00140   LatticeConvolver<T> & operator=(const LatticeConvolver<T> & other); 
00141 
00142   // The destructor does nothing special.
00143   ~LatticeConvolver();
00144 
00145   // Perform linear convolution of the model with the previously specified
00146   // psf. The supplied Lattices must be the same shape.
00147   void linear(Lattice<T> & result, const Lattice<T> & model);
00148 
00149   // Perform in-place linear convolution of the model with the previously
00150   // specified psf. Return the result in the same Lattice as the
00151   // model. 
00152   void linear(Lattice<T> & modelAndResult);
00153 
00154   // Perform circular convolution of the model with the previously
00155   // specified psf. Return the answer in result.
00156   void circular(Lattice<T> & result, const Lattice<T> & model);
00157 
00158   // Perform in-place linear convolution of the model with the previously
00159   // specified psf. Return the result in the same Lattice as the model.
00160   void circular(Lattice<T> & modelAndResult);
00161 
00162   // Perform convolution on the specified model using the currently initialised
00163   // convolution type (linear or circular). These functions will not resize the
00164   // LatticeConvolver if the supplied Lattice is the wrong shape.
00165   //
00166   // If the LatticeConvolver is setup for circular Convolution then the size of
00167   // the supplied model must be less than or equal to the shape returned by the
00168   // fftshape() function, which is usually the same as the shape of the psf.
00169   //
00170   // If the LatticeConvolver is setup to do linear convolution the the
00171   // input and output Lattices must have the same shape as the result from the
00172   // shape() member function. The convolution may be either in-place or not.
00173   // <group>
00174   void convolve(Lattice<T> & modelAndResult) const;
00175   void convolve(Lattice<T> & result, const Lattice<T> & model) const;
00176   // </group>
00177 
00178   // Return the psf currently used by this convolver. The supplied Lattice must
00179   // be the correct shape ie., the same as returned by the psfShape member
00180   // function.
00181   void getPsf(Lattice<T> & psf) const;
00182 
00183   // Resize the LatticeConvolver to do convolutions of the specified type and
00184   // shape. The supplied function must always have the same number of
00185   // dimensions as the internal point spread function (which can be found using
00186   // the shape member function). The LatticeConvolver will be set up to do
00187   // circular or linear convolutions depending on the supplied type
00188   void resize(const IPosition & modelShape, ConvEnums::ConvType type);
00189 
00190   // Returns the shape of the Lattices that the convolver will convolve. This
00191   // shape will always have as many dimensions as the psf that was used to
00192   // initialise the LatticeConvolver. If the LatticeConvolver is setup to do
00193   // circular convolutions then every axis of the returned IPosition will be
00194   // zero length. If the LatticeConvolver is setup to do linear convolutions
00195   // then the returned IPosition will have a positive values on each axis that
00196   // indicate the expected shape of the input model.
00197   IPosition shape() const;
00198 
00199   // Returns the shape of the point spread function that the LatticeConvolver
00200   // was initialised with.
00201   IPosition psfShape() const;
00202 
00203   // Returns the type of convolution the LatticeConvolver is currently set up
00204   // to do.
00205   ConvEnums::ConvType type() const;
00206 
00207   // Returns the shape of the FFT's that the LatticeConvolver will do when
00208   // performing the convolution. Not really useful except as a diagnostic
00209   // tool. If the shape contains a lot of poorly factorisable lengths then the
00210   // convolution will be slow.
00211   IPosition fftShape() const;
00212 
00213   // Set usage of fast convolve with lesser flips
00214   void setFastConvolve();
00215 
00216 private:
00217   //# The following functions are used in various places in the code and are
00218   //# documented in the .cc file. Static functions are used when the functions
00219   //# do not use the object state. They ensure that implicit assumptions
00220   //# about the current state and implicit side-effects are not possible
00221   //# because all information must be suplied in the input arguments
00222   static void pad(Lattice<T> & paddedLat, const Lattice<T> & inLat);
00223   static void unpad(Lattice<T> & result, const Lattice<T> & paddedResult);
00224   void makeXfr(const Lattice<T> & psf);
00225   void makePsf(Lattice<T> & psf) const;
00226   static IPosition calcFFTShape(const IPosition & psfShape, 
00227                                 const IPosition & modelShape,
00228                                 ConvEnums::ConvType type);
00229 
00230   IPosition itsPsfShape;
00231   IPosition itsModelShape;
00232   ConvEnums::ConvType itsType;
00233   IPosition itsFFTShape;
00234   TempLattice<typename NumericTraits<T>::ConjugateType>* itsXfr;
00235   TempLattice<T>* itsPsf;
00236   Bool itsCachedPsf;
00237   Bool doFast_p;
00238 };
00239 
00240 } //# NAMESPACE CASA - END
00241 
00242 #ifndef CASACORE_NO_AUTO_TEMPLATES
00243 #include <lattices/Lattices/LatticeConvolver.tcc>
00244 #endif //# CASACORE_NO_AUTO_TEMPLATES
00245 #endif
00246