casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Interpolate1D.h
Go to the documentation of this file.
00001 //# Interpolate1D.h: Interpolate in one dimension
00002 //# Copyright (C) 1996,1997,1999,2002,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 //# $Id: Interpolate1D.h 21024 2011-03-01 11:46:18Z gervandiepen $
00026 
00027 #ifndef SCIMATH_INTERPOLATE1D_H
00028 #define SCIMATH_INTERPOLATE1D_H
00029 
00030 #include <casa/aips.h>
00031 #include <scimath/Functionals/Function1D.h>
00032 #include <casa/Containers/Block.h>
00033 
00034 namespace casa { //# NAMESPACE CASA - BEGIN
00035 
00036 template<class Range> class SampledFunctional;
00037 
00038 // <summary> Interpolate in one dimension </summary>
00039 
00040 // <use visibility=export>
00041 
00042 // <reviewed reviewer="wyoung" date="1996/10/18" tests="tInterpolate1D" demos="dInterpolate1D">
00043 // </reviewed>
00044 
00045 // <prerequisite>
00046 //   <li> <linkto class=SampledFunctional>SampledFunctional</linkto> 
00047 //   <li> <linkto class=Function1D>Function1D</linkto> 
00048 // </prerequisite>
00049 
00050 // <etymology>
00051 // The Interpolate1D class does interpolation in one dimension only.
00052 // </etymology>
00053 
00054 // <synopsis>
00055 // This class will, given the abscissa and ordinates of a set of one
00056 // dimensional data, interpolate on this data set giving the value at any
00057 // specified ordinate. It will extrapolate if necessary, but this is will
00058 // usually give a poor result. There is no requirement for the ordinates to
00059 // be regularly spaced, or even sorted in any numerical order. However each
00060 // abscissa should have a unique value. 
00061 //
00062 // Interpolation can be done using the following methods:
00063 // <ul>
00064 //   <li> Nearest Neighbour  (default if there is one data point)
00065 //   <li> Linear (default unless there is only one data point)
00066 //   <li> Cubic Polynomial
00067 //   <li> Natural Cubic Spline
00068 // </ul>
00069 //
00070 // The restriction that each abcissus has a unique value can be lifted
00071 // by setting the <src>uniq=True </src> option in the appropriate
00072 // functions. This imposes the following additional restrictions on
00073 // interpolation. 
00074 // <ul>
00075 // <li> You cannot use cubic spline interpolation. 
00076 // <li> You cannot cannot interpolate within two data points of a repeated
00077 //      x-value when using cubic interpolation. 
00078 // <li> You cannot  interpolate within one data point of a repeated
00079 //      x-value when using linear or nearest neighbour interpolation. 
00080 // </ul>
00081 //
00082 // The abscissa must be a SampledFunctional that returns a scalar value that
00083 // can be ordered. ie. an uInt, Int, Float or Double (not Complex). The
00084 // ordinate can be any data type that has addition, and subtraction defined
00085 // as well as multiplication by a scalar. So the ordinate can be complex
00086 // numbers, where the interpolation is done separately on the real and
00087 // imaginary components, or an array, where the interpolation is done
00088 // separately on an element by element basis.
00089 //
00090 // This class will curently make an internal copy of the data supplied to
00091 // it, and sort the data if it is not told it is already sorted, by using
00092 // the <src> sorted=True </src> flag.
00093 // </synopsis>
00094 
00095 // <example>
00096 // This code fragment sets the interpolation method to cubic before
00097 // interpolating on the supplied (x,y) vectors.
00098 // <srcblock>
00099 //  Vector<Float> x(4); indgen(x); 
00100 //  Vector<Double> y(4); indgen(y); y = y*y*y;
00101 //  ScalarSampledFunctional<Float> fx(x)
00102 //  ScalarSampledFunctional<Double> fy(y);
00103 //  Interpolate1D<Float, Double> gain(fx, fy);
00104 //  gain.setMethod(Interpolate1D<Float,Double>::cubic);
00105 //  for (Float xs = -1; xs < 5; xs += 0.1)
00106 //    cout << "gain(" << xs << "):" << gain(xs) << endl;
00107 // </srcblock>
00108 // </example>
00109 
00110 // <motivation>
00111 // This class is motivated by the need to interpolate over the gain
00112 // solutions obtained from calibrator observations, in order to get the gain
00113 // at arbitrary times. 
00114 // </motivation>
00115 
00116 // <templating arg=Domain>
00117 //  <li> The Domain class must be a type that can be ordered in a mathematical
00118 // sense. This includes uInt, Int, Float, Double, but not Complex. 
00119 // </templating>
00120 
00121 // <templating arg=Range>
00122 // <li> The Range class must have addition and subtraction of Range objects with
00123 // each other as well as multiplication by a scalar defined. Besides the
00124 // scalar types listed above this includes Complex, DComplex, and Arrays of
00125 // any of these types.
00126 // </templating>
00127 
00128 // <thrown>
00129 //    <li> AipsError
00130 // </thrown>
00131 
00132 // <todo asof="1996/10/22">
00133 //   <li> avoid an internal copy of the data and have an index array as the
00134 //        only private data (plus the interpolation method and pointers to
00135 //        the actual data). 
00136 //   <li> Review the use of copy semantics in the copy constructor &
00137 //        assignment operator after making the above change. 
00138 // </todo>
00139 
00140 template <class Domain, class Range> class Interpolate1D :
00141 public Function1D<Domain, Range> {
00142 public:
00143   // The different interpolation methods are enumerated here
00144   enum Method {
00145     // Crude but sometimes useful
00146     nearestNeighbour, 
00147     // The most common method and the Default
00148     linear,           
00149     // Fits a third order polynomial to 4 pts 
00150     cubic,            
00151     // Natural Cubic Splines
00152     spline
00153   };
00154 
00155   // The default constructor generates a useless object until the setData
00156   // function has been called.
00157   Interpolate1D();
00158 
00159   // Construct an object with the specified data
00160   Interpolate1D(const SampledFunctional<Domain> &x, 
00161                 const SampledFunctional<Range> &y, 
00162                 const Bool sorted=False, 
00163                 const Bool uniq=False);
00164 
00165   // Define a new data set for the class to operate on. Equivalent in many
00166   // aspects to creating a new object.
00167   void setData(const SampledFunctional<Domain> &x, 
00168                const SampledFunctional<Range> &y, 
00169                const Bool sorted=False, 
00170                const Bool uniq=False);
00171 
00172   // The standard copy constructor, assignment operator and
00173   // destructor. Internal data is copied in both cases (copy semantics)
00174   // <group>
00175   Interpolate1D(const Interpolate1D<Domain, Range>& other);
00176   Interpolate1D<Domain, Range> & 
00177     operator=(const Interpolate1D<Domain, Range> & other);
00178   ~Interpolate1D();
00179   // </group>
00180 
00181   // Name of function
00182   virtual const String &name() const { static String x("interpolate1d");
00183     return x; }
00184 
00185   // Interpolation is done using the () operator (see example above). Actual
00186   // use is through the virtual <src>eval()</src> function.
00187   virtual Range eval(typename Function1D<Domain, Range>::FunctionArg x)
00188     const;
00189 
00190   // inquire/set the current interpolation method. uInts are used as
00191   // arguments instead of the Interpolate1D::Method enumerator due to
00192   // compiler limitations. See the example above (or the demo code) for the
00193   // recommended way to call these functions.
00194   // <group>
00195   uInt getMethod() const {return curMethod;}
00196   void setMethod(uInt method);
00197   // </group>
00198 
00199   // Access the data set that interpolation is done over. This will usually be
00200   // sorted. 
00201   // <group>
00202   Vector<Domain> getX() const;
00203   Vector<Range> getY() const;
00204   // </group>
00205 
00206   // A function to copy the Interpolate1D object
00207   // <group>
00208   virtual Function<Domain, Range> *clone() const;
00209   // </group>
00210 
00211 private:
00212   // A private function for doing polynomial interpolation
00213   Range polynomialInterpolation(const Domain x, uInt n, uInt offset) const;
00214 
00215   uInt curMethod;        // interpolation method to use
00216   uInt nElements;        // how many elements in the data set
00217   Block<Domain> xValues; // the abscissa of the data set (sorted)
00218   Block<Range> yValues;  // The corresponding ordinate of the data set
00219   Block<Range> y2Values; // The numerical second derivates (only for splines)
00220 
00221 };
00222 
00223 
00224 } //# NAMESPACE CASA - END
00225 
00226 #ifndef CASACORE_NO_AUTO_TEMPLATES
00227 #include <scimath/Functionals/Interpolate1D.tcc>
00228 #endif //# CASACORE_NO_AUTO_TEMPLATES
00229 #endif