Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/interpolate/_fitpack_impl.py: 6%

413 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-12 06:31 +0000

1""" 

2fitpack (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 

6See 

7 https://web.archive.org/web/20010524124604/http://www.cs.kuleuven.ac.be:80/cwis/research/nalag/research/topics/fitpack.html 

8or 

9 http://www.netlib.org/dierckx/ 

10 

11Copyright 2002 Pearu Peterson all rights reserved, 

12Pearu Peterson <pearu@cens.ioc.ee> 

13Permission to use, modify, and distribute this software is given under the 

14terms of the SciPy (BSD style) license. See LICENSE.txt that came with 

15this distribution for specifics. 

16 

17NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. 

18 

19TODO: Make interfaces to the following fitpack functions: 

20 For univariate splines: cocosp, concon, fourco, insert 

21 For bivariate splines: profil, regrid, parsur, surev 

22""" 

23 

24__all__ = ['splrep', 'splprep', 'splev', 'splint', 'sproot', 'spalde', 

25 'bisplrep', 'bisplev', 'insert', 'splder', 'splantider'] 

26 

27import warnings 

28import numpy as np 

29from . import _fitpack 

30from numpy import (atleast_1d, array, ones, zeros, sqrt, ravel, transpose, 

31 empty, iinfo, asarray) 

32 

33# Try to replace _fitpack interface with 

34# f2py-generated version 

35from . import dfitpack 

36 

37 

38dfitpack_int = dfitpack.types.intvar.dtype 

39 

40 

41def _int_overflow(x, msg=None): 

42 """Cast the value to an dfitpack_int and raise an OverflowError if the value 

43 cannot fit. 

44 """ 

45 if x > iinfo(dfitpack_int).max: 

46 if msg is None: 

47 msg = '%r cannot fit into an %r' % (x, dfitpack_int) 

48 raise OverflowError(msg) 

49 return dfitpack_int.type(x) 

50 

51 

52_iermess = { 

53 0: ["The spline has a residual sum of squares fp such that " 

54 "abs(fp-s)/s<=0.001", None], 

55 -1: ["The spline is an interpolating spline (fp=0)", None], 

56 -2: ["The spline is weighted least-squares polynomial of degree k.\n" 

57 "fp gives the upper bound fp0 for the smoothing factor s", None], 

58 1: ["The required storage space exceeds the available storage space.\n" 

59 "Probable causes: data (x,y) size is too small or smoothing parameter" 

60 "\ns is too small (fp>s).", ValueError], 

61 2: ["A theoretically impossible result when finding a smoothing spline\n" 

62 "with fp = s. Probable cause: s too small. (abs(fp-s)/s>0.001)", 

63 ValueError], 

64 3: ["The maximal number of iterations (20) allowed for finding smoothing\n" 

65 "spline with fp=s has been reached. Probable cause: s too small.\n" 

66 "(abs(fp-s)/s>0.001)", ValueError], 

67 10: ["Error on input data", ValueError], 

68 'unknown': ["An error occurred", TypeError] 

69} 

70 

71_iermess2 = { 

72 0: ["The spline has a residual sum of squares fp such that " 

73 "abs(fp-s)/s<=0.001", None], 

74 -1: ["The spline is an interpolating spline (fp=0)", None], 

75 -2: ["The spline is weighted least-squares polynomial of degree kx and ky." 

76 "\nfp gives the upper bound fp0 for the smoothing factor s", None], 

77 -3: ["Warning. The coefficients of the spline have been computed as the\n" 

78 "minimal norm least-squares solution of a rank deficient system.", 

79 None], 

80 1: ["The required storage space exceeds the available storage space.\n" 

81 "Probable causes: nxest or nyest too small or s is too small. (fp>s)", 

82 ValueError], 

83 2: ["A theoretically impossible result when finding a smoothing spline\n" 

84 "with fp = s. Probable causes: s too small or badly chosen eps.\n" 

85 "(abs(fp-s)/s>0.001)", ValueError], 

86 3: ["The maximal number of iterations (20) allowed for finding smoothing\n" 

87 "spline with fp=s has been reached. Probable cause: s too small.\n" 

88 "(abs(fp-s)/s>0.001)", ValueError], 

89 4: ["No more knots can be added because the number of B-spline\n" 

90 "coefficients already exceeds the number of data points m.\n" 

91 "Probable causes: either s or m too small. (fp>s)", ValueError], 

92 5: ["No more knots can be added because the additional knot would\n" 

93 "coincide with an old one. Probable cause: s too small or too large\n" 

94 "a weight to an inaccurate data point. (fp>s)", ValueError], 

95 10: ["Error on input data", ValueError], 

96 11: ["rwrk2 too small, i.e., there is not enough workspace for computing\n" 

97 "the minimal least-squares solution of a rank deficient system of\n" 

98 "linear equations.", ValueError], 

99 'unknown': ["An error occurred", TypeError] 

100} 

101 

102_parcur_cache = {'t': array([], float), 'wrk': array([], float), 

103 'iwrk': array([], dfitpack_int), 'u': array([], float), 

104 'ub': 0, 'ue': 1} 

105 

106 

107def splprep(x, w=None, u=None, ub=None, ue=None, k=3, task=0, s=None, t=None, 

108 full_output=0, nest=None, per=0, quiet=1): 

