11 Polynomial interpolation in a table.
12 This is a python version of CaloClusterCorrection/interpolate.
48 def interpolate (points, x, degree, ycol=1, regions=[], xcol=0):
49 """Polynomial interpolation in a table.
51 points Interpolation table.
52 The x values are in the first column (column 0),
53 and by default, the y values are in the second column (column 1).
54 The x values must be in ascending order, with no duplicates.
55 x The value to interpolate.
56 degree The degree of the interpolating polynomial.
57 ycol The column number of the y values. (0-based.)
58 regions Sometimes, you want to divide the range being interpolated
59 into several distinct regions, where the interpolated
60 function may be discontinuous at the boundaries
61 between regions. To do this, supply this argument,
62 which should contain a list (in ascending order)
63 of the x-coordinates of the region boundaries.
64 When the interpolation runs against a boundary,
65 the algorithm will add a copy of the last point
66 before the boundary, positioned at the boundary.
67 This helps to control runaway extrapolation
68 leading up to the boundary.
69 Returns the interpolated value.
71 The method used is Newtonian interpolation.
72 Based on the cernlib routine divdif.
74 if len (points) < 2
or degree < 1:
75 raise Exception (
'bad args!')
76 degree = min (degree, len (points) - 1)
81 ix = _bisect2 (points, x, xcol)
83 ir = _bisect (regions, x)
93 npts = degree + 2 - (degree%2)
113 while ilo < len (points)
and ir>0
and points[ilo][xcol] < regions[ir-1]:
122 if ihi > len (points):
126 while ihi > 0
and ir<len(regions)
and points[ihi-1][xcol] >= regions[ir]:
137 while ilo < len (points)
and ir>0
and points[ilo][xcol] < regions[ir-1]:
146 if extralo
and points[ilo][xcol] != regions[ir-1]:
151 t.append (regions[ir-1])
152 d.append (points[ilo][ycol])
154 if extrahi
and points[ihi-1][xcol] != regions[ir]:
159 t.append (regions[ir])
160 d.append (points[ihi-1][ycol])
162 t += [points[i][xcol]
for i
in range (ilo, ihi)]
163 d += [points[i][ycol]
for i
in range (ilo, ihi)]
165 degree = min (degree, npts-1)
166 extra = npts != degree+1
169 (t[0], t[npts-2]) = (t[npts-2], t[0])
170 (d[0], d[npts-2]) = (d[npts-2], d[0])
174 for l
in range(0, degree):
176 d[degree+1] = (d[degree+1]-d[degree-1]) / (t[degree+1]-t[degree-1-l])
177 for i
in range (degree, l, -1):
178 d[i] = (d[i]-d[i-1]) / (t[i]-t[i-1-l])
184 sum=0.5*(sum+d[degree+1])
185 for j
in range (degree-1, -1, -1):
186 sum = d[j] + (x - t[j]) * sum
192 __test__[
'tests'] =
"""
193 >>> def is_different (a, b):
194 ... den = abs(a) + abs(b)
195 ... if den == 0: return 0
196 ... return abs((a-b)/den) > 1e-6
197 >>> def testit (y2, table, x, degree, regions=[], ycol=1):
198 ... y1 = interpolate (table, x, degree, ycol, regions)
199 ... if is_different(y1, y2):
200 ... return "diff %f %f %f" % (x, y1, y2)
202 ... [0.05, 6.264762e-01],
203 ... [0.15, 6.671484e-01],
204 ... [0.25, 7.134157e-01],
205 ... [0.35, 8.211740e-01],
206 ... [0.45, 9.047978e-01],
207 ... [0.55, 9.087084e-01],
208 ... [0.65, 8.923957e-01],
209 ... [0.75, 9.584507e-01],
210 ... [0.85, -5.659607e-01],
211 ... [0.95, -6.995252e-01],
212 ... [1.05, -8.711259e-01],
213 ... [1.15, -1.038724e+00],
214 ... [1.25, -1.294152e+00],
215 ... [1.35, -1.170352e+00],
216 ... [1.45, -9.312256e-01],
218 >>> testit ( 0.912999, table, 0.5, 3);
219 >>> testit ( 0.590771, table, 0.0, 3);
220 >>> testit (-0.871126, table, 1.05, 3);
221 >>> testit (-1.0011166, table, 1.13, 3);
222 >>> testit (-1.04871, table, 1.4 , 3);
223 >>> testit (-9.34768, table, 2.0 , 3);
225 >>> testit ( 0.91485268, table, 0.5, 4);
226 >>> testit ( 0.55207348, table, 0.0, 4);
227 >>> testit (-0.87112588, table, 1.05, 4);
228 >>> testit (-0.99805647, table, 1.13, 4);
229 >>> testit (-1.0201578, table, 1.4 , 4);
230 >>> testit (-78.760239, table, 2.0 , 4);
232 >>> regions = [0.8, 1.05]
233 >>> testit ( 0.65513462, table, 0.1, 4, regions);
234 >>> testit ( 0.92242599, table, 0.7, 4, regions);
235 >>> testit (-0.88620204, table, 1.1, 4, regions);
236 >>> testit (-0.73959452, table, 1.0, 4, regions);
237 >>> testit (-0.69952518, table, 1.05, 4, regions);
238 >>> testit ( 0.95845068, table, 0.8, 4, regions);
239 >>> testit (-1.2802936, table, 1.3, 4, regions);
241 >>> testit ( 0.64960641, table, 0.1, 3, regions);
242 >>> testit ( 0.92791027, table, 0.7, 3, regions);
243 >>> testit (-0.91475517, table, 1.1, 3, regions);
244 >>> testit (-0.73959452, table, 1.0, 3, regions);
245 >>> testit (-0.69952518, table, 1.05, 3, regions);
246 >>> testit ( 0.95845068, table, 0.8, 3, regions);
247 >>> testit (-1.2631618, table, 1.3, 3, regions);
249 >>> testit (0.1, table, 0.1, 3, regions, 0);
251 >>> regions2 = [0.2, 1.2]
252 >>> testit ( 0.65359104, table, 0.1, 4, regions2);
253 >>> testit (-1.2503984, table, 1.3, 4, regions2);
257 if __name__ ==
"__main__":
258 print (
'PyAnalysisUtils/interpolate.py test')