_fitpack_impl.py 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311
  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. from __future__ import division, print_function, absolute_import
  20. __all__ = ['splrep', 'splprep', 'splev', 'splint', 'sproot', 'spalde',
  21. 'bisplrep', 'bisplev', 'insert', 'splder', 'splantider']
  22. import warnings
  23. import numpy as np
  24. from . import _fitpack
  25. from numpy import (atleast_1d, array, ones, zeros, sqrt, ravel, transpose,
  26. empty, iinfo, intc, asarray)
  27. # Try to replace _fitpack interface with
  28. # f2py-generated version
  29. from . import dfitpack
  30. def _intc_overflow(x, msg=None):
  31. """Cast the value to an intc and raise an OverflowError if the value
  32. cannot fit.
  33. """
  34. if x > iinfo(intc).max:
  35. if msg is None:
  36. msg = '%r cannot fit into an intc' % x
  37. raise OverflowError(msg)
  38. return intc(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([], intc), '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-dimensional 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. This parameter is deprecated; use standard Python warning filters
  152. instead.
  153. Returns
  154. -------
  155. tck : tuple
  156. A tuple (t,c,k) containing the vector of knots, the B-spline
  157. coefficients, and the degree of the spline.
  158. u : array
  159. An array of the values of the parameter.
  160. fp : float
  161. The weighted sum of squared residuals of the spline approximation.
  162. ier : int
  163. An integer flag about splrep success. Success is indicated
  164. if ier<=0. If ier in [1,2,3] an error occurred but was not raised.
  165. Otherwise an error is raised.
  166. msg : str
  167. A message corresponding to the integer flag, ier.
  168. See Also
  169. --------
  170. splrep, splev, sproot, spalde, splint,
  171. bisplrep, bisplev
  172. UnivariateSpline, BivariateSpline
  173. Notes
  174. -----
  175. See `splev` for evaluation of the spline and its derivatives.
  176. The number of dimensions N must be smaller than 11.
  177. References
  178. ----------
  179. .. [1] P. Dierckx, "Algorithms for smoothing data with periodic and
  180. parametric splines, Computer Graphics and Image Processing",
  181. 20 (1982) 171-184.
  182. .. [2] P. Dierckx, "Algorithms for smoothing data with periodic and
  183. parametric splines", report tw55, Dept. Computer Science,
  184. K.U.Leuven, 1981.
  185. .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs on
  186. Numerical Analysis, Oxford University Press, 1993.
  187. """
  188. if task <= 0:
  189. _parcur_cache = {'t': array([], float), 'wrk': array([], float),
  190. 'iwrk': array([], intc), 'u': array([], float),
  191. 'ub': 0, 'ue': 1}
  192. x = atleast_1d(x)
  193. idim, m = x.shape
  194. if per:
  195. for i in range(idim):
  196. if x[i][0] != x[i][-1]:
  197. if quiet < 2:
  198. warnings.warn(RuntimeWarning('Setting x[%d][%d]=x[%d][0]' %
  199. (i, m, i)))
  200. x[i][-1] = x[i][0]
  201. if not 0 < idim < 11:
  202. raise TypeError('0 < idim < 11 must hold')
  203. if w is None:
  204. w = ones(m, float)
  205. else:
  206. w = atleast_1d(w)
  207. ipar = (u is not None)
  208. if ipar:
  209. _parcur_cache['u'] = u
  210. if ub is None:
  211. _parcur_cache['ub'] = u[0]
  212. else:
  213. _parcur_cache['ub'] = ub
  214. if ue is None:
  215. _parcur_cache['ue'] = u[-1]
  216. else:
  217. _parcur_cache['ue'] = ue
  218. else:
  219. _parcur_cache['u'] = zeros(m, float)
  220. if not (1 <= k <= 5):
  221. raise TypeError('1 <= k= %d <=5 must hold' % k)
  222. if not (-1 <= task <= 1):
  223. raise TypeError('task must be -1, 0 or 1')
  224. if (not len(w) == m) or (ipar == 1 and (not len(u) == m)):
  225. raise TypeError('Mismatch of input dimensions')
  226. if s is None:
  227. s = m - sqrt(2*m)
  228. if t is None and task == -1:
  229. raise TypeError('Knots must be given for task=-1')
  230. if t is not None:
  231. _parcur_cache['t'] = atleast_1d(t)
  232. n = len(_parcur_cache['t'])
  233. if task == -1 and n < 2*k + 2:
  234. raise TypeError('There must be at least 2*k+2 knots for task=-1')
  235. if m <= k:
  236. raise TypeError('m > k must hold')
  237. if nest is None:
  238. nest = m + 2*k
  239. if (task >= 0 and s == 0) or (nest < 0):
  240. if per:
  241. nest = m + 2*k
  242. else:
  243. nest = m + k + 1
  244. nest = max(nest, 2*k + 3)
  245. u = _parcur_cache['u']
  246. ub = _parcur_cache['ub']
  247. ue = _parcur_cache['ue']
  248. t = _parcur_cache['t']
  249. wrk = _parcur_cache['wrk']
  250. iwrk = _parcur_cache['iwrk']
  251. t, c, o = _fitpack._parcur(ravel(transpose(x)), w, u, ub, ue, k,
  252. task, ipar, s, t, nest, wrk, iwrk, per)
  253. _parcur_cache['u'] = o['u']
  254. _parcur_cache['ub'] = o['ub']
  255. _parcur_cache['ue'] = o['ue']
  256. _parcur_cache['t'] = t
  257. _parcur_cache['wrk'] = o['wrk']
  258. _parcur_cache['iwrk'] = o['iwrk']
  259. ier = o['ier']
  260. fp = o['fp']
  261. n = len(t)
  262. u = o['u']
  263. c.shape = idim, n - k - 1
  264. tcku = [t, list(c), k], u
  265. if ier <= 0 and not quiet:
  266. warnings.warn(RuntimeWarning(_iermess[ier][0] +
  267. "\tk=%d n=%d m=%d fp=%f s=%f" %
  268. (k, len(t), m, fp, s)))
  269. if ier > 0 and not full_output:
  270. if ier in [1, 2, 3]:
  271. warnings.warn(RuntimeWarning(_iermess[ier][0]))
  272. else:
  273. try:
  274. raise _iermess[ier][1](_iermess[ier][0])
  275. except KeyError:
  276. raise _iermess['unknown'][1](_iermess['unknown'][0])
  277. if full_output:
  278. try:
  279. return tcku, fp, ier, _iermess[ier][0]
  280. except KeyError:
  281. return tcku, fp, ier, _iermess['unknown'][0]
  282. else:
  283. return tcku
  284. _curfit_cache = {'t': array([], float), 'wrk': array([], float),
  285. 'iwrk': array([], intc)}
  286. def splrep(x, y, w=None, xb=None, xe=None, k=3, task=0, s=None, t=None,
  287. full_output=0, per=0, quiet=1):
  288. """
  289. Find the B-spline representation of 1-D curve.
  290. Given the set of data points ``(x[i], y[i])`` determine a smooth spline
  291. approximation of degree k on the interval ``xb <= x <= xe``.
  292. Parameters
  293. ----------
  294. x, y : array_like
  295. The data points defining a curve y = f(x).
  296. w : array_like, optional
  297. Strictly positive rank-1 array of weights the same length as x and y.
  298. The weights are used in computing the weighted least-squares spline
  299. fit. If the errors in the y values have standard-deviation given by the
  300. vector d, then w should be 1/d. Default is ones(len(x)).
  301. xb, xe : float, optional
  302. The interval to fit. If None, these default to x[0] and x[-1]
  303. respectively.
  304. k : int, optional
  305. The order of the spline fit. It is recommended to use cubic splines.
  306. Even order splines should be avoided especially with small s values.
  307. 1 <= k <= 5
  308. task : {1, 0, -1}, optional
  309. If task==0 find t and c for a given smoothing factor, s.
  310. If task==1 find t and c for another value of the smoothing factor, s.
  311. There must have been a previous call with task=0 or task=1 for the same
  312. set of data (t will be stored an used internally)
  313. If task=-1 find the weighted least square spline for a given set of
  314. knots, t. These should be interior knots as knots on the ends will be
  315. added automatically.
  316. s : float, optional
  317. A smoothing condition. The amount of smoothness is determined by
  318. satisfying the conditions: sum((w * (y - g))**2,axis=0) <= s where g(x)
  319. is the smoothed interpolation of (x,y). The user can use s to control
  320. the tradeoff between closeness and smoothness of fit. Larger s means
  321. more smoothing while smaller values of s indicate less smoothing.
  322. Recommended values of s depend on the weights, w. If the weights
  323. represent the inverse of the standard-deviation of y, then a good s
  324. value should be found in the range (m-sqrt(2*m),m+sqrt(2*m)) where m is
  325. the number of datapoints in x, y, and w. default : s=m-sqrt(2*m) if
  326. weights are supplied. s = 0.0 (interpolating) if no weights are
  327. supplied.
  328. t : array_like, optional
  329. The knots needed for task=-1. If given then task is automatically set
  330. to -1.
  331. full_output : bool, optional
  332. If non-zero, then return optional outputs.
  333. per : bool, optional
  334. If non-zero, data points are considered periodic with period x[m-1] -
  335. x[0] and a smooth periodic spline approximation is returned. Values of
  336. y[m-1] and w[m-1] are not used.
  337. quiet : bool, optional
  338. Non-zero to suppress messages.
  339. This parameter is deprecated; use standard Python warning filters
  340. instead.
  341. Returns
  342. -------
  343. tck : tuple
  344. (t,c,k) a tuple containing the vector of knots, the B-spline
  345. coefficients, and the degree of the spline.
  346. fp : array, optional
  347. The weighted sum of squared residuals of the spline approximation.
  348. ier : int, optional
  349. An integer flag about splrep success. Success is indicated if ier<=0.
  350. If ier in [1,2,3] an error occurred but was not raised. Otherwise an
  351. error is raised.
  352. msg : str, optional
  353. A message corresponding to the integer flag, ier.
  354. Notes
  355. -----
  356. See splev for evaluation of the spline and its derivatives.
  357. The user is responsible for assuring that the values of *x* are unique.
  358. Otherwise, *splrep* will not return sensible results.
  359. See Also
  360. --------
  361. UnivariateSpline, BivariateSpline
  362. splprep, splev, sproot, spalde, splint
  363. bisplrep, bisplev
  364. Notes
  365. -----
  366. See splev for evaluation of the spline and its derivatives. Uses the
  367. FORTRAN routine curfit from FITPACK.
  368. If provided, knots `t` must satisfy the Schoenberg-Whitney conditions,
  369. i.e., there must be a subset of data points ``x[j]`` such that
  370. ``t[j] < x[j] < t[j+k+1]``, for ``j=0, 1,...,n-k-2``.
  371. References
  372. ----------
  373. Based on algorithms described in [1]_, [2]_, [3]_, and [4]_:
  374. .. [1] P. Dierckx, "An algorithm for smoothing, differentiation and
  375. integration of experimental data using spline functions",
  376. J.Comp.Appl.Maths 1 (1975) 165-184.
  377. .. [2] P. Dierckx, "A fast algorithm for smoothing data on a rectangular
  378. grid while using spline functions", SIAM J.Numer.Anal. 19 (1982)
  379. 1286-1304.
  380. .. [3] P. Dierckx, "An improved algorithm for curve fitting with spline
  381. functions", report tw54, Dept. Computer Science,K.U. Leuven, 1981.
  382. .. [4] P. Dierckx, "Curve and surface fitting with splines", Monographs on
  383. Numerical Analysis, Oxford University Press, 1993.
  384. Examples
  385. --------
  386. >>> import matplotlib.pyplot as plt
  387. >>> from scipy.interpolate import splev, splrep
  388. >>> x = np.linspace(0, 10, 10)
  389. >>> y = np.sin(x)
  390. >>> tck = splrep(x, y)
  391. >>> x2 = np.linspace(0, 10, 200)
  392. >>> y2 = splev(x2, tck)
  393. >>> plt.plot(x, y, 'o', x2, y2)
  394. >>> plt.show()
  395. """
  396. if task <= 0:
  397. _curfit_cache = {}
  398. x, y = map(atleast_1d, [x, y])
  399. m = len(x)
  400. if w is None:
  401. w = ones(m, float)
  402. if s is None:
  403. s = 0.0
  404. else:
  405. w = atleast_1d(w)
  406. if s is None:
  407. s = m - sqrt(2*m)
  408. if not len(w) == m:
  409. raise TypeError('len(w)=%d is not equal to m=%d' % (len(w), m))
  410. if (m != len(y)) or (m != len(w)):
  411. raise TypeError('Lengths of the first three arguments (x,y,w) must '
  412. 'be equal')
  413. if not (1 <= k <= 5):
  414. raise TypeError('Given degree of the spline (k=%d) is not supported. '
  415. '(1<=k<=5)' % k)
  416. if m <= k:
  417. raise TypeError('m > k must hold')
  418. if xb is None:
  419. xb = x[0]
  420. if xe is None:
  421. xe = x[-1]
  422. if not (-1 <= task <= 1):
  423. raise TypeError('task must be -1, 0 or 1')
  424. if t is not None:
  425. task = -1
  426. if task == -1:
  427. if t is None:
  428. raise TypeError('Knots must be given for task=-1')
  429. numknots = len(t)
  430. _curfit_cache['t'] = empty((numknots + 2*k + 2,), float)
  431. _curfit_cache['t'][k+1:-k-1] = t
  432. nest = len(_curfit_cache['t'])
  433. elif task == 0:
  434. if per:
  435. nest = max(m + 2*k, 2*k + 3)
  436. else:
  437. nest = max(m + k + 1, 2*k + 3)
  438. t = empty((nest,), float)
  439. _curfit_cache['t'] = t
  440. if task <= 0:
  441. if per:
  442. _curfit_cache['wrk'] = empty((m*(k + 1) + nest*(8 + 5*k),), float)
  443. else:
  444. _curfit_cache['wrk'] = empty((m*(k + 1) + nest*(7 + 3*k),), float)
  445. _curfit_cache['iwrk'] = empty((nest,), intc)
  446. try:
  447. t = _curfit_cache['t']
  448. wrk = _curfit_cache['wrk']
  449. iwrk = _curfit_cache['iwrk']
  450. except KeyError:
  451. raise TypeError("must call with task=1 only after"
  452. " call with task=0,-1")
  453. if not per:
  454. n, c, fp, ier = dfitpack.curfit(task, x, y, w, t, wrk, iwrk,
  455. xb, xe, k, s)
  456. else:
  457. n, c, fp, ier = dfitpack.percur(task, x, y, w, t, wrk, iwrk, k, s)
  458. tck = (t[:n], c[:n], k)
  459. if ier <= 0 and not quiet:
  460. _mess = (_iermess[ier][0] + "\tk=%d n=%d m=%d fp=%f s=%f" %
  461. (k, len(t), m, fp, s))
  462. warnings.warn(RuntimeWarning(_mess))
  463. if ier > 0 and not full_output:
  464. if ier in [1, 2, 3]:
  465. warnings.warn(RuntimeWarning(_iermess[ier][0]))
  466. else:
  467. try:
  468. raise _iermess[ier][1](_iermess[ier][0])
  469. except KeyError:
  470. raise _iermess['unknown'][1](_iermess['unknown'][0])
  471. if full_output:
  472. try:
  473. return tck, fp, ier, _iermess[ier][0]
  474. except KeyError:
  475. return tck, fp, ier, _iermess['unknown'][0]
  476. else:
  477. return tck
  478. def splev(x, tck, der=0, ext=0):
  479. """
  480. Evaluate a B-spline or its derivatives.
  481. Given the knots and coefficients of a B-spline representation, evaluate
  482. the value of the smoothing polynomial and its derivatives. This is a
  483. wrapper around the FORTRAN routines splev and splder of FITPACK.
  484. Parameters
  485. ----------
  486. x : array_like
  487. An array of points at which to return the value of the smoothed
  488. spline or its derivatives. If `tck` was returned from `splprep`,
  489. then the parameter values, u should be given.
  490. tck : tuple
  491. A sequence of length 3 returned by `splrep` or `splprep` containing
  492. the knots, coefficients, and degree of the spline.
  493. der : int, optional
  494. The order of derivative of the spline to compute (must be less than
  495. or equal to k).
  496. ext : int, optional
  497. Controls the value returned for elements of ``x`` not in the
  498. interval defined by the knot sequence.
  499. * if ext=0, return the extrapolated value.
  500. * if ext=1, return 0
  501. * if ext=2, raise a ValueError
  502. * if ext=3, return the boundary value.
  503. The default value is 0.
  504. Returns
  505. -------
  506. y : ndarray or list of ndarrays
  507. An array of values representing the spline function evaluated at
  508. the points in ``x``. If `tck` was returned from `splprep`, then this
  509. is a list of arrays representing the curve in N-dimensional space.
  510. See Also
  511. --------
  512. splprep, splrep, sproot, spalde, splint
  513. bisplrep, bisplev
  514. References
  515. ----------
  516. .. [1] C. de Boor, "On calculating with b-splines", J. Approximation
  517. Theory, 6, p.50-62, 1972.
  518. .. [2] M.G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths
  519. Applics, 10, p.134-149, 1972.
  520. .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs
  521. on Numerical Analysis, Oxford University Press, 1993.
  522. """
  523. t, c, k = tck
  524. try:
  525. c[0][0]
  526. parametric = True
  527. except Exception:
  528. parametric = False
  529. if parametric:
  530. return list(map(lambda c, x=x, t=t, k=k, der=der:
  531. splev(x, [t, c, k], der, ext), c))
  532. else:
  533. if not (0 <= der <= k):
  534. raise ValueError("0<=der=%d<=k=%d must hold" % (der, k))
  535. if ext not in (0, 1, 2, 3):
  536. raise ValueError("ext = %s not in (0, 1, 2, 3) " % ext)
  537. x = asarray(x)
  538. shape = x.shape
  539. x = atleast_1d(x).ravel()
  540. y, ier = _fitpack._spl_(x, der, t, c, k, ext)
  541. if ier == 10:
  542. raise ValueError("Invalid input data")
  543. if ier == 1:
  544. raise ValueError("Found x value not in the domain")
  545. if ier:
  546. raise TypeError("An error occurred")
  547. return y.reshape(shape)
  548. def splint(a, b, tck, full_output=0):
  549. """
  550. Evaluate the definite integral of a B-spline.
  551. Given the knots and coefficients of a B-spline, evaluate the definite
  552. integral of the smoothing polynomial between two given points.
  553. Parameters
  554. ----------
  555. a, b : float
  556. The end-points of the integration interval.
  557. tck : tuple
  558. A tuple (t,c,k) containing the vector of knots, the B-spline
  559. coefficients, and the degree of the spline (see `splev`).
  560. full_output : int, optional
  561. Non-zero to return optional output.
  562. Returns
  563. -------
  564. integral : float
  565. The resulting integral.
  566. wrk : ndarray
  567. An array containing the integrals of the normalized B-splines
  568. defined on the set of knots.
  569. Notes
  570. -----
  571. splint silently assumes that the spline function is zero outside the data
  572. interval (a, b).
  573. See Also
  574. --------
  575. splprep, splrep, sproot, spalde, splev
  576. bisplrep, bisplev
  577. UnivariateSpline, BivariateSpline
  578. References
  579. ----------
  580. .. [1] P.W. Gaffney, The calculation of indefinite integrals of b-splines",
  581. J. Inst. Maths Applics, 17, p.37-41, 1976.
  582. .. [2] P. Dierckx, "Curve and surface fitting with splines", Monographs
  583. on Numerical Analysis, Oxford University Press, 1993.
  584. """
  585. t, c, k = tck
  586. try:
  587. c[0][0]
  588. parametric = True
  589. except Exception:
  590. parametric = False
  591. if parametric:
  592. return list(map(lambda c, a=a, b=b, t=t, k=k:
  593. splint(a, b, [t, c, k]), c))
  594. else:
  595. aint, wrk = _fitpack._splint(t, c, k, a, b)
  596. if full_output:
  597. return aint, wrk
  598. else:
  599. return aint
  600. def sproot(tck, mest=10):
  601. """
  602. Find the roots of a cubic B-spline.
  603. Given the knots (>=8) and coefficients of a cubic B-spline return the
  604. roots of the spline.
  605. Parameters
  606. ----------
  607. tck : tuple
  608. A tuple (t,c,k) containing the vector of knots,
  609. the B-spline coefficients, and the degree of the spline.
  610. The number of knots must be >= 8, and the degree must be 3.
  611. The knots must be a montonically increasing sequence.
  612. mest : int, optional
  613. An estimate of the number of zeros (Default is 10).
  614. Returns
  615. -------
  616. zeros : ndarray
  617. An array giving the roots of the spline.
  618. See also
  619. --------
  620. splprep, splrep, splint, spalde, splev
  621. bisplrep, bisplev
  622. UnivariateSpline, BivariateSpline
  623. References
  624. ----------
  625. .. [1] C. de Boor, "On calculating with b-splines", J. Approximation
  626. Theory, 6, p.50-62, 1972.
  627. .. [2] M.G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths
  628. Applics, 10, p.134-149, 1972.
  629. .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs
  630. on Numerical Analysis, Oxford University Press, 1993.
  631. """
  632. t, c, k = tck
  633. if k != 3:
  634. raise ValueError("sproot works only for cubic (k=3) splines")
  635. try:
  636. c[0][0]
  637. parametric = True
  638. except Exception:
  639. parametric = False
  640. if parametric:
  641. return list(map(lambda c, t=t, k=k, mest=mest:
  642. sproot([t, c, k], mest), c))
  643. else:
  644. if len(t) < 8:
  645. raise TypeError("The number of knots %d>=8" % len(t))
  646. z, ier = _fitpack._sproot(t, c, k, mest)
  647. if ier == 10:
  648. raise TypeError("Invalid input data. "
  649. "t1<=..<=t4<t5<..<tn-3<=..<=tn must hold.")
  650. if ier == 0:
  651. return z
  652. if ier == 1:
  653. warnings.warn(RuntimeWarning("The number of zeros exceeds mest"))
  654. return z
  655. raise TypeError("Unknown error")
  656. def spalde(x, tck):
  657. """
  658. Evaluate all derivatives of a B-spline.
  659. Given the knots and coefficients of a cubic B-spline compute all
  660. derivatives up to order k at a point (or set of points).
  661. Parameters
  662. ----------
  663. x : array_like
  664. A point or a set of points at which to evaluate the derivatives.
  665. Note that ``t(k) <= x <= t(n-k+1)`` must hold for each `x`.
  666. tck : tuple
  667. A tuple (t,c,k) containing the vector of knots,
  668. the B-spline coefficients, and the degree of the spline.
  669. Returns
  670. -------
  671. results : {ndarray, list of ndarrays}
  672. An array (or a list of arrays) containing all derivatives
  673. up to order k inclusive for each point `x`.
  674. See Also
  675. --------
  676. splprep, splrep, splint, sproot, splev, bisplrep, bisplev,
  677. UnivariateSpline, BivariateSpline
  678. References
  679. ----------
  680. .. [1] de Boor C : On calculating with b-splines, J. Approximation Theory
  681. 6 (1972) 50-62.
  682. .. [2] Cox M.G. : The numerical evaluation of b-splines, J. Inst. Maths
  683. applics 10 (1972) 134-149.
  684. .. [3] Dierckx P. : Curve and surface fitting with splines, Monographs on
  685. Numerical Analysis, Oxford University Press, 1993.
  686. """
  687. t, c, k = tck
  688. try:
  689. c[0][0]
  690. parametric = True
  691. except Exception:
  692. parametric = False
  693. if parametric:
  694. return list(map(lambda c, x=x, t=t, k=k:
  695. spalde(x, [t, c, k]), c))
  696. else:
  697. x = atleast_1d(x)
  698. if len(x) > 1:
  699. return list(map(lambda x, tck=tck: spalde(x, tck), x))
  700. d, ier = _fitpack._spalde(t, c, k, x[0])
  701. if ier == 0:
  702. return d
  703. if ier == 10:
  704. raise TypeError("Invalid input data. t(k)<=x<=t(n-k+1) must hold.")
  705. raise TypeError("Unknown error")
  706. # def _curfit(x,y,w=None,xb=None,xe=None,k=3,task=0,s=None,t=None,
  707. # full_output=0,nest=None,per=0,quiet=1):
  708. _surfit_cache = {'tx': array([], float), 'ty': array([], float),
  709. 'wrk': array([], float), 'iwrk': array([], intc)}
  710. def bisplrep(x, y, z, w=None, xb=None, xe=None, yb=None, ye=None,
  711. kx=3, ky=3, task=0, s=None, eps=1e-16, tx=None, ty=None,
  712. full_output=0, nxest=None, nyest=None, quiet=1):
  713. """
  714. Find a bivariate B-spline representation of a surface.
  715. Given a set of data points (x[i], y[i], z[i]) representing a surface
  716. z=f(x,y), compute a B-spline representation of the surface. Based on
  717. the routine SURFIT from FITPACK.
  718. Parameters
  719. ----------
  720. x, y, z : ndarray
  721. Rank-1 arrays of data points.
  722. w : ndarray, optional
  723. Rank-1 array of weights. By default ``w=np.ones(len(x))``.
  724. xb, xe : float, optional
  725. End points of approximation interval in `x`.
  726. By default ``xb = x.min(), xe=x.max()``.
  727. yb, ye : float, optional
  728. End points of approximation interval in `y`.
  729. By default ``yb=y.min(), ye = y.max()``.
  730. kx, ky : int, optional
  731. The degrees of the spline (1 <= kx, ky <= 5).
  732. Third order (kx=ky=3) is recommended.
  733. task : int, optional
  734. If task=0, find knots in x and y and coefficients for a given
  735. smoothing factor, s.
  736. If task=1, find knots and coefficients for another value of the
  737. smoothing factor, s. bisplrep must have been previously called
  738. with task=0 or task=1.
  739. If task=-1, find coefficients for a given set of knots tx, ty.
  740. s : float, optional
  741. A non-negative smoothing factor. If weights correspond
  742. to the inverse of the standard-deviation of the errors in z,
  743. then a good s-value should be found in the range
  744. ``(m-sqrt(2*m),m+sqrt(2*m))`` where m=len(x).
  745. eps : float, optional
  746. A threshold for determining the effective rank of an
  747. over-determined linear system of equations (0 < eps < 1).
  748. `eps` is not likely to need changing.
  749. tx, ty : ndarray, optional
  750. Rank-1 arrays of the knots of the spline for task=-1
  751. full_output : int, optional
  752. Non-zero to return optional outputs.
  753. nxest, nyest : int, optional
  754. Over-estimates of the total number of knots. If None then
  755. ``nxest = max(kx+sqrt(m/2),2*kx+3)``,
  756. ``nyest = max(ky+sqrt(m/2),2*ky+3)``.
  757. quiet : int, optional
  758. Non-zero to suppress printing of messages.
  759. This parameter is deprecated; use standard Python warning filters
  760. instead.
  761. Returns
  762. -------
  763. tck : array_like
  764. A list [tx, ty, c, kx, ky] containing the knots (tx, ty) and
  765. coefficients (c) of the bivariate B-spline representation of the
  766. surface along with the degree of the spline.
  767. fp : ndarray
  768. The weighted sum of squared residuals of the spline approximation.
  769. ier : int
  770. An integer flag about splrep success. Success is indicated if
  771. ier<=0. If ier in [1,2,3] an error occurred but was not raised.
  772. Otherwise an error is raised.
  773. msg : str
  774. A message corresponding to the integer flag, ier.
  775. See Also
  776. --------
  777. splprep, splrep, splint, sproot, splev
  778. UnivariateSpline, BivariateSpline
  779. Notes
  780. -----
  781. See `bisplev` to evaluate the value of the B-spline given its tck
  782. representation.
  783. References
  784. ----------
  785. .. [1] Dierckx P.:An algorithm for surface fitting with spline functions
  786. Ima J. Numer. Anal. 1 (1981) 267-283.
  787. .. [2] Dierckx P.:An algorithm for surface fitting with spline functions
  788. report tw50, Dept. Computer Science,K.U.Leuven, 1980.
  789. .. [3] Dierckx P.:Curve and surface fitting with splines, Monographs on
  790. Numerical Analysis, Oxford University Press, 1993.
  791. """
  792. x, y, z = map(ravel, [x, y, z]) # ensure 1-d arrays.
  793. m = len(x)
  794. if not (m == len(y) == len(z)):
  795. raise TypeError('len(x)==len(y)==len(z) must hold.')
  796. if w is None:
  797. w = ones(m, float)
  798. else:
  799. w = atleast_1d(w)
  800. if not len(w) == m:
  801. raise TypeError('len(w)=%d is not equal to m=%d' % (len(w), m))
  802. if xb is None:
  803. xb = x.min()
  804. if xe is None:
  805. xe = x.max()
  806. if yb is None:
  807. yb = y.min()
  808. if ye is None:
  809. ye = y.max()
  810. if not (-1 <= task <= 1):
  811. raise TypeError('task must be -1, 0 or 1')
  812. if s is None:
  813. s = m - sqrt(2*m)
  814. if tx is None and task == -1:
  815. raise TypeError('Knots_x must be given for task=-1')
  816. if tx is not None:
  817. _surfit_cache['tx'] = atleast_1d(tx)
  818. nx = len(_surfit_cache['tx'])
  819. if ty is None and task == -1:
  820. raise TypeError('Knots_y must be given for task=-1')
  821. if ty is not None:
  822. _surfit_cache['ty'] = atleast_1d(ty)
  823. ny = len(_surfit_cache['ty'])
  824. if task == -1 and nx < 2*kx+2:
  825. raise TypeError('There must be at least 2*kx+2 knots_x for task=-1')
  826. if task == -1 and ny < 2*ky+2:
  827. raise TypeError('There must be at least 2*ky+2 knots_x for task=-1')
  828. if not ((1 <= kx <= 5) and (1 <= ky <= 5)):
  829. raise TypeError('Given degree of the spline (kx,ky=%d,%d) is not '
  830. 'supported. (1<=k<=5)' % (kx, ky))
  831. if m < (kx + 1)*(ky + 1):
  832. raise TypeError('m >= (kx+1)(ky+1) must hold')
  833. if nxest is None:
  834. nxest = int(kx + sqrt(m/2))
  835. if nyest is None:
  836. nyest = int(ky + sqrt(m/2))
  837. nxest, nyest = max(nxest, 2*kx + 3), max(nyest, 2*ky + 3)
  838. if task >= 0 and s == 0:
  839. nxest = int(kx + sqrt(3*m))
  840. nyest = int(ky + sqrt(3*m))
  841. if task == -1:
  842. _surfit_cache['tx'] = atleast_1d(tx)
  843. _surfit_cache['ty'] = atleast_1d(ty)
  844. tx, ty = _surfit_cache['tx'], _surfit_cache['ty']
  845. wrk = _surfit_cache['wrk']
  846. u = nxest - kx - 1
  847. v = nyest - ky - 1
  848. km = max(kx, ky) + 1
  849. ne = max(nxest, nyest)
  850. bx, by = kx*v + ky + 1, ky*u + kx + 1
  851. b1, b2 = bx, bx + v - ky
  852. if bx > by:
  853. b1, b2 = by, by + u - kx
  854. msg = "Too many data points to interpolate"
  855. lwrk1 = _intc_overflow(u*v*(2 + b1 + b2) +
  856. 2*(u + v + km*(m + ne) + ne - kx - ky) + b2 + 1,
  857. msg=msg)
  858. lwrk2 = _intc_overflow(u*v*(b2 + 1) + b2, msg=msg)
  859. tx, ty, c, o = _fitpack._surfit(x, y, z, w, xb, xe, yb, ye, kx, ky,
  860. task, s, eps, tx, ty, nxest, nyest,
  861. wrk, lwrk1, lwrk2)
  862. _curfit_cache['tx'] = tx
  863. _curfit_cache['ty'] = ty
  864. _curfit_cache['wrk'] = o['wrk']
  865. ier, fp = o['ier'], o['fp']
  866. tck = [tx, ty, c, kx, ky]
  867. ierm = min(11, max(-3, ier))
  868. if ierm <= 0 and not quiet:
  869. _mess = (_iermess2[ierm][0] +
  870. "\tkx,ky=%d,%d nx,ny=%d,%d m=%d fp=%f s=%f" %
  871. (kx, ky, len(tx), len(ty), m, fp, s))
  872. warnings.warn(RuntimeWarning(_mess))
  873. if ierm > 0 and not full_output:
  874. if ier in [1, 2, 3, 4, 5]:
  875. _mess = ("\n\tkx,ky=%d,%d nx,ny=%d,%d m=%d fp=%f s=%f" %
  876. (kx, ky, len(tx), len(ty), m, fp, s))
  877. warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess))
  878. else:
  879. try:
  880. raise _iermess2[ierm][1](_iermess2[ierm][0])
  881. except KeyError:
  882. raise _iermess2['unknown'][1](_iermess2['unknown'][0])
  883. if full_output:
  884. try:
  885. return tck, fp, ier, _iermess2[ierm][0]
  886. except KeyError:
  887. return tck, fp, ier, _iermess2['unknown'][0]
  888. else:
  889. return tck
  890. def bisplev(x, y, tck, dx=0, dy=0):
  891. """
  892. Evaluate a bivariate B-spline and its derivatives.
  893. Return a rank-2 array of spline function values (or spline derivative
  894. values) at points given by the cross-product of the rank-1 arrays `x` and
  895. `y`. In special cases, return an array or just a float if either `x` or
  896. `y` or both are floats. Based on BISPEV from FITPACK.
  897. Parameters
  898. ----------
  899. x, y : ndarray
  900. Rank-1 arrays specifying the domain over which to evaluate the
  901. spline or its derivative.
  902. tck : tuple
  903. A sequence of length 5 returned by `bisplrep` containing the knot
  904. locations, the coefficients, and the degree of the spline:
  905. [tx, ty, c, kx, ky].
  906. dx, dy : int, optional
  907. The orders of the partial derivatives in `x` and `y` respectively.
  908. Returns
  909. -------
  910. vals : ndarray
  911. The B-spline or its derivative evaluated over the set formed by
  912. the cross-product of `x` and `y`.
  913. See Also
  914. --------
  915. splprep, splrep, splint, sproot, splev
  916. UnivariateSpline, BivariateSpline
  917. Notes
  918. -----
  919. See `bisplrep` to generate the `tck` representation.
  920. References
  921. ----------
  922. .. [1] Dierckx P. : An algorithm for surface fitting
  923. with spline functions
  924. Ima J. Numer. Anal. 1 (1981) 267-283.
  925. .. [2] Dierckx P. : An algorithm for surface fitting
  926. with spline functions
  927. report tw50, Dept. Computer Science,K.U.Leuven, 1980.
  928. .. [3] Dierckx P. : Curve and surface fitting with splines,
  929. Monographs on Numerical Analysis, Oxford University Press, 1993.
  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:
  1088. raise ValueError(("The spline has internal repeated knots "
  1089. "and is not differentiable %d times") % n)
  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