109 """ 

110 Find the B-spline representation of an N-D curve. 

111 

112 Given a list of N rank-1 arrays, `x`, which represent a curve in 

113 N-dimensional space parametrized by `u`, find a smooth approximating 

114 spline curve g(`u`). Uses the FORTRAN routine parcur from FITPACK. 

115 

116 Parameters 

117 ---------- 

118 x : array_like 

119 A list of sample vector arrays representing the curve. 

120 w : array_like, optional 

121 Strictly positive rank-1 array of weights the same length as `x[0]`. 

122 The weights are used in computing the weighted least-squares spline 

123 fit. If the errors in the `x` values have standard-deviation given by 

124 the vector d, then `w` should be 1/d. Default is ``ones(len(x[0]))``. 

125 u : array_like, optional 

126 An array of parameter values. If not given, these values are 

127 calculated automatically as ``M = len(x[0])``, where 

128 

129 v[0] = 0 

130 

131 v[i] = v[i-1] + distance(`x[i]`, `x[i-1]`) 

132 

133 u[i] = v[i] / v[M-1] 

134 

135 ub, ue : int, optional 

136 The end-points of the parameters interval. Defaults to 

137 u[0] and u[-1]. 

138 k : int, optional 

139 Degree of the spline. Cubic splines are recommended. 

140 Even values of `k` should be avoided especially with a small s-value. 

141 ``1 <= k <= 5``, default is 3. 

142 task : int, optional 

143 If task==0 (default), find t and c for a given smoothing factor, s. 

144 If task==1, find t and c for another value of the smoothing factor, s. 

145 There must have been a previous call with task=0 or task=1 

146 for the same set of data. 

147 If task=-1 find the weighted least square spline for a given set of 

148 knots, t. 

149 s : float, optional 

150 A smoothing condition. The amount of smoothness is determined by 

151 satisfying the conditions: ``sum((w * (y - g))**2,axis=0) <= s``, 

152 where g(x) is the smoothed interpolation of (x,y). The user can 

153 use `s` to control the trade-off between closeness and smoothness 

154 of fit. Larger `s` means more smoothing while smaller values of `s` 

155 indicate less smoothing. Recommended values of `s` depend on the 

156 weights, w. If the weights represent the inverse of the 

157 standard-deviation of y, then a good `s` value should be found in 

158 the range ``(m-sqrt(2*m),m+sqrt(2*m))``, where m is the number of 

159 data points in x, y, and w. 

160 t : int, optional 

161 The knots needed for task=-1. 

162 full_output : int, optional 

163 If non-zero, then return optional outputs. 

164 nest : int, optional 

165 An over-estimate of the total number of knots of the spline to 

166 help in determining the storage space. By default nest=m/2. 

167 Always large enough is nest=m+k+1. 

168 per : int, optional 

169 If non-zero, data points are considered periodic with period 

170 ``x[m-1] - x[0]`` and a smooth periodic spline approximation is 

171 returned. Values of ``y[m-1]`` and ``w[m-1]`` are not used. 

172 quiet : int, optional 

173 Non-zero to suppress messages. 

174 

175 Returns 

176 ------- 

177 tck : tuple 

178 A tuple (t,c,k) containing the vector of knots, the B-spline 

179 coefficients, and the degree of the spline. 

180 u : array 

181 An array of the values of the parameter. 

182 fp : float 

183 The weighted sum of squared residuals of the spline approximation. 

184 ier : int 

185 An integer flag about splrep success. Success is indicated 

186 if ier<=0. If ier in [1,2,3] an error occurred but was not raised. 

187 Otherwise an error is raised. 

188 msg : str 

189 A message corresponding to the integer flag, ier. 

190 

191 See Also 

192 -------- 

193 splrep, splev, sproot, spalde, splint, 

194 bisplrep, bisplev 

195 UnivariateSpline, BivariateSpline 

196 

197 Notes 

198 ----- 

199 See `splev` for evaluation of the spline and its derivatives. 

200 The number of dimensions N must be smaller than 11. 

201 

202 References 

203 ---------- 

204 .. [1] P. Dierckx, "Algorithms for smoothing data with periodic and 

205 parametric splines, Computer Graphics and Image Processing", 

206 20 (1982) 171-184. 

207 .. [2] P. Dierckx, "Algorithms for smoothing data with periodic and 

208 parametric splines", report tw55, Dept. Computer Science, 

209 K.U.Leuven, 1981. 

210 .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs on 

211 Numerical Analysis, Oxford University Press, 1993. 

212 

213 """ 

214 if task <= 0: 

215 _parcur_cache = {'t': array([], float), 'wrk': array([], float), 

216 'iwrk': array([], dfitpack_int), 'u': array([], float), 

217 'ub': 0, 'ue': 1} 

218 x = atleast_1d(x) 

219 idim, m = x.shape 

220 if per: 

221 for i in range(idim): 

222 if x[i][0] != x[i][-1]: 

223 if not quiet: 

224 warnings.warn(RuntimeWarning('Setting x[%d][%d]=x[%d][0]' % 

225 (i, m, i))) 

226 x[i][-1] = x[i][0] 

227 if not 0 < idim < 11: 

228 raise TypeError('0 < idim < 11 must hold') 

229 if w is None: 

230 w = ones(m, float) 

231 else: 

232 w = atleast_1d(w) 

233 ipar = (u is not None) 

234 if ipar: 

235 _parcur_cache['u'] = u 

236 if ub is None: 

237 _parcur_cache['ub'] = u[0] 

238 else: 

239 _parcur_cache['ub'] = ub 

240 if ue is None: 

241 _parcur_cache['ue'] = u[-1] 

242 else: 

243 _parcur_cache['ue'] = ue 

244 else: 

245 _parcur_cache['u'] = zeros(m, float) 

246 if not (1 <= k <= 5): 

247 raise TypeError('1 <= k= %d <=5 must hold' % k) 

248 if not (-1 <= task <= 1): 

249 raise TypeError('task must be -1, 0 or 1') 

250 if (not len(w) == m) or (ipar == 1 and (not len(u) == m)): 

251 raise TypeError('Mismatch of input dimensions') 

252 if s is None: 

253 s = m - sqrt(2*m) 

254 if t is None and task == -1: 

255 raise TypeError('Knots must be given for task=-1') 

256 if t is not None: 

257 _parcur_cache['t'] = atleast_1d(t) 

258 n = len(_parcur_cache['t']) 

259 if task == -1 and n < 2*k + 2: 

260 raise TypeError('There must be at least 2*k+2 knots for task=-1') 

261 if m <= k: 

262 raise TypeError('m > k must hold') 

263 if nest is None: 

264 nest = m + 2*k 

265 

266 if (task >= 0 and s == 0) or (nest < 0): 

267 if per: 

268 nest = m + 2*k 

269 else: 

270 nest = m + k + 1 

271 nest = max(nest, 2*k + 3) 

272 u = _parcur_cache['u'] 

273 ub = _parcur_cache['ub'] 

274 ue = _parcur_cache['ue'] 

275 t = _parcur_cache['t'] 

276 wrk = _parcur_cache['wrk'] 

277 iwrk = _parcur_cache['iwrk'] 

278 t, c, o = _fitpack._parcur(ravel(transpose(x)), w, u, ub, ue, k, 

279 task, ipar, s, t, nest, wrk, iwrk, per) 

280 _parcur_cache['u'] = o['u'] 

281 _parcur_cache['ub'] = o['ub'] 

282 _parcur_cache['ue'] = o['ue'] 

283 _parcur_cache['t'] = t 

284 _parcur_cache['wrk'] = o['wrk'] 

285 _parcur_cache['iwrk'] = o['iwrk'] 

286 ier = o['ier'] 

287 fp = o['fp'] 

288 n = len(t) 

289 u = o['u'] 

290 c.shape = idim, n - k - 1 

291 tcku = [t, list(c), k], u 

292 if ier <= 0 and not quiet: 

293 warnings.warn(RuntimeWarning(_iermess[ier][0] + 

294 "\tk=%d n=%d m=%d fp=%f s=%f" % 

295 (k, len(t), m, fp, s))) 

296 if ier > 0 and not full_output: 

297 if ier in [1, 2, 3]: 

298 warnings.warn(RuntimeWarning(_iermess[ier][0])) 

299 else: 

300 try: 

301 raise _iermess[ier][1](_iermess[ier][0]) 

302 except KeyError as e: 

303 raise _iermess['unknown'][1](_iermess['unknown'][0]) from e 

304 if full_output: 

305 try: 

306 return tcku, fp, ier, _iermess[ier][0] 

