_fitpack_impl.py 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314
  1. """
  2. fitpack (dierckx in netlib) --- A Python-C wrapper to FITPACK (by P. Dierckx).
  3. FITPACK is a collection of FORTRAN programs for curve and surface
  4. fitting with splines and tensor product splines.
  5. See
  6. https://web.archive.org/web/20010524124604/http://www.cs.kuleuven.ac.be:80/cwis/research/nalag/research/topics/fitpack.html
  7. or
  8. http://www.netlib.org/dierckx/
  9. Copyright 2002 Pearu Peterson all rights reserved,
  10. Pearu Peterson <pearu@cens.ioc.ee>
  11. Permission to use, modify, and distribute this software is given under the
  12. terms of the SciPy (BSD style) license. See LICENSE.txt that came with
  13. this distribution for specifics.
  14. NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
  15. TODO: Make interfaces to the following fitpack functions:
  16. For univariate splines: cocosp, concon, fourco, insert
  17. For bivariate splines: profil, regrid, parsur, surev
  18. """
  19. __all__ = ['splrep', 'splprep', 'splev', 'splint', 'sproot', 'spalde',
  20. 'bisplrep', 'bisplev', 'insert', 'splder', 'splantider']
  21. import warnings
  22. import numpy as np
  23. from . import _fitpack
  24. from numpy import (atleast_1d, array, ones, zeros, sqrt, ravel, transpose,
  25. empty, iinfo, asarray)
  26. # Try to replace _fitpack interface with
  27. # f2py-generated version
  28. from . import dfitpack
  29. dfitpack_int = dfitpack.types.intvar.dtype
  30. def _int_overflow(x, msg=None):
  31. """Cast the value to an dfitpack_int and raise an OverflowError if the value
  32. cannot fit.
  33. """
  34. if x > iinfo(dfitpack_int).max:
  35. if msg is None:
  36. msg = '%r cannot fit into an %r' % (x, dfitpack_int)
  37. raise OverflowError(msg)
  38. return dfitpack_int.type(x)
  39. _iermess = {
  40. 0: ["The spline has a residual sum of squares fp such that "
  41. "abs(fp-s)/s<=0.001", None],
  42. -1: ["The spline is an interpolating spline (fp=0)", None],
  43. -2: ["The spline is weighted least-squares polynomial of degree k.\n"
  44. "fp gives the upper bound fp0 for the smoothing factor s", None],
  45. 1: ["The required storage space exceeds the available storage space.\n"
  46. "Probable causes: data (x,y) size is too small or smoothing parameter"
  47. "\ns is too small (fp>s).", ValueError],
  48. 2: ["A theoretically impossible result when finding a smoothing spline\n"
  49. "with fp = s. Probable cause: s too small. (abs(fp-s)/s>0.001)",
  50. ValueError],
  51. 3: ["The maximal number of iterations (20) allowed for finding smoothing\n"
  52. "spline with fp=s has been reached. Probable cause: s too small.\n"
  53. "(abs(fp-s)/s>0.001)", ValueError],
  54. 10: ["Error on input data", ValueError],
  55. 'unknown': ["An error occurred", TypeError]
  56. }
  57. _iermess2 = {
  58. 0: ["The spline has a residual sum of squares fp such that "
  59. "abs(fp-s)/s<=0.001", None],
  60. -1: ["The spline is an interpolating spline (fp=0)", None],
  61. -2: ["The spline is weighted least-squares polynomial of degree kx and ky."
  62. "\nfp gives the upper bound fp0 for the smoothing factor s", None],
  63. -3: ["Warning. The coefficients of the spline have been computed as the\n"
  64. "minimal norm least-squares solution of a rank deficient system.",
  65. None],
  66. 1: ["The required storage space exceeds the available storage space.\n"
  67. "Probable causes: nxest or nyest too small or s is too small. (fp>s)",
  68. ValueError],
  69. 2: ["A theoretically impossible result when finding a smoothing spline\n"
  70. "with fp = s. Probable causes: s too small or badly chosen eps.\n"
  71. "(abs(fp-s)/s>0.001)", ValueError],
  72. 3: ["The maximal number of iterations (20) allowed for finding smoothing\n"
  73. "spline with fp=s has been reached. Probable cause: s too small.\n"
  74. "(abs(fp-s)/s>0.001)", ValueError],
  75. 4: ["No more knots can be added because the number of B-spline\n"
  76. "coefficients already exceeds the number of data points m.\n"
  77. "Probable causes: either s or m too small. (fp>s)", ValueError],
  78. 5: ["No more knots can be added because the additional knot would\n"
  79. "coincide with an old one. Probable cause: s too small or too large\n"
  80. "a weight to an inaccurate data point. (fp>s)", ValueError],
  81. 10: ["Error on input data", ValueError],
  82. 11: ["rwrk2 too small, i.e., there is not enough workspace for computing\n"
  83. "the minimal least-squares solution of a rank deficient system of\n"
  84. "linear equations.", ValueError],
  85. 'unknown': ["An error occurred", TypeError]
  86. }
  87. _parcur_cache = {'t': array([], float), 'wrk': array([], float),
  88. 'iwrk': array([], dfitpack_int), 'u': array([], float),
  89. 'ub': 0, 'ue': 1}
  90. def splprep(x, w=None, u=None, ub=None, ue=None, k=3, task=0, s=None, t=None,
  91. full_output=0, nest=None, per=0, quiet=1):
  92. """
  93. Find the B-spline representation of an N-D curve.
  94. Given a list of N rank-1 arrays, `x`, which represent a curve in
  95. N-dimensional space parametrized by `u`, find a smooth approximating
  96. spline curve g(`u`). Uses the FORTRAN routine parcur from FITPACK.
  97. Parameters
  98. ----------
  99. x : array_like
  100. A list of sample vector arrays representing the curve.
  101. w : array_like, optional
  102. Strictly positive rank-1 array of weights the same length as `x[0]`.
  103. The weights are used in computing the weighted least-squares spline
  104. fit. If the errors in the `x` values have standard-deviation given by
  105. the vector d, then `w` should be 1/d. Default is ``ones(len(x[0]))``.
  106. u : array_like, optional
  107. An array of parameter values. If not given, these values are
  108. calculated automatically as ``M = len(x[0])``, where
  109. v[0] = 0
  110. v[i] = v[i-1] + distance(`x[i]`, `x[i-1]`)
  111. u[i] = v[i] / v[M-1]
  112. ub, ue : int, optional
  113. The end-points of the parameters interval. Defaults to
  114. u[0] and u[-1].
  115. k : int, optional
  116. Degree of the spline. Cubic splines are recommended.
  117. Even values of `k` should be avoided especially with a small s-value.
  118. ``1 <= k <= 5``, default is 3.
  119. task : int, optional
  120. If task==0 (default), find t and c for a given smoothing factor, s.
  121. If task==1, find t and c for another value of the smoothing factor, s.
  122. There must have been a previous call with task=0 or task=1
  123. for the same set of data.
  124. If task=-1 find the weighted least square spline for a given set of
  125. knots, t.
  126. s : float, optional
  127. A smoothing condition. The amount of smoothness is determined by
  128. satisfying the conditions: ``sum((w * (y - g))**2,axis=0) <= s``,
  129. where g(x) is the smoothed interpolation of (x,y). The user can
  130. use `s` to control the trade-off between closeness and smoothness
  131. of fit. Larger `s` means more smoothing while smaller values of `s`
  132. indicate less smoothing. Recommended values of `s` depend on the
  133. weights, w. If the weights represent the inverse of the
  134. standard-deviation of y, then a good `s` value should be found in
  135. the range ``(m-sqrt(2*m),m+sqrt(2*m))``, where m is the number of
  136. data points in x, y, and w.
  137. t : int, optional
  138. The knots needed for task=-1.
  139. full_output : int, optional
  140. If non-zero, then return optional outputs.
  141. nest : int, optional
  142. An over-estimate of the total number of knots of the spline to
  143. help in determining the storage space. By default nest=m/2.
  144. Always large enough is nest=m+k+1.
  145. per : int, optional
  146. If non-zero, data points are considered periodic with period
  147. ``x[m-1] - x[0]`` and a smooth periodic spline approximation is
  148. returned. Values of ``y[m-1]`` and ``w[m-1]`` are not used.
  149. quiet : int, optional
  150. Non-zero to suppress messages.
  151. Returns
  152. -------
  153. tck : tuple
  154. A tuple (t,c,k) containing the vector of knots, the B-spline
  155. coefficients, and the degree of the spline.
  156. u : array
  157. An array of the values of the parameter.
  158. fp : float
  159. The weighted sum of squared residuals of the spline approximation.
  160. ier : int
  161. An integer flag about splrep success. Success is indicated
  162. if ier<=0. If ier in [1,2,3] an error occurred but was not raised.
  163. Otherwise an error is raised.
  164. msg : str
  165. A message corresponding to the integer flag, ier.
  166. See Also
  167. --------
  168. splrep, splev, sproot, spalde, splint,
  169. bisplrep, bisplev
  170. UnivariateSpline, BivariateSpline
  171. Notes
  172. -----
  173. See `splev` for evaluation of the spline and its derivatives.
  174. The number of dimensions N must be smaller than 11.
  175. References
  176. ----------
  177. .. [1] P. Dierckx, "Algorithms for smoothing data with periodic and
  178. parametric splines, Computer Graphics and Image Processing",
  179. 20 (1982) 171-184.
  180. .. [2] P. Dierckx, "Algorithms for smoothing data with periodic and
  181. parametric splines", report tw55, Dept. Computer Science,
  182. K.U.Leuven, 1981.
  183. .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs on
  184. Numerical Analysis, Oxford University Press, 1993.
  185. """
  186. if task <= 0:
  187. _parcur_cache = {'t': array([], float), 'wrk': array([], float),
  188. 'iwrk': array([], dfitpack_int), 'u': array([], float),
  189. 'ub': 0, 'ue': 1}
  190. x = atleast_1d(x)
  191. idim, m = x.shape
  192. if per:
  193. for i in range(idim):
  194. if x[i][0] != x[i][-1]:
  195. if not quiet:
  196. warnings.warn(RuntimeWarning('Setting x[%d][%d]=x[%d][0]' %
  197. (i, m, i)))
  198. x[i][-1] = x[i][0]
  199. if not 0 < idim < 11:
  200. raise TypeError('0 < idim < 11 must hold')
  201. if w is None:
  202. w = ones(m, float)
  203. else:
  204. w = atleast_1d(w)
  205. ipar = (u is not None)
  206. if ipar:
  207. _parcur_cache['u'] = u
  208. if ub is None:
  209. _parcur_cache['ub'] = u[0]
  210. else:
  211. _parcur_cache['ub'] = ub
  212. if ue is None:
  213. _parcur_cache['ue'] = u[-1]
  214. else:
  215. _parcur_cache['ue'] = ue
  216. else:
  217. _parcur_cache['u'] = zeros(m, float)
  218. if not (1 <= k <= 5):
  219. raise TypeError('1 <= k= %d <=5 must hold' % k)
  220. if not (-1 <= task <= 1):
  221. raise TypeError('task must be -1, 0 or 1')
  222. if (not len(w) == m) or (ipar == 1 and (not len(u) == m)):
  223. raise TypeError('Mismatch of input dimensions')
  224. if s is None:
  225. s = m - sqrt(2*m)
  226. if t is None and task == -1:
  227. raise TypeError('Knots must be given for task=-1')
  228. if t is not None:
  229. _parcur_cache['t'] = atleast_1d(t)
  230. n = len(_parcur_cache['t'])
  231. if task == -1 and n < 2*k + 2:
  232. raise TypeError('There must be at least 2*k+2 knots for task=-1')
  233. if m <= k:
  234. raise TypeError('m > k must hold')
  235. if nest is None:
  236. nest = m + 2*k
  237. if (task >= 0 and s == 0) or (nest < 0):
  238. if per:
  239. nest = m + 2*k
  240. else:
  241. nest = m + k + 1
  242. nest = max(nest, 2*k + 3)
  243. u = _parcur_cache['u']
  244. ub = _parcur_cache['ub']
  245. ue = _parcur_cache['ue']
  246. t = _parcur_cache['t']
  247. wrk = _parcur_cache['wrk']
  248. iwrk = _parcur_cache['iwrk']
  249. t, c, o = _fitpack._parcur(ravel(transpose(x)), w, u, ub, ue, k,
  250. task, ipar, s, t, nest, wrk, iwrk, per)
  251. _parcur_cache['u'] = o['u']
  252. _parcur_cache['ub'] = o['ub']
  253. _parcur_cache['ue'] = o['ue']
  254. _parcur_cache['t'] = t
  255. _parcur_cache['wrk'] = o['wrk']
  256. _parcur_cache['iwrk'] = o['iwrk']
  257. ier = o['ier']
  258. fp = o['fp']
  259. n = len(t)
  260. u = o['u']
  261. c.shape = idim, n - k - 1
  262. tcku = [t, list(c), k], u
  263. if ier <= 0 and not quiet:
  264. warnings.warn(RuntimeWarning(_iermess[ier][0] +
  265. "\tk=%d n=%d m=%d fp=%f s=%f" %
  266. (k, len(t), m, fp, s)))
  267. if ier > 0 and not full_output:
  268. if ier in [1, 2, 3]:
  269. warnings.warn(RuntimeWarning(_iermess[ier][0]))
  270. else:
  271. try:
  272. raise _iermess[ier][1](_iermess[ier][0])
  273. except KeyError as e:
  274. raise _iermess['unknown'][1](_iermess['unknown'][0]) from e
  275. if full_output:
  276. try:
  277. return tcku, fp, ier, _iermess[ier][0]
  278. except KeyError:
  279. return tcku, fp, ier, _iermess['unknown'][0]
  280. else:
  281. return tcku
  282. _curfit_cache = {'t': array([], float), 'wrk': array([], float),
  283. 'iwrk': array([], dfitpack_int)}
  284. def splrep(x, y, w=None, xb=None, xe=None, k=3, task=0, s=None, t=None,
  285. full_output=0, per=0, quiet=1):
  286. """
  287. Find the B-spline representation of 1-D curve.
  288. Given the set of data points ``(x[i], y[i])`` determine a smooth spline
  289. approximation of degree k on the interval ``xb <= x <= xe``.
  290. Parameters
  291. ----------
  292. x, y : array_like
  293. The data points defining a curve y = f(x).
  294. w : array_like, optional
  295. Strictly positive rank-1 array of weights the same length as x and y.
  296. The weights are used in computing the weighted least-squares spline
  297. fit. If the errors in the y values have standard-deviation given by the
  298. vector d, then w should be 1/d. Default is ones(len(x)).
  299. xb, xe : float, optional
  300. The interval to fit. If None, these default to x[0] and x[-1]
  301. respectively.
  302. k : int, optional
  303. The order of the spline fit. It is recommended to use cubic splines.
  304. Even order splines should be avoided especially with small s values.
  305. 1 <= k <= 5
  306. task : {1, 0, -1}, optional
  307. If task==0 find t and c for a given smoothing factor, s.
  308. If task==1 find t and c for another value of the smoothing factor, s.
  309. There must have been a previous call with task=0 or task=1 for the same
  310. set of data (t will be stored an used internally)
  311. If task=-1 find the weighted least square spline for a given set of
  312. knots, t. These should be interior knots as knots on the ends will be
  313. added automatically.
  314. s : float, optional
  315. A smoothing condition. The amount of smoothness is determined by
  316. satisfying the conditions: sum((w * (y - g))**2,axis=0) <= s, where g(x)
  317. is the smoothed interpolation of (x,y). The user can use s to control
  318. the tradeoff between closeness and smoothness of fit. Larger s means
  319. more smoothing while smaller values of s indicate less smoothing.
  320. Recommended values of s depend on the weights, w. If the weights
  321. represent the inverse of the standard-deviation of y, then a good s
  322. value should be found in the range (m-sqrt(2*m),m+sqrt(2*m)) where m is
  323. the number of datapoints in x, y, and w. default : s=m-sqrt(2*m) if
  324. weights are supplied. s = 0.0 (interpolating) if no weights are
  325. supplied.
  326. t : array_like, optional
  327. The knots needed for task=-1. If given then task is automatically set
  328. to -1.
  329. full_output : bool, optional
  330. If non-zero, then return optional outputs.
  331. per : bool, optional
  332. If non-zero, data points are considered periodic with period x[m-1] -
  333. x[0] and a smooth periodic spline approximation is returned. Values of
  334. y[m-1] and w[m-1] are not used.
  335. quiet : bool, optional
  336. Non-zero to suppress messages.
  337. Returns
  338. -------
  339. tck : tuple
  340. (t,c,k) a tuple containing the vector of knots, the B-spline
  341. coefficients, and the degree of the spline.
  342. fp : array, optional
  343. The weighted sum of squared residuals of the spline approximation.
  344. ier : int, optional
  345. An integer flag about splrep success. Success is indicated if ier<=0.
  346. If ier in [1,2,3] an error occurred but was not raised. Otherwise an
  347. error is raised.
  348. msg : str, optional
  349. A message corresponding to the integer flag, ier.
  350. See Also
  351. --------
  352. UnivariateSpline, BivariateSpline
  353. splprep, splev, sproot, spalde, splint
  354. bisplrep, bisplev
  355. Notes
  356. -----
  357. See splev for evaluation of the spline and its derivatives. Uses the
  358. FORTRAN routine curfit from FITPACK.
  359. The user is responsible for assuring that the values of *x* are unique.
  360. Otherwise, *splrep* will not return sensible results.
  361. If provided, knots `t` must satisfy the Schoenberg-Whitney conditions,
  362. i.e., there must be a subset of data points ``x[j]`` such that
  363. ``t[j] < x[j] < t[j+k+1]``, for ``j=0, 1,...,n-k-2``.
  364. References
  365. ----------
  366. Based on algorithms described in [1]_, [2]_, [3]_, and [4]_:
  367. .. [1] P. Dierckx, "An algorithm for smoothing, differentiation and
  368. integration of experimental data using spline functions",
  369. J.Comp.Appl.Maths 1 (1975) 165-184.
  370. .. [2] P. Dierckx, "A fast algorithm for smoothing data on a rectangular
  371. grid while using spline functions", SIAM J.Numer.Anal. 19 (1982)
  372. 1286-1304.
  373. .. [3] P. Dierckx, "An improved algorithm for curve fitting with spline
  374. functions", report tw54, Dept. Computer Science,K.U. Leuven, 1981.
  375. .. [4] P. Dierckx, "Curve and surface fitting with splines", Monographs on
  376. Numerical Analysis, Oxford University Press, 1993.
  377. Examples
  378. --------
  379. >>> import matplotlib.pyplot as plt
  380. >>> from scipy.interpolate import splev, splrep
  381. >>> x = np.linspace(0, 10, 10)
  382. >>> y = np.sin(x)
  383. >>> tck = splrep(x, y)
  384. >>> x2 = np.linspace(0, 10, 200)
  385. >>> y2 = splev(x2, tck)
  386. >>> plt.plot(x, y, 'o', x2, y2)
  387. >>> plt.show()
  388. """
  389. if task <= 0:
  390. _curfit_cache = {}
  391. x, y = map(atleast_1d, [x, y])
  392. m = len(x)
  393. if w is None:
  394. w = ones(m, float)
  395. if s is None:
  396. s = 0.0
  397. else:
  398. w = atleast_1d(w)
  399. if s is None:
  400. s = m - sqrt(2*m)
  401. if not len(w) == m:
  402. raise TypeError('len(w)=%d is not equal to m=%d' % (len(w), m))
  403. if (m != len(y)) or (m != len(w)):
  404. raise TypeError('Lengths of the first three arguments (x,y,w) must '
  405. 'be equal')
  406. if not (1 <= k <= 5):
  407. raise TypeError('Given degree of the spline (k=%d) is not supported. '
  408. '(1<=k<=5)' % k)
  409. if m <= k:
  410. raise TypeError('m > k must hold')
  411. if xb is None:
  412. xb = x[0]
  413. if xe is None:
  414. xe = x[-1]
  415. if not (-1 <= task <= 1):
  416. raise TypeError('task must be -1, 0 or 1')
  417. if t is not None:
  418. task = -1
  419. if task == -1:
  420. if t is None:
  421. raise TypeError('Knots must be given for task=-1')
  422. numknots = len(t)
  423. _curfit_cache['t'] = empty((numknots + 2*k + 2,), float)
  424. _curfit_cache['t'][k+1:-k-1] = t
  425. nest = len(_curfit_cache['t'])
  426. elif task == 0:
  427. if per:
  428. nest = max(m + 2*k, 2*k + 3)
  429. else:
  430. nest = max(m + k + 1, 2*k + 3)
  431. t = empty((nest,), float)
  432. _curfit_cache['t'] = t
  433. if task <= 0:
  434. if per:
  435. _curfit_cache['wrk'] = empty((m*(k + 1) + nest*(8 + 5*k),), float)
  436. else:
  437. _curfit_cache['wrk'] = empty((m*(k + 1) + nest*(7 + 3*k),), float)
  438. _curfit_cache['iwrk'] = empty((nest,), dfitpack_int)
  439. try:
  440. t = _curfit_cache['t']
  441. wrk = _curfit_cache['wrk']
  442. iwrk = _curfit_cache['iwrk']
  443. except KeyError as e:
  444. raise TypeError("must call with task=1 only after"
  445. " call with task=0,-1") from e
  446. if not per:
  447. n, c, fp, ier = dfitpack.curfit(task, x, y, w, t, wrk, iwrk,
  448. xb, xe, k, s)
  449. else:
  450. n, c, fp, ier = dfitpack.percur(task, x, y, w, t, wrk, iwrk, k, s)
  451. tck = (t[:n], c[:n], k)
  452. if ier <= 0 and not quiet:
  453. _mess = (_iermess[ier][0] + "\tk=%d n=%d m=%d fp=%f s=%f" %
  454. (k, len(t), m, fp, s))
  455. warnings.warn(RuntimeWarning(_mess))
  456. if ier > 0 and not full_output:
  457. if ier in [1, 2, 3]:
  458. warnings.warn(RuntimeWarning(_iermess[ier][0]))
  459. else:
  460. try:
  461. raise _iermess[ier][1](_iermess[ier][0])
  462. except KeyError as e:
  463. raise _iermess['unknown'][1](_iermess['unknown'][0]) from e
  464. if full_output:
  465. try:
  466. return tck, fp, ier, _iermess[ier][0]
  467. except KeyError:
  468. return tck, fp, ier, _iermess['unknown'][0]
  469. else:
  470. return tck
  471. def splev(x, tck, der=0, ext=0):
  472. """
  473. Evaluate a B-spline or its derivatives.
  474. Given the knots and coefficients of a B-spline representation, evaluate
  475. the value of the smoothing polynomial and its derivatives. This is a
  476. wrapper around the FORTRAN routines splev and splder of FITPACK.
  477. Parameters
  478. ----------
  479. x : array_like
  480. An array of points at which to return the value of the smoothed
  481. spline or its derivatives. If `tck` was returned from `splprep`,
  482. then the parameter values, u should be given.
  483. tck : tuple
  484. A sequence of length 3 returned by `splrep` or `splprep` containing
  485. the knots, coefficients, and degree of the spline.
  486. der : int, optional
  487. The order of derivative of the spline to compute (must be less than
  488. or equal to k).
  489. ext : int, optional
  490. Controls the value returned for elements of ``x`` not in the
  491. interval defined by the knot sequence.
  492. * if ext=0, return the extrapolated value.
  493. * if ext=1, return 0
  494. * if ext=2, raise a ValueError
  495. * if ext=3, return the boundary value.
  496. The default value is 0.
  497. Returns
  498. -------
  499. y : ndarray or list of ndarrays
  500. An array of values representing the spline function evaluated at
  501. the points in ``x``. If `tck` was returned from `splprep`, then this
  502. is a list of arrays representing the curve in N-D space.
  503. See Also
  504. --------
  505. splprep, splrep, sproot, spalde, splint
  506. bisplrep, bisplev
  507. References
  508. ----------
  509. .. [1] C. de Boor, "On calculating with b-splines", J. Approximation
  510. Theory, 6, p.50-62, 1972.
  511. .. [2] M.G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths
  512. Applics, 10, p.134-149, 1972.
  513. .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs
  514. on Numerical Analysis, Oxford University Press, 1993.
  515. """
  516. t, c, k = tck
  517. try:
  518. c[0][0]
  519. parametric = True
  520. except Exception:
  521. parametric = False
  522. if parametric:
  523. return list(map(lambda c, x=x, t=t, k=k, der=der:
  524. splev(x, [t, c, k], der, ext), c))
  525. else:
  526. if not (0 <= der <= k):
  527. raise ValueError("0<=der=%d<=k=%d must hold" % (der, k))
  528. if ext not in (0, 1, 2, 3):
  529. raise ValueError("ext = %s not in (0, 1, 2, 3) " % ext)
  530. x = asarray(x)
  531. shape = x.shape
  532. x = atleast_1d(x).ravel()
  533. y, ier = _fitpack._spl_(x, der, t, c, k, ext)
  534. if ier == 10:
  535. raise ValueError("Invalid input data")
  536. if ier == 1:
  537. raise ValueError("Found x value not in the domain")
  538. if ier:
  539. raise TypeError("An error occurred")
  540. return y.reshape(shape)
  541. def splint(a, b, tck, full_output=0):
  542. """
  543. Evaluate the definite integral of a B-spline.
  544. Given the knots and coefficients of a B-spline, evaluate the definite
  545. integral of the smoothing polynomial between two given points.
  546. Parameters
  547. ----------
  548. a, b : float
  549. The end-points of the integration interval.
  550. tck : tuple
  551. A tuple (t,c,k) containing the vector of knots, the B-spline
  552. coefficients, and the degree of the spline (see `splev`).
  553. full_output : int, optional
  554. Non-zero to return optional output.
  555. Returns
  556. -------
  557. integral : float
  558. The resulting integral.
  559. wrk : ndarray
  560. An array containing the integrals of the normalized B-splines
  561. defined on the set of knots.
  562. Notes
  563. -----
  564. splint silently assumes that the spline function is zero outside the data
  565. interval (a, b).
  566. See Also
  567. --------
  568. splprep, splrep, sproot, spalde, splev
  569. bisplrep, bisplev
  570. UnivariateSpline, BivariateSpline
  571. References
  572. ----------
  573. .. [1] P.W. Gaffney, The calculation of indefinite integrals of b-splines",
  574. J. Inst. Maths Applics, 17, p.37-41, 1976.
  575. .. [2] P. Dierckx, "Curve and surface fitting with splines", Monographs
  576. on Numerical Analysis, Oxford University Press, 1993.
  577. """
  578. t, c, k = tck
  579. try:
  580. c[0][0]
  581. parametric = True
  582. except Exception:
  583. parametric = False
  584. if parametric:
  585. return list(map(lambda c, a=a, b=b, t=t, k=k:
  586. splint(a, b, [t, c, k]), c))
  587. else:
  588. aint, wrk = dfitpack.splint(t, c, k, a, b)
  589. if full_output:
  590. return aint, wrk
  591. else:
  592. return aint
  593. def sproot(tck, mest=10):
  594. """
  595. Find the roots of a cubic B-spline.
  596. Given the knots (>=8) and coefficients of a cubic B-spline return the
  597. roots of the spline.
  598. Parameters
  599. ----------
  600. tck : tuple
  601. A tuple (t,c,k) containing the vector of knots,
  602. the B-spline coefficients, and the degree of the spline.
  603. The number of knots must be >= 8, and the degree must be 3.
  604. The knots must be a montonically increasing sequence.
  605. mest : int, optional
  606. An estimate of the number of zeros (Default is 10).
  607. Returns
  608. -------
  609. zeros : ndarray
  610. An array giving the roots of the spline.
  611. See Also
  612. --------
  613. splprep, splrep, splint, spalde, splev
  614. bisplrep, bisplev
  615. UnivariateSpline, BivariateSpline
  616. References
  617. ----------
  618. .. [1] C. de Boor, "On calculating with b-splines", J. Approximation
  619. Theory, 6, p.50-62, 1972.
  620. .. [2] M.G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths
  621. Applics, 10, p.134-149, 1972.
  622. .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs
  623. on Numerical Analysis, Oxford University Press, 1993.
  624. """
  625. t, c, k = tck
  626. if k != 3:
  627. raise ValueError("sproot works only for cubic (k=3) splines")
  628. try:
  629. c[0][0]
  630. parametric = True
  631. except Exception:
  632. parametric = False
  633. if parametric:
  634. return list(map(lambda c, t=t, k=k, mest=mest:
  635. sproot([t, c, k], mest), c))
  636. else:
  637. if len(t) < 8:
  638. raise TypeError("The number of knots %d>=8" % len(t))
  639. z, m, ier = dfitpack.sproot(t, c, mest)
  640. if ier == 10:
  641. raise TypeError("Invalid input data. "
  642. "t1<=..<=t4<t5<..<tn-3<=..<=tn must hold.")
  643. if ier == 0:
  644. return z[:m]
  645. if ier == 1:
  646. warnings.warn(RuntimeWarning("The number of zeros exceeds mest"))
  647. return z[:m]
  648. raise TypeError("Unknown error")
  649. def spalde(x, tck):
  650. """
  651. Evaluate all derivatives of a B-spline.
  652. Given the knots and coefficients of a cubic B-spline compute all
  653. derivatives up to order k at a point (or set of points).
  654. Parameters
  655. ----------
  656. x : array_like
  657. A point or a set of points at which to evaluate the derivatives.
  658. Note that ``t(k) <= x <= t(n-k+1)`` must hold for each `x`.
  659. tck : tuple
  660. A tuple (t,c,k) containing the vector of knots,
  661. the B-spline coefficients, and the degree of the spline.
  662. Returns
  663. -------
  664. results : {ndarray, list of ndarrays}
  665. An array (or a list of arrays) containing all derivatives
  666. up to order k inclusive for each point `x`.
  667. See Also
  668. --------
  669. splprep, splrep, splint, sproot, splev, bisplrep, bisplev,
  670. UnivariateSpline, BivariateSpline
  671. References
  672. ----------
  673. .. [1] de Boor C : On calculating with b-splines, J. Approximation Theory
  674. 6 (1972) 50-62.
  675. .. [2] Cox M.G. : The numerical evaluation of b-splines, J. Inst. Maths
  676. applics 10 (1972) 134-149.
  677. .. [3] Dierckx P. : Curve and surface fitting with splines, Monographs on
  678. Numerical Analysis, Oxford University Press, 1993.
  679. """
  680. t, c, k = tck
  681. try:
  682. c[0][0]
  683. parametric = True
  684. except Exception:
  685. parametric = False
  686. if parametric:
  687. return list(map(lambda c, x=x, t=t, k=k:
  688. spalde(x, [t, c, k]), c))
  689. else:
  690. x = atleast_1d(x)
  691. if len(x) > 1:
  692. return list(map(lambda x, tck=tck: spalde(x, tck), x))
  693. d, ier = dfitpack.spalde(t, c, k+1, x[0])
  694. if ier == 0:
  695. return d
  696. if ier == 10:
  697. raise TypeError("Invalid input data. t(k)<=x<=t(n-k+1) must hold.")
  698. raise TypeError("Unknown error")
  699. # def _curfit(x,y,w=None,xb=None,xe=None,k=3,task=0,s=None,t=None,
  700. # full_output=0,nest=None,per=0,quiet=1):
  701. _surfit_cache = {'tx': array([], float), 'ty': array([], float),
  702. 'wrk': array([], float), 'iwrk': array([], dfitpack_int)}
  703. def bisplrep(x, y, z, w=None, xb=None, xe=None, yb=None, ye=None,
  704. kx=3, ky=3, task=0, s=None, eps=1e-16, tx=None, ty=None,
  705. full_output=0, nxest=None, nyest=None, quiet=1):
  706. """
  707. Find a bivariate B-spline representation of a surface.
  708. Given a set of data points (x[i], y[i], z[i]) representing a surface
  709. z=f(x,y), compute a B-spline representation of the surface. Based on
  710. the routine SURFIT from FITPACK.
  711. Parameters
  712. ----------
  713. x, y, z : ndarray
  714. Rank-1 arrays of data points.
  715. w : ndarray, optional
  716. Rank-1 array of weights. By default ``w=np.ones(len(x))``.
  717. xb, xe : float, optional
  718. End points of approximation interval in `x`.
  719. By default ``xb = x.min(), xe=x.max()``.
  720. yb, ye : float, optional
  721. End points of approximation interval in `y`.
  722. By default ``yb=y.min(), ye = y.max()``.
  723. kx, ky : int, optional
  724. The degrees of the spline (1 <= kx, ky <= 5).
  725. Third order (kx=ky=3) is recommended.
  726. task : int, optional
  727. If task=0, find knots in x and y and coefficients for a given
  728. smoothing factor, s.
  729. If task=1, find knots and coefficients for another value of the
  730. smoothing factor, s. bisplrep must have been previously called
  731. with task=0 or task=1.
  732. If task=-1, find coefficients for a given set of knots tx, ty.
  733. s : float, optional
  734. A non-negative smoothing factor. If weights correspond
  735. to the inverse of the standard-deviation of the errors in z,
  736. then a good s-value should be found in the range
  737. ``(m-sqrt(2*m),m+sqrt(2*m))`` where m=len(x).
  738. eps : float, optional
  739. A threshold for determining the effective rank of an
  740. over-determined linear system of equations (0 < eps < 1).
  741. `eps` is not likely to need changing.
  742. tx, ty : ndarray, optional
  743. Rank-1 arrays of the knots of the spline for task=-1
  744. full_output : int, optional
  745. Non-zero to return optional outputs.
  746. nxest, nyest : int, optional
  747. Over-estimates of the total number of knots. If None then
  748. ``nxest = max(kx+sqrt(m/2),2*kx+3)``,
  749. ``nyest = max(ky+sqrt(m/2),2*ky+3)``.
  750. quiet : int, optional
  751. Non-zero to suppress printing of messages.
  752. Returns
  753. -------
  754. tck : array_like
  755. A list [tx, ty, c, kx, ky] containing the knots (tx, ty) and
  756. coefficients (c) of the bivariate B-spline representation of the
  757. surface along with the degree of the spline.
  758. fp : ndarray
  759. The weighted sum of squared residuals of the spline approximation.
  760. ier : int
  761. An integer flag about splrep success. Success is indicated if
  762. ier<=0. If ier in [1,2,3] an error occurred but was not raised.
  763. Otherwise an error is raised.
  764. msg : str
  765. A message corresponding to the integer flag, ier.
  766. See Also
  767. --------
  768. splprep, splrep, splint, sproot, splev
  769. UnivariateSpline, BivariateSpline
  770. Notes
  771. -----
  772. See `bisplev` to evaluate the value of the B-spline given its tck
  773. representation.
  774. If the input data is such that input dimensions have incommensurate
  775. units and differ by many orders of magnitude, the interpolant may have
  776. numerical artifacts. Consider rescaling the data before interpolation.
  777. References
  778. ----------
  779. .. [1] Dierckx P.:An algorithm for surface fitting with spline functions
  780. Ima J. Numer. Anal. 1 (1981) 267-283.
  781. .. [2] Dierckx P.:An algorithm for surface fitting with spline functions
  782. report tw50, Dept. Computer Science,K.U.Leuven, 1980.
  783. .. [3] Dierckx P.:Curve and surface fitting with splines, Monographs on
  784. Numerical Analysis, Oxford University Press, 1993.
  785. Examples
  786. --------
  787. Examples are given :ref:`in the tutorial <tutorial-interpolate_2d_spline>`.
  788. """
  789. x, y, z = map(ravel, [x, y, z]) # ensure 1-d arrays.
  790. m = len(x)
  791. if not (m == len(y) == len(z)):
  792. raise TypeError('len(x)==len(y)==len(z) must hold.')
  793. if w is None:
  794. w = ones(m, float)
  795. else:
  796. w = atleast_1d(w)
  797. if not len(w) == m:
  798. raise TypeError('len(w)=%d is not equal to m=%d' % (len(w), m))
  799. if xb is None:
  800. xb = x.min()
  801. if xe is None:
  802. xe = x.max()
  803. if yb is None:
  804. yb = y.min()
  805. if ye is None:
  806. ye = y.max()
  807. if not (-1 <= task <= 1):
  808. raise TypeError('task must be -1, 0 or 1')
  809. if s is None:
  810. s = m - sqrt(2*m)
  811. if tx is None and task == -1:
  812. raise TypeError('Knots_x must be given for task=-1')
  813. if tx is not None:
  814. _surfit_cache['tx'] = atleast_1d(tx)
  815. nx = len(_surfit_cache['tx'])
  816. if ty is None and task == -1:
  817. raise TypeError('Knots_y must be given for task=-1')
  818. if ty is not None:
  819. _surfit_cache['ty'] = atleast_1d(ty)
  820. ny = len(_surfit_cache['ty'])
  821. if task == -1 and nx < 2*kx+2:
  822. raise TypeError('There must be at least 2*kx+2 knots_x for task=-1')
  823. if task == -1 and ny < 2*ky+2:
  824. raise TypeError('There must be at least 2*ky+2 knots_x for task=-1')
  825. if not ((1 <= kx <= 5) and (1 <= ky <= 5)):
  826. raise TypeError('Given degree of the spline (kx,ky=%d,%d) is not '
  827. 'supported. (1<=k<=5)' % (kx, ky))
  828. if m < (kx + 1)*(ky + 1):
  829. raise TypeError('m >= (kx+1)(ky+1) must hold')
  830. if nxest is None:
  831. nxest = int(kx + sqrt(m/2))
  832. if nyest is None:
  833. nyest = int(ky + sqrt(m/2))
  834. nxest, nyest = max(nxest, 2*kx + 3), max(nyest, 2*ky + 3)
  835. if task >= 0 and s == 0:
  836. nxest = int(kx + sqrt(3*m))
  837. nyest = int(ky + sqrt(3*m))
  838. if task == -1:
  839. _surfit_cache['tx'] = atleast_1d(tx)
  840. _surfit_cache['ty'] = atleast_1d(ty)
  841. tx, ty = _surfit_cache['tx'], _surfit_cache['ty']
  842. wrk = _surfit_cache['wrk']
  843. u = nxest - kx - 1
  844. v = nyest - ky - 1
  845. km = max(kx, ky) + 1
  846. ne = max(nxest, nyest)
  847. bx, by = kx*v + ky + 1, ky*u + kx + 1
  848. b1, b2 = bx, bx + v - ky
  849. if bx > by:
  850. b1, b2 = by, by + u - kx
  851. msg = "Too many data points to interpolate"
  852. lwrk1 = _int_overflow(u*v*(2 + b1 + b2) +
  853. 2*(u + v + km*(m + ne) + ne - kx - ky) + b2 + 1,
  854. msg=msg)
  855. lwrk2 = _int_overflow(u*v*(b2 + 1) + b2, msg=msg)
  856. tx, ty, c, o = _fitpack._surfit(x, y, z, w, xb, xe, yb, ye, kx, ky,
  857. task, s, eps, tx, ty, nxest, nyest,
  858. wrk, lwrk1, lwrk2)
  859. _curfit_cache['tx'] = tx
  860. _curfit_cache['ty'] = ty
  861. _curfit_cache['wrk'] = o['wrk']
  862. ier, fp = o['ier'], o['fp']
  863. tck = [tx, ty, c, kx, ky]
  864. ierm = min(11, max(-3, ier))
  865. if ierm <= 0 and not quiet:
  866. _mess = (_iermess2[ierm][0] +
  867. "\tkx,ky=%d,%d nx,ny=%d,%d m=%d fp=%f s=%f" %
  868. (kx, ky, len(tx), len(ty), m, fp, s))
  869. warnings.warn(RuntimeWarning(_mess))
  870. if ierm > 0 and not full_output:
  871. if ier in [1, 2, 3, 4, 5]:
  872. _mess = ("\n\tkx,ky=%d,%d nx,ny=%d,%d m=%d fp=%f s=%f" %
  873. (kx, ky, len(tx), len(ty), m, fp, s))
  874. warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess))
  875. else:
  876. try:
  877. raise _iermess2[ierm][1](_iermess2[ierm][0])
  878. except KeyError as e:
  879. raise _iermess2['unknown'][1](_iermess2['unknown'][0]) from e
  880. if full_output:
  881. try:
  882. return tck, fp, ier, _iermess2[ierm][0]
  883. except KeyError:
  884. return tck, fp, ier, _iermess2['unknown'][0]
  885. else:
  886. return tck
  887. def bisplev(x, y, tck, dx=0, dy=0):
  888. """
  889. Evaluate a bivariate B-spline and its derivatives.
  890. Return a rank-2 array of spline function values (or spline derivative
  891. values) at points given by the cross-product of the rank-1 arrays `x` and
  892. `y`. In special cases, return an array or just a float if either `x` or
  893. `y` or both are floats. Based on BISPEV and PARDER from FITPACK.
  894. Parameters
  895. ----------
  896. x, y : ndarray
  897. Rank-1 arrays specifying the domain over which to evaluate the
  898. spline or its derivative.
  899. tck : tuple
  900. A sequence of length 5 returned by `bisplrep` containing the knot
  901. locations, the coefficients, and the degree of the spline:
  902. [tx, ty, c, kx, ky].
  903. dx, dy : int, optional
  904. The orders of the partial derivatives in `x` and `y` respectively.
  905. Returns
  906. -------
  907. vals : ndarray
  908. The B-spline or its derivative evaluated over the set formed by
  909. the cross-product of `x` and `y`.
  910. See Also
  911. --------
  912. splprep, splrep, splint, sproot, splev
  913. UnivariateSpline, BivariateSpline
  914. Notes
  915. -----
  916. See `bisplrep` to generate the `tck` representation.
  917. References
  918. ----------
  919. .. [1] Dierckx P. : An algorithm for surface fitting
  920. with spline functions
  921. Ima J. Numer. Anal. 1 (1981) 267-283.
  922. .. [2] Dierckx P. : An algorithm for surface fitting
  923. with spline functions
  924. report tw50, Dept. Computer Science,K.U.Leuven, 1980.
  925. .. [3] Dierckx P. : Curve and surface fitting with splines,
  926. Monographs on Numerical Analysis, Oxford University Press, 1993.
  927. Examples
  928. --------
  929. Examples are given :ref:`in the tutorial <tutorial-interpolate_2d_spline>`.
  930. """
  931. tx, ty, c, kx, ky = tck
  932. if not (0 <= dx < kx):
  933. raise ValueError("0 <= dx = %d < kx = %d must hold" % (dx, kx))
  934. if not (0 <= dy < ky):
  935. raise ValueError("0 <= dy = %d < ky = %d must hold" % (dy, ky))
  936. x, y = map(atleast_1d, [x, y])
  937. if (len(x.shape) != 1) or (len(y.shape) != 1):
  938. raise ValueError("First two entries should be rank-1 arrays.")
  939. z, ier = _fitpack._bispev(tx, ty, c, kx, ky, x, y, dx, dy)
  940. if ier == 10:
  941. raise ValueError("Invalid input data")
  942. if ier:
  943. raise TypeError("An error occurred")
  944. z.shape = len(x), len(y)
  945. if len(z) > 1:
  946. return z
  947. if len(z[0]) > 1:
  948. return z[0]
  949. return z[0][0]
  950. def dblint(xa, xb, ya, yb, tck):
  951. """Evaluate the integral of a spline over area [xa,xb] x [ya,yb].
  952. Parameters
  953. ----------
  954. xa, xb : float
  955. The end-points of the x integration interval.
  956. ya, yb : float
  957. The end-points of the y integration interval.
  958. tck : list [tx, ty, c, kx, ky]
  959. A sequence of length 5 returned by bisplrep containing the knot
  960. locations tx, ty, the coefficients c, and the degrees kx, ky
  961. of the spline.
  962. Returns
  963. -------
  964. integ : float
  965. The value of the resulting integral.
  966. """
  967. tx, ty, c, kx, ky = tck
  968. return dfitpack.dblint(tx, ty, c, kx, ky, xa, xb, ya, yb)
  969. def insert(x, tck, m=1, per=0):
  970. """
  971. Insert knots into a B-spline.
  972. Given the knots and coefficients of a B-spline representation, create a
  973. new B-spline with a knot inserted `m` times at point `x`.
  974. This is a wrapper around the FORTRAN routine insert of FITPACK.
  975. Parameters
  976. ----------
  977. x (u) : array_like
  978. A 1-D point at which to insert a new knot(s). If `tck` was returned
  979. from ``splprep``, then the parameter values, u should be given.
  980. tck : tuple
  981. A tuple (t,c,k) returned by ``splrep`` or ``splprep`` containing
  982. the vector of knots, the B-spline coefficients,
  983. and the degree of the spline.
  984. m : int, optional
  985. The number of times to insert the given knot (its multiplicity).
  986. Default is 1.
  987. per : int, optional
  988. If non-zero, the input spline is considered periodic.
  989. Returns
  990. -------
  991. tck : tuple
  992. A tuple (t,c,k) containing the vector of knots, the B-spline
  993. coefficients, and the degree of the new spline.
  994. ``t(k+1) <= x <= t(n-k)``, where k is the degree of the spline.
  995. In case of a periodic spline (``per != 0``) there must be
  996. either at least k interior knots t(j) satisfying ``t(k+1)<t(j)<=x``
  997. or at least k interior knots t(j) satisfying ``x<=t(j)<t(n-k)``.
  998. Notes
  999. -----
  1000. Based on algorithms from [1]_ and [2]_.
  1001. References
  1002. ----------
  1003. .. [1] W. Boehm, "Inserting new knots into b-spline curves.",
  1004. Computer Aided Design, 12, p.199-201, 1980.
  1005. .. [2] P. Dierckx, "Curve and surface fitting with splines, Monographs on
  1006. Numerical Analysis", Oxford University Press, 1993.
  1007. """
  1008. t, c, k = tck
  1009. try:
  1010. c[0][0]
  1011. parametric = True
  1012. except Exception:
  1013. parametric = False
  1014. if parametric:
  1015. cc = []
  1016. for c_vals in c:
  1017. tt, cc_val, kk = insert(x, [t, c_vals, k], m)
  1018. cc.append(cc_val)
  1019. return (tt, cc, kk)
  1020. else:
  1021. tt, cc, ier = _fitpack._insert(per, t, c, k, x, m)
  1022. if ier == 10:
  1023. raise ValueError("Invalid input data")
  1024. if ier:
  1025. raise TypeError("An error occurred")
  1026. return (tt, cc, k)
  1027. def splder(tck, n=1):
  1028. """
  1029. Compute the spline representation of the derivative of a given spline
  1030. Parameters
  1031. ----------
  1032. tck : tuple of (t, c, k)
  1033. Spline whose derivative to compute
  1034. n : int, optional
  1035. Order of derivative to evaluate. Default: 1
  1036. Returns
  1037. -------
  1038. tck_der : tuple of (t2, c2, k2)
  1039. Spline of order k2=k-n representing the derivative
  1040. of the input spline.
  1041. Notes
  1042. -----
  1043. .. versionadded:: 0.13.0
  1044. See Also
  1045. --------
  1046. splantider, splev, spalde
  1047. Examples
  1048. --------
  1049. This can be used for finding maxima of a curve:
  1050. >>> from scipy.interpolate import splrep, splder, sproot
  1051. >>> x = np.linspace(0, 10, 70)
  1052. >>> y = np.sin(x)
  1053. >>> spl = splrep(x, y, k=4)
  1054. Now, differentiate the spline and find the zeros of the
  1055. derivative. (NB: `sproot` only works for order 3 splines, so we
  1056. fit an order 4 spline):
  1057. >>> dspl = splder(spl)
  1058. >>> sproot(dspl) / np.pi
  1059. array([ 0.50000001, 1.5 , 2.49999998])
  1060. This agrees well with roots :math:`\\pi/2 + n\\pi` of
  1061. :math:`\\cos(x) = \\sin'(x)`.
  1062. """
  1063. if n < 0:
  1064. return splantider(tck, -n)
  1065. t, c, k = tck
  1066. if n > k:
  1067. raise ValueError(("Order of derivative (n = %r) must be <= "
  1068. "order of spline (k = %r)") % (n, tck[2]))
  1069. # Extra axes for the trailing dims of the `c` array:
  1070. sh = (slice(None),) + ((None,)*len(c.shape[1:]))
  1071. with np.errstate(invalid='raise', divide='raise'):
  1072. try:
  1073. for j in range(n):
  1074. # See e.g. Schumaker, Spline Functions: Basic Theory, Chapter 5
  1075. # Compute the denominator in the differentiation formula.
  1076. # (and append traling dims, if necessary)
  1077. dt = t[k+1:-1] - t[1:-k-1]
  1078. dt = dt[sh]
  1079. # Compute the new coefficients
  1080. c = (c[1:-1-k] - c[:-2-k]) * k / dt
  1081. # Pad coefficient array to same size as knots (FITPACK
  1082. # convention)
  1083. c = np.r_[c, np.zeros((k,) + c.shape[1:])]
  1084. # Adjust knots
  1085. t = t[1:-1]
  1086. k -= 1
  1087. except FloatingPointError as e:
  1088. raise ValueError(("The spline has internal repeated knots "
  1089. "and is not differentiable %d times") % n) from e
  1090. return t, c, k
  1091. def splantider(tck, n=1):
  1092. """
  1093. Compute the spline for the antiderivative (integral) of a given spline.
  1094. Parameters
  1095. ----------
  1096. tck : tuple of (t, c, k)
  1097. Spline whose antiderivative to compute
  1098. n : int, optional
  1099. Order of antiderivative to evaluate. Default: 1
  1100. Returns
  1101. -------
  1102. tck_ader : tuple of (t2, c2, k2)
  1103. Spline of order k2=k+n representing the antiderivative of the input
  1104. spline.
  1105. See Also
  1106. --------
  1107. splder, splev, spalde
  1108. Notes
  1109. -----
  1110. The `splder` function is the inverse operation of this function.
  1111. Namely, ``splder(splantider(tck))`` is identical to `tck`, modulo
  1112. rounding error.
  1113. .. versionadded:: 0.13.0
  1114. Examples
  1115. --------
  1116. >>> from scipy.interpolate import splrep, splder, splantider, splev
  1117. >>> x = np.linspace(0, np.pi/2, 70)
  1118. >>> y = 1 / np.sqrt(1 - 0.8*np.sin(x)**2)
  1119. >>> spl = splrep(x, y)
  1120. The derivative is the inverse operation of the antiderivative,
  1121. although some floating point error accumulates:
  1122. >>> splev(1.7, spl), splev(1.7, splder(splantider(spl)))
  1123. (array(2.1565429877197317), array(2.1565429877201865))
  1124. Antiderivative can be used to evaluate definite integrals:
  1125. >>> ispl = splantider(spl)
  1126. >>> splev(np.pi/2, ispl) - splev(0, ispl)
  1127. 2.2572053588768486
  1128. This is indeed an approximation to the complete elliptic integral
  1129. :math:`K(m) = \\int_0^{\\pi/2} [1 - m\\sin^2 x]^{-1/2} dx`:
  1130. >>> from scipy.special import ellipk
  1131. >>> ellipk(0.8)
  1132. 2.2572053268208538
  1133. """
  1134. if n < 0:
  1135. return splder(tck, -n)
  1136. t, c, k = tck
  1137. # Extra axes for the trailing dims of the `c` array:
  1138. sh = (slice(None),) + (None,)*len(c.shape[1:])
  1139. for j in range(n):
  1140. # This is the inverse set of operations to splder.
  1141. # Compute the multiplier in the antiderivative formula.
  1142. dt = t[k+1:] - t[:-k-1]
  1143. dt = dt[sh]
  1144. # Compute the new coefficients
  1145. c = np.cumsum(c[:-k-1] * dt, axis=0) / (k + 1)
  1146. c = np.r_[np.zeros((1,) + c.shape[1:]),
  1147. c,
  1148. [c[-1]] * (k+2)]
  1149. # New knots
  1150. t = np.r_[t[0], t, t[-1]]
  1151. k += 1
  1152. return t, c, k