from __future__ import division import numpy as np from scipy.interpolate import Akima1DInterpolator def cubic_spline_3pts(x, y, T): """ Apparently scipy.interpolate.interp1d does not support cubic spline for less than 4 points. """ x0, x1, x2 = x y0, y1, y2 = y x1x0, x2x1 = x1 - x0, x2 - x1 y1y0, y2y1 = y1 - y0, y2 - y1 _x1x0, _x2x1 = 1.0 / x1x0, 1.0 / x2x1 m11, m12, m13 = 2 * _x1x0, _x1x0, 0 m21, m22, m23 = _x1x0, 2.0 * (_x1x0 + _x2x1), _x2x1 m31, m32, m33 = 0, _x2x1, 2.0 * _x2x1 v1 = 3 * y1y0 * _x1x0 * _x1x0 v3 = 3 * y2y1 * _x2x1 * _x2x1 v2 = v1 + v3 M = np.array([[m11, m12, m13], [m21, m22, m23], [m31, m32, m33]]) v = np.array([v1, v2, v3]).T k = np.array(np.linalg.inv(M).dot(v)) a1 = k[0] * x1x0 - y1y0 b1 = -k[1] * x1x0 + y1y0 a2 = k[1] * x2x1 - y2y1 b2 = -k[2] * x2x1 + y2y1 t = T[np.r_[T >= x0] & np.r_[T <= x2]] t1 = (T[np.r_[T >= x0] & np.r_[T < x1]] - x0) / x1x0 t2 = (T[np.r_[T >= x1] & np.r_[T <= x2]] - x1) / x2x1 t11, t22 = 1.0 - t1, 1.0 - t2 q1 = t11 * y0 + t1 * y1 + t1 * t11 * (a1 * t11 + b1 * t1) q2 = t22 * y1 + t2 * y2 + t2 * t22 * (a2 * t22 + b2 * t2) q = np.append(q1, q2) return t, q def akima(X, Y, x): spl = Akima1DInterpolator(X, Y) return spl(x)