307 except KeyError: 

308 return tcku, fp, ier, _iermess['unknown'][0] 

309 else: 

310 return tcku 

311 

312 

313_curfit_cache = {'t': array([], float), 'wrk': array([], float), 

314 'iwrk': array([], dfitpack_int)} 

315 

316 

317def splrep(x, y, w=None, xb=None, xe=None, k=3, task=0, s=None, t=None, 

318 full_output=0, per=0, quiet=1): 

319 """ 

320 Find the B-spline representation of 1-D curve. 

321 

322 Given the set of data points ``(x[i], y[i])`` determine a smooth spline 

323 approximation of degree k on the interval ``xb <= x <= xe``. 

324 

325 Parameters 

326 ---------- 

327 x, y : array_like 

328 The data points defining a curve y = f(x). 

329 w : array_like, optional 

330 Strictly positive rank-1 array of weights the same length as x and y. 

331 The weights are used in computing the weighted least-squares spline 

332 fit. If the errors in the y values have standard-deviation given by the 

333 vector d, then w should be 1/d. Default is ones(len(x)). 

334 xb, xe : float, optional 

335 The interval to fit. If None, these default to x[0] and x[-1] 

336 respectively. 

337 k : int, optional 

338 The order of the spline fit. It is recommended to use cubic splines. 

339 Even order splines should be avoided especially with small s values. 

340 1 <= k <= 5 

341 task : {1, 0, -1}, optional 

342 If task==0 find t and c for a given smoothing factor, s. 

343 

344 If task==1 find t and c for another value of the smoothing factor, s. 

345 There must have been a previous call with task=0 or task=1 for the same 

346 set of data (t will be stored an used internally) 

347 

348 If task=-1 find the weighted least square spline for a given set of 

349 knots, t. These should be interior knots as knots on the ends will be 

350 added automatically. 

351 s : float, optional 

352 A smoothing condition. The amount of smoothness is determined by 

353 satisfying the conditions: sum((w * (y - g))**2,axis=0) <= s, where g(x) 

354 is the smoothed interpolation of (x,y). The user can use s to control 

355 the tradeoff between closeness and smoothness of fit. Larger s means 

356 more smoothing while smaller values of s indicate less smoothing. 

357 Recommended values of s depend on the weights, w. If the weights 

358 represent the inverse of the standard-deviation of y, then a good s 

359 value should be found in the range (m-sqrt(2*m),m+sqrt(2*m)) where m is 

360 the number of datapoints in x, y, and w. default : s=m-sqrt(2*m) if 

361 weights are supplied. s = 0.0 (interpolating) if no weights are 

362 supplied. 

363 t : array_like, optional 

364 The knots needed for task=-1. If given then task is automatically set 

365 to -1. 

366 full_output : bool, optional 

367 If non-zero, then return optional outputs. 

368 per : bool, optional 

369 If non-zero, data points are considered periodic with period x[m-1] - 

370 x[0] and a smooth periodic spline approximation is returned. Values of 

371 y[m-1] and w[m-1] are not used. 

372 quiet : bool, optional 

373 Non-zero to suppress messages. 

374 

375 Returns 

376 ------- 

377 tck : tuple 

378 (t,c,k) a tuple containing the vector of knots, the B-spline 

379 coefficients, and the degree of the spline. 

380 fp : array, optional 

381 The weighted sum of squared residuals of the spline approximation. 

382 ier : int, optional 

383 An integer flag about splrep success. Success is indicated if ier<=0. 

384 If ier in [1,2,3] an error occurred but was not raised. Otherwise an 

385 error is raised. 

386 msg : str, optional 

387 A message corresponding to the integer flag, ier. 

388 

389 See Also 

390 -------- 

391 UnivariateSpline, BivariateSpline 

392 splprep, splev, sproot, spalde, splint 

393 bisplrep, bisplev 

394 

395 Notes 

396 ----- 

397 See splev for evaluation of the spline and its derivatives. Uses the 

398 FORTRAN routine curfit from FITPACK. 

399 

400 The user is responsible for assuring that the values of *x* are unique. 

401 Otherwise, *splrep* will not return sensible results. 

402 

403 If provided, knots `t` must satisfy the Schoenberg-Whitney conditions, 

404 i.e., there must be a subset of data points ``x[j]`` such that 

405 ``t[j] < x[j] < t[j+k+1]``, for ``j=0, 1,...,n-k-2``. 

406 

407 References 

408 ---------- 

409 Based on algorithms described in [1]_, [2]_, [3]_, and [4]_: 

410 

411 .. [1] P. Dierckx, "An algorithm for smoothing, differentiation and 

412 integration of experimental data using spline functions", 

413 J.Comp.Appl.Maths 1 (1975) 165-184. 

414 .. [2] P. Dierckx, "A fast algorithm for smoothing data on a rectangular 

415 grid while using spline functions", SIAM J.Numer.Anal. 19 (1982) 

416 1286-1304. 

417 .. [3] P. Dierckx, "An improved algorithm for curve fitting with spline 

418 functions", report tw54, Dept. Computer Science,K.U. Leuven, 1981. 

419 .. [4] P. Dierckx, "Curve and surface fitting with splines", Monographs on 

420 Numerical Analysis, Oxford University Press, 1993. 

421 

422 Examples 

423 -------- 

424 

425 >>> import matplotlib.pyplot as plt 

426 >>> from scipy.interpolate import splev, splrep 

427 >>> x = np.linspace(0, 10, 10) 

428 >>> y = np.sin(x) 

429 >>> tck = splrep(x, y) 

430 >>> x2 = np.linspace(0, 10, 200) 

431 >>> y2 = splev(x2, tck) 

432 >>> plt.plot(x, y, 'o', x2, y2) 

433 >>> plt.show() 

434 

435 """ 

436 if task <= 0: 

437 _curfit_cache = {} 

438 x, y = map(atleast_1d, [x, y]) 

439 m = len(x) 

440 if w is None: 

441 w = ones(m, float) 

442 if s is None: 

443 s = 0.0 

444 else: 

445 w = atleast_1d(w) 

446 if s is None: 

447 s = m - sqrt(2*m) 

448 if not len(w) == m: 

449 raise TypeError('len(w)=%d is not equal to m=%d' % (len(w), m)) 

450 if (m != len(y)) or (m != len(w)): 

451 raise TypeError('Lengths of the first three arguments (x,y,w) must ' 

452 'be equal') 

453 if not (1 <= k <= 5): 

454 raise TypeError('Given degree of the spline (k=%d) is not supported. ' 

455 '(1<=k<=5)' % k) 

456 if m <= k: 

457 raise TypeError('m > k must hold') 

458 if xb is None: 

459 xb = x[0] 

460 if xe is None: 

461 xe = x[-1] 

462 if not (-1 <= task <= 1): 

463 raise TypeError('task must be -1, 0 or 1') 

464 if t is not None: 

465 task = -1 

