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