466 if task == -1: 

467 if t is None: 

468 raise TypeError('Knots must be given for task=-1') 

469 numknots = len(t) 

470 _curfit_cache['t'] = empty((numknots + 2*k + 2,), float) 

471 _curfit_cache['t'][k+1:-k-1] = t 

472 nest = len(_curfit_cache['t']) 

473 elif task == 0: 

474 if per: 

475 nest = max(m + 2*k, 2*k + 3) 

476 else: 

477 nest = max(m + k + 1, 2*k + 3) 

478 t = empty((nest,), float) 

479 _curfit_cache['t'] = t 

480 if task <= 0: 

481 if per: 

482 _curfit_cache['wrk'] = empty((m*(k + 1) + nest*(8 + 5*k),), float) 

483 else: 

484 _curfit_cache['wrk'] = empty((m*(k + 1) + nest*(7 + 3*k),), float) 

485 _curfit_cache['iwrk'] = empty((nest,), dfitpack_int) 

486 try: 

487 t = _curfit_cache['t'] 

488 wrk = _curfit_cache['wrk'] 

489 iwrk = _curfit_cache['iwrk'] 

490 except KeyError as e: 

491 raise TypeError("must call with task=1 only after" 

492 " call with task=0,-1") from e 

493 if not per: 

494 n, c, fp, ier = dfitpack.curfit(task, x, y, w, t, wrk, iwrk, 

495 xb, xe, k, s) 

496 else: 

497 n, c, fp, ier = dfitpack.percur(task, x, y, w, t, wrk, iwrk, k, s) 

498 tck = (t[:n], c[:n], k) 

499 if ier <= 0 and not quiet: 

500 _mess = (_iermess[ier][0] + "\tk=%d n=%d m=%d fp=%f s=%f" % 

501 (k, len(t), m, fp, s)) 

502 warnings.warn(RuntimeWarning(_mess)) 

503 if ier > 0 and not full_output: 

504 if ier in [1, 2, 3]: 

505 warnings.warn(RuntimeWarning(_iermess[ier][0])) 

506 else: 

507 try: 

508 raise _iermess[ier][1](_iermess[ier][0]) 

509 except KeyError as e: 

510 raise _iermess['unknown'][1](_iermess['unknown'][0]) from e 

511 if full_output: 

512 try: 

513 return tck, fp, ier, _iermess[ier][0] 

514 except KeyError: 

515 return tck, fp, ier, _iermess['unknown'][0] 

516 else: 

517 return tck 

518 

519 

520def splev(x, tck, der=0, ext=0): 

521 """ 

522 Evaluate a B-spline or its derivatives. 

523 

524 Given the knots and coefficients of a B-spline representation, evaluate 

525 the value of the smoothing polynomial and its derivatives. This is a 

526 wrapper around the FORTRAN routines splev and splder of FITPACK. 

527 

528 Parameters 

529 ---------- 

530 x : array_like 

531 An array of points at which to return the value of the smoothed 

532 spline or its derivatives. If `tck` was returned from `splprep`, 

533 then the parameter values, u should be given. 

534 tck : tuple 

535 A sequence of length 3 returned by `splrep` or `splprep` containing 

536 the knots, coefficients, and degree of the spline. 

537 der : int, optional 

538 The order of derivative of the spline to compute (must be less than 

539 or equal to k). 

540 ext : int, optional 

541 Controls the value returned for elements of ``x`` not in the 

542 interval defined by the knot sequence. 

543 

544 * if ext=0, return the extrapolated value. 

545 * if ext=1, return 0 

546 * if ext=2, raise a ValueError 

547 * if ext=3, return the boundary value. 

548 

549 The default value is 0. 

550 

551 Returns 

552 ------- 

553 y : ndarray or list of ndarrays 

554 An array of values representing the spline function evaluated at 

555 the points in ``x``. If `tck` was returned from `splprep`, then this 

556 is a list of arrays representing the curve in N-D space. 

557 

558 See Also 

559 -------- 

560 splprep, splrep, sproot, spalde, splint 

561 bisplrep, bisplev 

562 

563 References 

564 ---------- 

565 .. [1] C. de Boor, "On calculating with b-splines", J. Approximation 

566 Theory, 6, p.50-62, 1972. 

567 .. [2] M.G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths 

568 Applics, 10, p.134-149, 1972. 

569 .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs 

570 on Numerical Analysis, Oxford University Press, 1993. 

571 

572 """ 

573 t, c, k = tck 

574 try: 

575 c[0][0] 

576 parametric = True 

577 except Exception: 

578 parametric = False 

579 if parametric: 

580 return list(map(lambda c, x=x, t=t, k=k, der=der: 

581 splev(x, [t, c, k], der, ext), c)) 

582 else: 

583 if not (0 <= der <= k): 

584 raise ValueError("0<=der=%d<=k=%d must hold" % (der, k)) 

585 if ext not in (0, 1, 2, 3): 

586 raise ValueError("ext = %s not in (0, 1, 2, 3) " % ext) 

587 

588 x = asarray(x) 

589 shape = x.shape 

590 x = atleast_1d(x).ravel() 

591 y, ier = _fitpack._spl_(x, der, t, c, k, ext) 

592 

593 if ier == 10: 

594 raise ValueError("Invalid input data") 

595 if ier == 1: 

596 raise ValueError("Found x value not in the domain") 

597 if ier: 

598 raise TypeError("An error occurred") 

599 

600 return y.reshape(shape) 

601 

602 

603def splint(a, b, tck, full_output=0): 

604 """ 

605 Evaluate the definite integral of a B-spline. 

606 

607 Given the knots and coefficients of a B-spline, evaluate the definite 

608 integral of the smoothing polynomial between two given points. 

609 

610 Parameters 

611 ---------- 

612 a, b : float 

613 The end-points of the integration interval. 

614 tck : tuple 

615 A tuple (t,c,k) containing the vector of knots, the B-spline 

616 coefficients, and the degree of the spline (see `splev`). 

617 full_output : int, optional 

618 Non-zero to return optional output. 

619 

620 Returns 

621 ------- 

622 integral : float 

623 The resulting integral. 

624 wrk : ndarray 

625 An array containing the integrals of the normalized B-splines 

626 defined on the set of knots. 

627 

628 Notes 

629 ----- 

630 splint silently assumes that the spline function is zero outside the data 

631 interval (a, b). 

632 

633 See Also 

634 -------- 

635 splprep, splrep, sproot, spalde, splev 

636 bisplrep, bisplev 

637 UnivariateSpline, BivariateSpline 

638 

639 References 

640 ---------- 

641 .. [1] P.W. Gaffney, The calculation of indefinite integrals of b-splines", 

642 J. Inst. Maths Applics, 17, p.37-41, 1976. 

643 .. [2] P. Dierckx, "Curve and surface fitting with splines", Monographs 

644 on Numerical Analysis, Oxford University Press, 1993. 

645 

646 """ 

647 t, c, k = tck 

648 try: 

649 c[0][0] 

650 parametric = True 

651 except Exception: 

652 parametric = False 

653 if parametric: 

654 return list(map(lambda c, a=a, b=b, t=t, k=k: 

655 splint(a, b, [t, c, k]), c)) 

656 else: 

657 aint, wrk = dfitpack.splint(t, c, k, a, b) 

658 if full_output: 

659 return aint, wrk 

660 else: 

661 return aint 

662 

663 

664def sproot(tck, mest=10): 

665 """ 

666 Find the roots of a cubic B-spline. 

667 

668 Given the knots (>=8) and coefficients of a cubic B-spline return the 

669 roots of the spline. 

670 

671 Parameters 

672 ---------- 

673 tck : tuple 

674 A tuple (t,c,k) containing the vector of knots, 

675 the B-spline coefficients, and the degree of the spline. 

676 The number of knots must be >= 8, and the degree must be 3. 

677 The knots must be a montonically increasing sequence. 

678 mest : int, optional 

679 An estimate of the number of zeros (Default is 10). 

680 

681 Returns 

682 ------- 

683 zeros : ndarray 

684 An array giving the roots of the spline. 

685 

686 See Also 

687 -------- 

688 splprep, splrep, splint, spalde, splev 

689 bisplrep, bisplev 

690 UnivariateSpline, BivariateSpline 

691 

692 

693 References 

694 ---------- 

695 .. [1] C. de Boor, "On calculating with b-splines", J. Approximation 

696 Theory, 6, p.50-62, 1972. 

697 .. [2] M.G. Cox, "The numerical evaluation of b-splines", J. Inst. Maths 

698 Applics, 10, p.134-149, 1972. 

699 .. [3] P. Dierckx, "Curve and surface fitting with splines", Monographs 

700 on Numerical Analysis, Oxford University Press, 1993. 

701 

702 """ 

703 t, c, k = tck 

704 if k != 3: 

705 raise ValueError("sproot works only for cubic (k=3) splines") 

706 try: 

707 c[0][0] 

708 parametric = True 

709 except Exception: 

710 parametric = False 

711 if parametric: 

712 return list(map(lambda c, t=t, k=k, mest=mest: 

713 sproot([t, c, k], mest), c)) 

714 else: 

715 if len(t) < 8: 

716 raise TypeError("The number of knots %d>=8" % len(t)) 

717 z, m, ier = dfitpack.sproot(t, c, mest) 

718 if ier == 10: 

719 raise TypeError("Invalid input data. " 

720 "t1<=..<=t4<t5<..<tn-3<=..<=tn must hold.") 

721 if ier == 0: 

722 return z[:m] 

723 if ier == 1: 

724 warnings.warn(RuntimeWarning("The number of zeros exceeds mest")) 

725 return z[:m] 

726 raise TypeError("Unknown error") 

727 

728 

729def spalde(x, tck): 

730 """ 

731 Evaluate all derivatives of a B-spline. 

732 

733 Given the knots and coefficients of a cubic B-spline compute all 

734 derivatives up to order k at a point (or set of points). 

735 

736 Parameters 

737 ---------- 

738 x : array_like 

739 A point or a set of points at which to evaluate the derivatives. 

740 Note that ``t(k) <= x <= t(n-k+1)`` must hold for each `x`. 

741 tck : tuple 

742 A tuple (t,c,k) containing the vector of knots, 

743 the B-spline coefficients, and the degree of the spline. 

744 

745 Returns 

746 ------- 

747 results : {ndarray, list of ndarrays} 

748 An array (or a list of arrays) containing all derivatives 

749 up to order k inclusive for each point `x`. 

750 

751 See Also 

752 -------- 

753 splprep, splrep, splint, sproot, splev, bisplrep, bisplev, 

754 UnivariateSpline, BivariateSpline 

755 

756 References 

757 ---------- 

758 .. [1] de Boor C : On calculating with b-splines, J. Approximation Theory 

759 6 (1972) 50-62. 

760 .. [2] Cox M.G. : The numerical evaluation of b-splines, J. Inst. Maths 

761 applics 10 (1972) 134-149. 

762 .. [3] Dierckx P. : Curve and surface fitting with splines, Monographs on 

763 Numerical Analysis, Oxford University Press, 1993. 

764 

765 """ 

766 t, c, k = tck 

767 try: 

768 c[0][0] 

769 parametric = True 

770 except Exception: 

771 parametric = False 

772 if parametric: 

773 return list(map(lambda c, x=x, t=t, k=k: 

774 spalde(x, [t, c, k]), c)) 

775 else: 

776 x = atleast_1d(x) 

777 if len(x) > 1: 

778 return list(map(lambda x, tck=tck: spalde(x, tck), x)) 

779 d, ier = dfitpack.spalde(t, c, k+1, x[0]) 

780 if ier == 0: 

781 return d 

782 if ier == 10: 

783 raise TypeError("Invalid input data. t(k)<=x<=t(n-k+1) must hold.") 

784 raise TypeError("Unknown error") 

785 

786# def _curfit(x,y,w=None,xb=None,xe=None,k=3,task=0,s=None,t=None, 

787# full_output=0,nest=None,per=0,quiet=1): 

788 

789 

790_surfit_cache = {'tx': array([], float), 'ty': array([], float), 

791 'wrk': array([], float), 'iwrk': array([], dfitpack_int)} 

792 

793 

794def bisplrep(x, y, z, w=None, xb=None, xe=None, yb=None, ye=None, 

795 kx=3, ky=3, task=0, s=None, eps=1e-16, tx=None, ty=None, 

796 full_output=0, nxest=None, nyest=None, quiet=1): 

797 """ 

798 Find a bivariate B-spline representation of a surface. 

799 

800 Given a set of data points (x[i], y[i], z[i]) representing a surface 

801 z=f(x,y), compute a B-spline representation of the surface. Based on 

802 the routine SURFIT from FITPACK. 

803 

804 Parameters 

805 ---------- 

806 x, y, z : ndarray 

807 Rank-1 arrays of data points. 

808 w : ndarray, optional 

809 Rank-1 array of weights. By default ``w=np.ones(len(x))``. 

810 xb, xe : float, optional 

811 End points of approximation interval in `x`. 

812 By default ``xb = x.min(), xe=x.max()``. 

813 yb, ye : float, optional 

814 End points of approximation interval in `y`. 

815 By default ``yb=y.min(), ye = y.max()``. 

816 kx, ky : int, optional 

817 The degrees of the spline (1 <= kx, ky <= 5). 

818 Third order (kx=ky=3) is recommended. 

819 task : int, optional 

820 If task=0, find knots in x and y and coefficients for a given 

821 smoothing factor, s. 

822 If task=1, find knots and coefficients for another value of the 

823 smoothing factor, s. bisplrep must have been previously called 

824 with task=0 or task=1. 

825 If task=-1, find coefficients for a given set of knots tx, ty. 

826 s : float, optional 

827 A non-negative smoothing factor. If weights correspond 

828 to the inverse of the standard-deviation of the errors in z, 

829 then a good s-value should be found in the range 

830 ``(m-sqrt(2*m),m+sqrt(2*m))`` where m=len(x). 

831 eps : float, optional 

832 A threshold for determining the effective rank of an 

833 over-determined linear system of equations (0 < eps < 1). 

834 `eps` is not likely to need changing. 

835 tx, ty : ndarray, optional 

836 Rank-1 arrays of the knots of the spline for task=-1 

837 full_output : int, optional 

838 Non-zero to return optional outputs. 

839 nxest, nyest : int, optional 

840 Over-estimates of the total number of knots. If None then 

841 ``nxest = max(kx+sqrt(m/2),2*kx+3)``, 

842 ``nyest = max(ky+sqrt(m/2),2*ky+3)``. 

843 quiet : int, optional 

844 Non-zero to suppress printing of messages. 

845 

846 Returns 

847 ------- 

848 tck : array_like 

849 A list [tx, ty, c, kx, ky] containing the knots (tx, ty) and 

850 coefficients (c) of the bivariate B-spline representation of the 

851 surface along with the degree of the spline. 

852 fp : ndarray 

853 The weighted sum of squared residuals of the spline approximation. 

854 ier : int 

855 An integer flag about splrep success. Success is indicated if 

856 ier<=0. If ier in [1,2,3] an error occurred but was not raised. 

857 Otherwise an error is raised. 

858 msg : str 

859 A message corresponding to the integer flag, ier. 

860 

861 See Also 

862 -------- 

863 splprep, splrep, splint, sproot, splev 

864 UnivariateSpline, BivariateSpline 

865 

866 Notes 

867 ----- 

868 See `bisplev` to evaluate the value of the B-spline given its tck 

869 representation. 

870 

871 If the input data is such that input dimensions have incommensurate 

872 units and differ by many orders of magnitude, the interpolant may have 

873 numerical artifacts. Consider rescaling the data before interpolation. 

874 

875 References 

876 ---------- 

877 .. [1] Dierckx P.:An algorithm for surface fitting with spline functions 

878 Ima J. Numer. Anal. 1 (1981) 267-283. 

879 .. [2] Dierckx P.:An algorithm for surface fitting with spline functions 

880 report tw50, Dept. Computer Science,K.U.Leuven, 1980. 

881 .. [3] Dierckx P.:Curve and surface fitting with splines, Monographs on 

882 Numerical Analysis, Oxford University Press, 1993. 

883 

884 Examples 

885 -------- 

886 Examples are given :ref:`in the tutorial <tutorial-interpolate_2d_spline>`. 

887 

888 """ 

889 x, y, z = map(ravel, [x, y, z]) # ensure 1-d arrays. 

890 m = len(x) 

891 if not (m == len(y) == len(z)): 

892 raise TypeError('len(x)==len(y)==len(z) must hold.') 

893 if w is None: 

894 w = ones(m, float) 

895 else: 

896 w = atleast_1d(w) 

897 if not len(w) == m: 

898 raise TypeError('len(w)=%d is not equal to m=%d' % (len(w), m)) 

899 if xb is None: 

900 xb = x.min() 

901 if xe is None: 

902 xe = x.max() 

903 if yb is None: 

904 yb = y.min() 

905 if ye is None: 

906 ye = y.max() 

907 if not (-1 <= task <= 1): 

908 raise TypeError('task must be -1, 0 or 1') 

909 if s is None: 

910 s = m - sqrt(2*m) 

911 if tx is None and task == -1: 

912 raise TypeError('Knots_x must be given for task=-1') 

913 if tx is not None: 

914 _surfit_cache['tx'] = atleast_1d(tx) 

915 nx = len(_surfit_cache['tx']) 

916 if ty is None and task == -1: 

917 raise TypeError('Knots_y must be given for task=-1') 

918 if ty is not None: 

919 _surfit_cache['ty'] = atleast_1d(ty) 

920 ny = len(_surfit_cache['ty']) 

921 if task == -1 and nx < 2*kx+2: 

922 raise TypeError('There must be at least 2*kx+2 knots_x for task=-1') 

923 if task == -1 and ny < 2*ky+2: 

924 raise TypeError('There must be at least 2*ky+2 knots_x for task=-1') 

925 if not ((1 <= kx <= 5) and (1 <= ky <= 5)): 

926 raise TypeError('Given degree of the spline (kx,ky=%d,%d) is not ' 

927 'supported. (1<=k<=5)' % (kx, ky)) 

928 if m < (kx + 1)*(ky + 1): 

929 raise TypeError('m >= (kx+1)(ky+1) must hold') 

930 if nxest is None: 

931 nxest = int(kx + sqrt(m/2)) 

932 if nyest is None: 

933 nyest = int(ky + sqrt(m/2)) 

934 nxest, nyest = max(nxest, 2*kx + 3), max(nyest, 2*ky + 3) 

935 if task >= 0 and s == 0: 

936 nxest = int(kx + sqrt(3*m)) 

937 nyest = int(ky + sqrt(3*m)) 

938 if task == -1: 

939 _surfit_cache['tx'] = atleast_1d(tx) 

940 _surfit_cache['ty'] = atleast_1d(ty) 

941 tx, ty = _surfit_cache['tx'], _surfit_cache['ty'] 

942 wrk = _surfit_cache['wrk'] 

943 u = nxest - kx - 1 

944 v = nyest - ky - 1 

945 km = max(kx, ky) + 1 

946 ne = max(nxest, nyest) 

947 bx, by = kx*v + ky + 1, ky*u + kx + 1 

948 b1, b2 = bx, bx + v - ky 

949 if bx > by: 

950 b1, b2 = by, by + u - kx 

951 msg = "Too many data points to interpolate" 

952 lwrk1 = _int_overflow(u*v*(2 + b1 + b2) + 

953 2*(u + v + km*(m + ne) + ne - kx - ky) + b2 + 1, 

954 msg=msg) 

955 lwrk2 = _int_overflow(u*v*(b2 + 1) + b2, msg=msg) 

956 tx, ty, c, o = _fitpack._surfit(x, y, z, w, xb, xe, yb, ye, kx, ky, 

957 task, s, eps, tx, ty, nxest, nyest, 

958 wrk, lwrk1, lwrk2) 

959 _curfit_cache['tx'] = tx 

960 _curfit_cache['ty'] = ty 

961 _curfit_cache['wrk'] = o['wrk'] 

962 ier, fp = o['ier'], o['fp'] 

963 tck = [tx, ty, c, kx, ky] 

964 

965 ierm = min(11, max(-3, ier)) 

966 if ierm <= 0 and not quiet: 

967 _mess = (_iermess2[ierm][0] + 

968 "\tkx,ky=%d,%d nx,ny=%d,%d m=%d fp=%f s=%f" % 

969 (kx, ky, len(tx), len(ty), m, fp, s)) 

970 warnings.warn(RuntimeWarning(_mess)) 

971 if ierm > 0 and not full_output: 

972 if ier in [1, 2, 3, 4, 5]: 

973 _mess = ("\n\tkx,ky=%d,%d nx,ny=%d,%d m=%d fp=%f s=%f" % 

974 (kx, ky, len(tx), len(ty), m, fp, s)) 

975 warnings.warn(RuntimeWarning(_iermess2[ierm][0] + _mess)) 

976 else: 

977 try: 

978 raise _iermess2[ierm][1](_iermess2[ierm][0]) 

979 except KeyError as e: 

980 raise _iermess2['unknown'][1](_iermess2['unknown'][0]) from e 

981 if full_output: 

982 try: 

983 return tck, fp, ier, _iermess2[ierm][0] 

984 except KeyError: 

985 return tck, fp, ier, _iermess2['unknown'][0] 

986 else: 

987 return tck 

988 

989 

990def bisplev(x, y, tck, dx=0, dy=0): 

991 """ 

992 Evaluate a bivariate B-spline and its derivatives. 

993 

994 Return a rank-2 array of spline function values (or spline derivative 

995 values) at points given by the cross-product of the rank-1 arrays `x` and 

996 `y`. In special cases, return an array or just a float if either `x` or 

997 `y` or both are floats. Based on BISPEV and PARDER from FITPACK. 

998 

999 Parameters 

1000 ---------- 

1001 x, y : ndarray 

1002 Rank-1 arrays specifying the domain over which to evaluate the 

1003 spline or its derivative. 

1004 tck : tuple 

1005 A sequence of length 5 returned by `bisplrep` containing the knot 

1006 locations, the coefficients, and the degree of the spline: 

1007 [tx, ty, c, kx, ky]. 

1008 dx, dy : int, optional 

1009 The orders of the partial derivatives in `x` and `y` respectively. 

1010 

1011 Returns 

1012 ------- 

1013 vals : ndarray 

1014 The B-spline or its derivative evaluated over the set formed by 

1015 the cross-product of `x` and `y`. 

1016 

1017 See Also 

1018 -------- 

1019 splprep, splrep, splint, sproot, splev 

1020 UnivariateSpline, BivariateSpline 

1021 

1022 Notes 

1023 ----- 

1024 See `bisplrep` to generate the `tck` representation. 

1025 

1026 References 

1027 ---------- 

1028 .. [1] Dierckx P. : An algorithm for surface fitting 

1029 with spline functions 

1030 Ima J. Numer. Anal. 1 (1981) 267-283. 

1031 .. [2] Dierckx P. : An algorithm for surface fitting 

1032 with spline functions 

1033 report tw50, Dept. Computer Science,K.U.Leuven, 1980. 

1034 .. [3] Dierckx P. : Curve and surface fitting with splines, 

1035 Monographs on Numerical Analysis, Oxford University Press, 1993. 

1036 

1037 Examples 

1038 -------- 

1039 Examples are given :ref:`in the tutorial <tutorial-interpolate_2d_spline>`. 

1040 

1041 """ 

1042 tx, ty, c, kx, ky = tck 

1043 if not (0 <= dx < kx): 

1044 raise ValueError("0 <= dx = %d < kx = %d must hold" % (dx, kx)) 

1045 if not (0 <= dy < ky): 

1046 raise ValueError("0 <= dy = %d < ky = %d must hold" % (dy, ky)) 

1047 x, y = map(atleast_1d, [x, y]) 

1048 if (len(x.shape) != 1) or (len(y.shape) != 1): 

1049 raise ValueError("First two entries should be rank-1 arrays.") 

1050 z, ier = _fitpack._bispev(tx, ty, c, kx, ky, x, y, dx, dy) 

1051 if ier == 10: 

1052 raise ValueError("Invalid input data") 

1053 if ier: 

1054 raise TypeError("An error occurred") 

1055 z.shape = len(x), len(y) 

1056 if len(z) > 1: 

1057 return z 

1058 if len(z[0]) > 1: 

1059 return z[0] 

1060 return z[0][0] 

1061 

1062 

1063def dblint(xa, xb, ya, yb, tck): 

1064 """Evaluate the integral of a spline over area [xa,xb] x [ya,yb]. 

1065 

1066 Parameters 

1067 ---------- 

1068 xa, xb : float 

1069 The end-points of the x integration interval. 

1070 ya, yb : float 

1071 The end-points of the y integration interval. 

1072 tck : list [tx, ty, c, kx, ky] 

1073 A sequence of length 5 returned by bisplrep containing the knot 

1074 locations tx, ty, the coefficients c, and the degrees kx, ky 

1075 of the spline. 

1076 

1077 Returns 

1078 ------- 

1079 integ : float 

1080 The value of the resulting integral. 

1081 """ 

1082 tx, ty, c, kx, ky = tck 

1083 return dfitpack.dblint(tx, ty, c, kx, ky, xa, xb, ya, yb) 

1084 

1085 

1086def insert(x, tck, m=1, per=0): 

1087 """ 

1088 Insert knots into a B-spline. 

1089 

1090 Given the knots and coefficients of a B-spline representation, create a 

1091 new B-spline with a knot inserted `m` times at point `x`. 

1092 This is a wrapper around the FORTRAN routine insert of FITPACK. 

1093 

1094 Parameters 

1095 ---------- 

1096 x (u) : array_like 

1097 A 1-D point at which to insert a new knot(s). If `tck` was returned 

1098 from ``splprep``, then the parameter values, u should be given. 

1099 tck : tuple 

1100 A tuple (t,c,k) returned by ``splrep`` or ``splprep`` containing 

1101 the vector of knots, the B-spline coefficients, 

1102 and the degree of the spline. 

1103 m : int, optional 

1104 The number of times to insert the given knot (its multiplicity). 

1105 Default is 1. 

1106 per : int, optional 

1107 If non-zero, the input spline is considered periodic. 

1108 

1109 Returns 

1110 ------- 

1111 tck : tuple 

1112 A tuple (t,c,k) containing the vector of knots, the B-spline 

1113 coefficients, and the degree of the new spline. 

1114 ``t(k+1) <= x <= t(n-k)``, where k is the degree of the spline. 

1115 In case of a periodic spline (``per != 0``) there must be 

1116 either at least k interior knots t(j) satisfying ``t(k+1)<t(j)<=x`` 

1117 or at least k interior knots t(j) satisfying ``x<=t(j)<t(n-k)``. 

1118 

1119 Notes 

1120 ----- 

1121 Based on algorithms from [1]_ and [2]_. 

1122 

1123 References 

1124 ---------- 

1125 .. [1] W. Boehm, "Inserting new knots into b-spline curves.", 

1126 Computer Aided Design, 12, p.199-201, 1980. 

1127 .. [2] P. Dierckx, "Curve and surface fitting with splines, Monographs on 

1128 Numerical Analysis", Oxford University Press, 1993. 

1129 

1130 """ 

1131 t, c, k = tck 

1132 try: 

1133 c[0][0] 

1134 parametric = True 

1135 except Exception: 

1136 parametric = False 

1137 if parametric: 

1138 cc = [] 

1139 for c_vals in c: 

1140 tt, cc_val, kk = insert(x, [t, c_vals, k], m) 

1141 cc.append(cc_val) 

1142 return (tt, cc, kk) 

1143 else: 

1144 tt, cc, ier = _fitpack._insert(per, t, c, k, x, m) 

1145 if ier == 10: 

1146 raise ValueError("Invalid input data") 

1147 if ier: 

1148 raise TypeError("An error occurred") 

1149 return (tt, cc, k) 

1150 

1151 

1152def splder(tck, n=1): 

1153 """ 

1154 Compute the spline representation of the derivative of a given spline 

1155 

1156 Parameters 

1157 ---------- 

1158 tck : tuple of (t, c, k) 

1159 Spline whose derivative to compute 

1160 n : int, optional 

1161 Order of derivative to evaluate. Default: 1 

1162 

1163 Returns 

1164 ------- 

1165 tck_der : tuple of (t2, c2, k2) 

1166 Spline of order k2=k-n representing the derivative 

1167 of the input spline. 

1168 

1169 Notes 

1170 ----- 

1171 

1172 .. versionadded:: 0.13.0 

1173 

1174 See Also 

1175 -------- 

1176 splantider, splev, spalde 

1177 

1178 Examples 

1179 -------- 

1180 This can be used for finding maxima of a curve: 

1181 

1182 >>> from scipy.interpolate import splrep, splder, sproot 

1183 >>> x = np.linspace(0, 10, 70) 

1184 >>> y = np.sin(x) 

1185 >>> spl = splrep(x, y, k=4) 

1186 

1187 Now, differentiate the spline and find the zeros of the 

1188 derivative. (NB: `sproot` only works for order 3 splines, so we 

1189 fit an order 4 spline): 

1190 

1191 >>> dspl = splder(spl) 

1192 >>> sproot(dspl) / np.pi 

1193 array([ 0.50000001, 1.5 , 2.49999998]) 

1194 

1195 This agrees well with roots :math:`\\pi/2 + n\\pi` of 

1196 :math:`\\cos(x) = \\sin'(x)`. 

1197 

1198 """ 

1199 if n < 0: 

1200 return splantider(tck, -n) 

1201 

1202 t, c, k = tck 

1203 

1204 if n > k: 

1205 raise ValueError(("Order of derivative (n = %r) must be <= " 

1206 "order of spline (k = %r)") % (n, tck[2])) 

1207 

1208 # Extra axes for the trailing dims of the `c` array: 

1209 sh = (slice(None),) + ((None,)*len(c.shape[1:])) 

1210 

1211 with np.errstate(invalid='raise', divide='raise'): 

1212 try: 

1213 for j in range(n): 

1214 # See e.g. Schumaker, Spline Functions: Basic Theory, Chapter 5 

1215 

1216 # Compute the denominator in the differentiation formula. 

1217 # (and append traling dims, if necessary) 

1218 dt = t[k+1:-1] - t[1:-k-1] 

1219 dt = dt[sh] 

1220 # Compute the new coefficients 

1221 c = (c[1:-1-k] - c[:-2-k]) * k / dt 

1222 # Pad coefficient array to same size as knots (FITPACK 

1223 # convention) 

1224 c = np.r_[c, np.zeros((k,) + c.shape[1:])] 

1225 # Adjust knots 

1226 t = t[1:-1] 

1227 k -= 1 

1228 except FloatingPointError as e: 

1229 raise ValueError(("The spline has internal repeated knots " 

1230 "and is not differentiable %d times") % n) from e 

1231 

1232 return t, c, k 

1233 

1234 

1235def splantider(tck, n=1): 

1236 """ 

1237 Compute the spline for the antiderivative (integral) of a given spline. 

1238 

1239 Parameters 

1240 ---------- 

1241 tck : tuple of (t, c, k) 

1242 Spline whose antiderivative to compute 

1243 n : int, optional 

1244 Order of antiderivative to evaluate. Default: 1 

1245 

1246 Returns 

1247 ------- 

1248 tck_ader : tuple of (t2, c2, k2) 

1249 Spline of order k2=k+n representing the antiderivative of the input 

1250 spline. 

1251 

1252 See Also 

1253 -------- 

1254 splder, splev, spalde 

1255 

1256 Notes 

1257 ----- 

1258 The `splder` function is the inverse operation of this function. 

1259 Namely, ``splder(splantider(tck))`` is identical to `tck`, modulo 

1260 rounding error. 

1261 

1262 .. versionadded:: 0.13.0 

1263 

1264 Examples 

1265 -------- 

1266 >>> from scipy.interpolate import splrep, splder, splantider, splev 

1267 >>> x = np.linspace(0, np.pi/2, 70) 

1268 >>> y = 1 / np.sqrt(1 - 0.8*np.sin(x)**2) 

1269 >>> spl = splrep(x, y) 

1270 

1271 The derivative is the inverse operation of the antiderivative, 

1272 although some floating point error accumulates: 

1273 

1274 >>> splev(1.7, spl), splev(1.7, splder(splantider(spl))) 

1275 (array(2.1565429877197317), array(2.1565429877201865)) 

1276 

1277 Antiderivative can be used to evaluate definite integrals: 

1278 

1279 >>> ispl = splantider(spl) 

1280 >>> splev(np.pi/2, ispl) - splev(0, ispl) 

1281 2.2572053588768486 

1282 

1283 This is indeed an approximation to the complete elliptic integral 

1284 :math:`K(m) = \\int_0^{\\pi/2} [1 - m\\sin^2 x]^{-1/2} dx`: 

1285 

1286 >>> from scipy.special import ellipk 

1287 >>> ellipk(0.8) 

1288 2.2572053268208538 

1289 

1290 """ 

1291 if n < 0: 

1292 return splder(tck, -n) 

1293 

1294 t, c, k = tck 

1295 

1296 # Extra axes for the trailing dims of the `c` array: 

1297 sh = (slice(None),) + (None,)*len(c.shape[1:]) 

1298 

1299 for j in range(n): 

1300 # This is the inverse set of operations to splder. 

1301 

1302 # Compute the multiplier in the antiderivative formula. 

1303 dt = t[k+1:] - t[:-k-1] 

1304 dt = dt[sh] 

1305 # Compute the new coefficients 

1306 c = np.cumsum(c[:-k-1] * dt, axis=0) / (k + 1) 

1307 c = np.r_[np.zeros((1,) + c.shape[1:]), 

1308 c, 

1309 [c[-1]] * (k+2)] 

1310 # New knots 

1311 t = np.r_[t[0], t, t[-1]] 

1312 k += 1 

1313 

1314 return t, c, k