Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/lib/function_base.py: 22%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1266 statements  

1import collections.abc 

2import functools 

3import re 

4import sys 

5import warnings 

6 

7from .._utils import set_module 

8import numpy as np 

9import numpy.core.numeric as _nx 

10from numpy.core import transpose 

11from numpy.core.numeric import ( 

12 ones, zeros_like, arange, concatenate, array, asarray, asanyarray, empty, 

13 ndarray, take, dot, where, intp, integer, isscalar, absolute 

14 ) 

15from numpy.core.umath import ( 

16 pi, add, arctan2, frompyfunc, cos, less_equal, sqrt, sin, 

17 mod, exp, not_equal, subtract 

18 ) 

19from numpy.core.fromnumeric import ( 

20 ravel, nonzero, partition, mean, any, sum 

21 ) 

22from numpy.core.numerictypes import typecodes 

23from numpy.core import overrides 

24from numpy.core.function_base import add_newdoc 

25from numpy.lib.twodim_base import diag 

26from numpy.core.multiarray import ( 

27 _place, add_docstring, bincount, normalize_axis_index, _monotonicity, 

28 interp as compiled_interp, interp_complex as compiled_interp_complex 

29 ) 

30from numpy.core.umath import _add_newdoc_ufunc as add_newdoc_ufunc 

31 

32import builtins 

33 

34# needed in this module for compatibility 

35from numpy.lib.histograms import histogram, histogramdd # noqa: F401 

36 

37 

38array_function_dispatch = functools.partial( 

39 overrides.array_function_dispatch, module='numpy') 

40 

41 

42__all__ = [ 

43 'select', 'piecewise', 'trim_zeros', 'copy', 'iterable', 'percentile', 

44 'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp', 'flip', 

45 'rot90', 'extract', 'place', 'vectorize', 'asarray_chkfinite', 'average', 

46 'bincount', 'digitize', 'cov', 'corrcoef', 

47 'msort', 'median', 'sinc', 'hamming', 'hanning', 'bartlett', 

48 'blackman', 'kaiser', 'trapz', 'i0', 'add_newdoc', 'add_docstring', 

49 'meshgrid', 'delete', 'insert', 'append', 'interp', 'add_newdoc_ufunc', 

50 'quantile' 

51 ] 

52 

53# _QuantileMethods is a dictionary listing all the supported methods to 

54# compute quantile/percentile. 

55# 

56# Below virtual_index refer to the index of the element where the percentile 

57# would be found in the sorted sample. 

58# When the sample contains exactly the percentile wanted, the virtual_index is 

59# an integer to the index of this element. 

60# When the percentile wanted is in between two elements, the virtual_index 

61# is made of a integer part (a.k.a 'i' or 'left') and a fractional part 

62# (a.k.a 'g' or 'gamma') 

63# 

64# Each method in _QuantileMethods has two properties 

65# get_virtual_index : Callable 

66# The function used to compute the virtual_index. 

67# fix_gamma : Callable 

68# A function used for discret methods to force the index to a specific value. 

69_QuantileMethods = dict( 

70 # --- HYNDMAN and FAN METHODS 

71 # Discrete methods 

72 inverted_cdf=dict( 

73 get_virtual_index=lambda n, quantiles: _inverted_cdf(n, quantiles), 

74 fix_gamma=lambda gamma, _: gamma, # should never be called 

75 ), 

76 averaged_inverted_cdf=dict( 

77 get_virtual_index=lambda n, quantiles: (n * quantiles) - 1, 

78 fix_gamma=lambda gamma, _: _get_gamma_mask( 

79 shape=gamma.shape, 

80 default_value=1., 

81 conditioned_value=0.5, 

82 where=gamma == 0), 

83 ), 

84 closest_observation=dict( 

85 get_virtual_index=lambda n, quantiles: _closest_observation(n, 

86 quantiles), 

87 fix_gamma=lambda gamma, _: gamma, # should never be called 

88 ), 

89 # Continuous methods 

90 interpolated_inverted_cdf=dict( 

91 get_virtual_index=lambda n, quantiles: 

92 _compute_virtual_index(n, quantiles, 0, 1), 

93 fix_gamma=lambda gamma, _: gamma, 

94 ), 

95 hazen=dict( 

96 get_virtual_index=lambda n, quantiles: 

97 _compute_virtual_index(n, quantiles, 0.5, 0.5), 

98 fix_gamma=lambda gamma, _: gamma, 

99 ), 

100 weibull=dict( 

101 get_virtual_index=lambda n, quantiles: 

102 _compute_virtual_index(n, quantiles, 0, 0), 

103 fix_gamma=lambda gamma, _: gamma, 

104 ), 

105 # Default method. 

106 # To avoid some rounding issues, `(n-1) * quantiles` is preferred to 

107 # `_compute_virtual_index(n, quantiles, 1, 1)`. 

108 # They are mathematically equivalent. 

109 linear=dict( 

110 get_virtual_index=lambda n, quantiles: (n - 1) * quantiles, 

111 fix_gamma=lambda gamma, _: gamma, 

112 ), 

113 median_unbiased=dict( 

114 get_virtual_index=lambda n, quantiles: 

115 _compute_virtual_index(n, quantiles, 1 / 3.0, 1 / 3.0), 

116 fix_gamma=lambda gamma, _: gamma, 

117 ), 

118 normal_unbiased=dict( 

119 get_virtual_index=lambda n, quantiles: 

120 _compute_virtual_index(n, quantiles, 3 / 8.0, 3 / 8.0), 

121 fix_gamma=lambda gamma, _: gamma, 

122 ), 

123 # --- OTHER METHODS 

124 lower=dict( 

125 get_virtual_index=lambda n, quantiles: np.floor( 

126 (n - 1) * quantiles).astype(np.intp), 

127 fix_gamma=lambda gamma, _: gamma, 

128 # should never be called, index dtype is int 

129 ), 

130 higher=dict( 

131 get_virtual_index=lambda n, quantiles: np.ceil( 

132 (n - 1) * quantiles).astype(np.intp), 

133 fix_gamma=lambda gamma, _: gamma, 

134 # should never be called, index dtype is int 

135 ), 

136 midpoint=dict( 

137 get_virtual_index=lambda n, quantiles: 0.5 * ( 

138 np.floor((n - 1) * quantiles) 

139 + np.ceil((n - 1) * quantiles)), 

140 fix_gamma=lambda gamma, index: _get_gamma_mask( 

141 shape=gamma.shape, 

142 default_value=0.5, 

143 conditioned_value=0., 

144 where=index % 1 == 0), 

145 ), 

146 nearest=dict( 

147 get_virtual_index=lambda n, quantiles: np.around( 

148 (n - 1) * quantiles).astype(np.intp), 

149 fix_gamma=lambda gamma, _: gamma, 

150 # should never be called, index dtype is int 

151 )) 

152 

153 

154def _rot90_dispatcher(m, k=None, axes=None): 

155 return (m,) 

156 

157 

158@array_function_dispatch(_rot90_dispatcher) 

159def rot90(m, k=1, axes=(0, 1)): 

160 """ 

161 Rotate an array by 90 degrees in the plane specified by axes. 

162 

163 Rotation direction is from the first towards the second axis. 

164 This means for a 2D array with the default `k` and `axes`, the 

165 rotation will be counterclockwise. 

166 

167 Parameters 

168 ---------- 

169 m : array_like 

170 Array of two or more dimensions. 

171 k : integer 

172 Number of times the array is rotated by 90 degrees. 

173 axes : (2,) array_like 

174 The array is rotated in the plane defined by the axes. 

175 Axes must be different. 

176 

177 .. versionadded:: 1.12.0 

178 

179 Returns 

180 ------- 

181 y : ndarray 

182 A rotated view of `m`. 

183 

184 See Also 

185 -------- 

186 flip : Reverse the order of elements in an array along the given axis. 

187 fliplr : Flip an array horizontally. 

188 flipud : Flip an array vertically. 

189 

190 Notes 

191 ----- 

192 ``rot90(m, k=1, axes=(1,0))`` is the reverse of 

193 ``rot90(m, k=1, axes=(0,1))`` 

194 

195 ``rot90(m, k=1, axes=(1,0))`` is equivalent to 

196 ``rot90(m, k=-1, axes=(0,1))`` 

197 

198 Examples 

199 -------- 

200 >>> m = np.array([[1,2],[3,4]], int) 

201 >>> m 

202 array([[1, 2], 

203 [3, 4]]) 

204 >>> np.rot90(m) 

205 array([[2, 4], 

206 [1, 3]]) 

207 >>> np.rot90(m, 2) 

208 array([[4, 3], 

209 [2, 1]]) 

210 >>> m = np.arange(8).reshape((2,2,2)) 

211 >>> np.rot90(m, 1, (1,2)) 

212 array([[[1, 3], 

213 [0, 2]], 

214 [[5, 7], 

215 [4, 6]]]) 

216 

217 """ 

218 axes = tuple(axes) 

219 if len(axes) != 2: 

220 raise ValueError("len(axes) must be 2.") 

221 

222 m = asanyarray(m) 

223 

224 if axes[0] == axes[1] or absolute(axes[0] - axes[1]) == m.ndim: 

225 raise ValueError("Axes must be different.") 

226 

227 if (axes[0] >= m.ndim or axes[0] < -m.ndim 

228 or axes[1] >= m.ndim or axes[1] < -m.ndim): 

229 raise ValueError("Axes={} out of range for array of ndim={}." 

230 .format(axes, m.ndim)) 

231 

232 k %= 4 

233 

234 if k == 0: 

235 return m[:] 

236 if k == 2: 

237 return flip(flip(m, axes[0]), axes[1]) 

238 

239 axes_list = arange(0, m.ndim) 

240 (axes_list[axes[0]], axes_list[axes[1]]) = (axes_list[axes[1]], 

241 axes_list[axes[0]]) 

242 

243 if k == 1: 

244 return transpose(flip(m, axes[1]), axes_list) 

245 else: 

246 # k == 3 

247 return flip(transpose(m, axes_list), axes[1]) 

248 

249 

250def _flip_dispatcher(m, axis=None): 

251 return (m,) 

252 

253 

254@array_function_dispatch(_flip_dispatcher) 

255def flip(m, axis=None): 

256 """ 

257 Reverse the order of elements in an array along the given axis. 

258 

259 The shape of the array is preserved, but the elements are reordered. 

260 

261 .. versionadded:: 1.12.0 

262 

263 Parameters 

264 ---------- 

265 m : array_like 

266 Input array. 

267 axis : None or int or tuple of ints, optional 

268 Axis or axes along which to flip over. The default, 

269 axis=None, will flip over all of the axes of the input array. 

270 If axis is negative it counts from the last to the first axis. 

271 

272 If axis is a tuple of ints, flipping is performed on all of the axes 

273 specified in the tuple. 

274 

275 .. versionchanged:: 1.15.0 

276 None and tuples of axes are supported 

277 

278 Returns 

279 ------- 

280 out : array_like 

281 A view of `m` with the entries of axis reversed. Since a view is 

282 returned, this operation is done in constant time. 

283 

284 See Also 

285 -------- 

286 flipud : Flip an array vertically (axis=0). 

287 fliplr : Flip an array horizontally (axis=1). 

288 

289 Notes 

290 ----- 

291 flip(m, 0) is equivalent to flipud(m). 

292 

293 flip(m, 1) is equivalent to fliplr(m). 

294 

295 flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n. 

296 

297 flip(m) corresponds to ``m[::-1,::-1,...,::-1]`` with ``::-1`` at all 

298 positions. 

299 

300 flip(m, (0, 1)) corresponds to ``m[::-1,::-1,...]`` with ``::-1`` at 

301 position 0 and position 1. 

302 

303 Examples 

304 -------- 

305 >>> A = np.arange(8).reshape((2,2,2)) 

306 >>> A 

307 array([[[0, 1], 

308 [2, 3]], 

309 [[4, 5], 

310 [6, 7]]]) 

311 >>> np.flip(A, 0) 

312 array([[[4, 5], 

313 [6, 7]], 

314 [[0, 1], 

315 [2, 3]]]) 

316 >>> np.flip(A, 1) 

317 array([[[2, 3], 

318 [0, 1]], 

319 [[6, 7], 

320 [4, 5]]]) 

321 >>> np.flip(A) 

322 array([[[7, 6], 

323 [5, 4]], 

324 [[3, 2], 

325 [1, 0]]]) 

326 >>> np.flip(A, (0, 2)) 

327 array([[[5, 4], 

328 [7, 6]], 

329 [[1, 0], 

330 [3, 2]]]) 

331 >>> A = np.random.randn(3,4,5) 

332 >>> np.all(np.flip(A,2) == A[:,:,::-1,...]) 

333 True 

334 """ 

335 if not hasattr(m, 'ndim'): 

336 m = asarray(m) 

337 if axis is None: 

338 indexer = (np.s_[::-1],) * m.ndim 

339 else: 

340 axis = _nx.normalize_axis_tuple(axis, m.ndim) 

341 indexer = [np.s_[:]] * m.ndim 

342 for ax in axis: 

343 indexer[ax] = np.s_[::-1] 

344 indexer = tuple(indexer) 

345 return m[indexer] 

346 

347 

348@set_module('numpy') 

349def iterable(y): 

350 """ 

351 Check whether or not an object can be iterated over. 

352 

353 Parameters 

354 ---------- 

355 y : object 

356 Input object. 

357 

358 Returns 

359 ------- 

360 b : bool 

361 Return ``True`` if the object has an iterator method or is a 

362 sequence and ``False`` otherwise. 

363 

364 

365 Examples 

366 -------- 

367 >>> np.iterable([1, 2, 3]) 

368 True 

369 >>> np.iterable(2) 

370 False 

371 

372 Notes 

373 ----- 

374 In most cases, the results of ``np.iterable(obj)`` are consistent with 

375 ``isinstance(obj, collections.abc.Iterable)``. One notable exception is 

376 the treatment of 0-dimensional arrays:: 

377 

378 >>> from collections.abc import Iterable 

379 >>> a = np.array(1.0) # 0-dimensional numpy array 

380 >>> isinstance(a, Iterable) 

381 True 

382 >>> np.iterable(a) 

383 False 

384 

385 """ 

386 try: 

387 iter(y) 

388 except TypeError: 

389 return False 

390 return True 

391 

392 

393def _average_dispatcher(a, axis=None, weights=None, returned=None, *, 

394 keepdims=None): 

395 return (a, weights) 

396 

397 

398@array_function_dispatch(_average_dispatcher) 

399def average(a, axis=None, weights=None, returned=False, *, 

400 keepdims=np._NoValue): 

401 """ 

402 Compute the weighted average along the specified axis. 

403 

404 Parameters 

405 ---------- 

406 a : array_like 

407 Array containing data to be averaged. If `a` is not an array, a 

408 conversion is attempted. 

409 axis : None or int or tuple of ints, optional 

410 Axis or axes along which to average `a`. The default, 

411 axis=None, will average over all of the elements of the input array. 

412 If axis is negative it counts from the last to the first axis. 

413 

414 .. versionadded:: 1.7.0 

415 

416 If axis is a tuple of ints, averaging is performed on all of the axes 

417 specified in the tuple instead of a single axis or all the axes as 

418 before. 

419 weights : array_like, optional 

420 An array of weights associated with the values in `a`. Each value in 

421 `a` contributes to the average according to its associated weight. 

422 The weights array can either be 1-D (in which case its length must be 

423 the size of `a` along the given axis) or of the same shape as `a`. 

424 If `weights=None`, then all data in `a` are assumed to have a 

425 weight equal to one. The 1-D calculation is:: 

426 

427 avg = sum(a * weights) / sum(weights) 

428 

429 The only constraint on `weights` is that `sum(weights)` must not be 0. 

430 returned : bool, optional 

431 Default is `False`. If `True`, the tuple (`average`, `sum_of_weights`) 

432 is returned, otherwise only the average is returned. 

433 If `weights=None`, `sum_of_weights` is equivalent to the number of 

434 elements over which the average is taken. 

435 keepdims : bool, optional 

436 If this is set to True, the axes which are reduced are left 

437 in the result as dimensions with size one. With this option, 

438 the result will broadcast correctly against the original `a`. 

439 *Note:* `keepdims` will not work with instances of `numpy.matrix` 

440 or other classes whose methods do not support `keepdims`. 

441 

442 .. versionadded:: 1.23.0 

443 

444 Returns 

445 ------- 

446 retval, [sum_of_weights] : array_type or double 

447 Return the average along the specified axis. When `returned` is `True`, 

448 return a tuple with the average as the first element and the sum 

449 of the weights as the second element. `sum_of_weights` is of the 

450 same type as `retval`. The result dtype follows a genereal pattern. 

451 If `weights` is None, the result dtype will be that of `a` , or ``float64`` 

452 if `a` is integral. Otherwise, if `weights` is not None and `a` is non- 

453 integral, the result type will be the type of lowest precision capable of 

454 representing values of both `a` and `weights`. If `a` happens to be 

455 integral, the previous rules still applies but the result dtype will 

456 at least be ``float64``. 

457 

458 Raises 

459 ------ 

460 ZeroDivisionError 

461 When all weights along axis are zero. See `numpy.ma.average` for a 

462 version robust to this type of error. 

463 TypeError 

464 When the length of 1D `weights` is not the same as the shape of `a` 

465 along axis. 

466 

467 See Also 

468 -------- 

469 mean 

470 

471 ma.average : average for masked arrays -- useful if your data contains 

472 "missing" values 

473 numpy.result_type : Returns the type that results from applying the 

474 numpy type promotion rules to the arguments. 

475 

476 Examples 

477 -------- 

478 >>> data = np.arange(1, 5) 

479 >>> data 

480 array([1, 2, 3, 4]) 

481 >>> np.average(data) 

482 2.5 

483 >>> np.average(np.arange(1, 11), weights=np.arange(10, 0, -1)) 

484 4.0 

485 

486 >>> data = np.arange(6).reshape((3, 2)) 

487 >>> data 

488 array([[0, 1], 

489 [2, 3], 

490 [4, 5]]) 

491 >>> np.average(data, axis=1, weights=[1./4, 3./4]) 

492 array([0.75, 2.75, 4.75]) 

493 >>> np.average(data, weights=[1./4, 3./4]) 

494 Traceback (most recent call last): 

495 ... 

496 TypeError: Axis must be specified when shapes of a and weights differ. 

497 

498 >>> a = np.ones(5, dtype=np.float128) 

499 >>> w = np.ones(5, dtype=np.complex64) 

500 >>> avg = np.average(a, weights=w) 

501 >>> print(avg.dtype) 

502 complex256 

503 

504 With ``keepdims=True``, the following result has shape (3, 1). 

505 

506 >>> np.average(data, axis=1, keepdims=True) 

507 array([[0.5], 

508 [2.5], 

509 [4.5]]) 

510 """ 

511 a = np.asanyarray(a) 

512 

513 if keepdims is np._NoValue: 

514 # Don't pass on the keepdims argument if one wasn't given. 

515 keepdims_kw = {} 

516 else: 

517 keepdims_kw = {'keepdims': keepdims} 

518 

519 if weights is None: 

520 avg = a.mean(axis, **keepdims_kw) 

521 avg_as_array = np.asanyarray(avg) 

522 scl = avg_as_array.dtype.type(a.size/avg_as_array.size) 

523 else: 

524 wgt = np.asanyarray(weights) 

525 

526 if issubclass(a.dtype.type, (np.integer, np.bool_)): 

527 result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8') 

528 else: 

529 result_dtype = np.result_type(a.dtype, wgt.dtype) 

530 

531 # Sanity checks 

532 if a.shape != wgt.shape: 

533 if axis is None: 

534 raise TypeError( 

535 "Axis must be specified when shapes of a and weights " 

536 "differ.") 

537 if wgt.ndim != 1: 

538 raise TypeError( 

539 "1D weights expected when shapes of a and weights differ.") 

540 if wgt.shape[0] != a.shape[axis]: 

541 raise ValueError( 

542 "Length of weights not compatible with specified axis.") 

543 

544 # setup wgt to broadcast along axis 

545 wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape) 

546 wgt = wgt.swapaxes(-1, axis) 

547 

548 scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw) 

549 if np.any(scl == 0.0): 

550 raise ZeroDivisionError( 

551 "Weights sum to zero, can't be normalized") 

552 

553 avg = avg_as_array = np.multiply(a, wgt, 

554 dtype=result_dtype).sum(axis, **keepdims_kw) / scl 

555 

556 if returned: 

557 if scl.shape != avg_as_array.shape: 

558 scl = np.broadcast_to(scl, avg_as_array.shape).copy() 

559 return avg, scl 

560 else: 

561 return avg 

562 

563 

564@set_module('numpy') 

565def asarray_chkfinite(a, dtype=None, order=None): 

566 """Convert the input to an array, checking for NaNs or Infs. 

567 

568 Parameters 

569 ---------- 

570 a : array_like 

571 Input data, in any form that can be converted to an array. This 

572 includes lists, lists of tuples, tuples, tuples of tuples, tuples 

573 of lists and ndarrays. Success requires no NaNs or Infs. 

574 dtype : data-type, optional 

575 By default, the data-type is inferred from the input data. 

576 order : {'C', 'F', 'A', 'K'}, optional 

577 Memory layout. 'A' and 'K' depend on the order of input array a. 

578 'C' row-major (C-style), 

579 'F' column-major (Fortran-style) memory representation. 

580 'A' (any) means 'F' if `a` is Fortran contiguous, 'C' otherwise 

581 'K' (keep) preserve input order 

582 Defaults to 'C'. 

583 

584 Returns 

585 ------- 

586 out : ndarray 

587 Array interpretation of `a`. No copy is performed if the input 

588 is already an ndarray. If `a` is a subclass of ndarray, a base 

589 class ndarray is returned. 

590 

591 Raises 

592 ------ 

593 ValueError 

594 Raises ValueError if `a` contains NaN (Not a Number) or Inf (Infinity). 

595 

596 See Also 

597 -------- 

598 asarray : Create and array. 

599 asanyarray : Similar function which passes through subclasses. 

600 ascontiguousarray : Convert input to a contiguous array. 

601 asfarray : Convert input to a floating point ndarray. 

602 asfortranarray : Convert input to an ndarray with column-major 

603 memory order. 

604 fromiter : Create an array from an iterator. 

605 fromfunction : Construct an array by executing a function on grid 

606 positions. 

607 

608 Examples 

609 -------- 

610 Convert a list into an array. If all elements are finite 

611 ``asarray_chkfinite`` is identical to ``asarray``. 

612 

613 >>> a = [1, 2] 

614 >>> np.asarray_chkfinite(a, dtype=float) 

615 array([1., 2.]) 

616 

617 Raises ValueError if array_like contains Nans or Infs. 

618 

619 >>> a = [1, 2, np.inf] 

620 >>> try: 

621 ... np.asarray_chkfinite(a) 

622 ... except ValueError: 

623 ... print('ValueError') 

624 ... 

625 ValueError 

626 

627 """ 

628 a = asarray(a, dtype=dtype, order=order) 

629 if a.dtype.char in typecodes['AllFloat'] and not np.isfinite(a).all(): 

630 raise ValueError( 

631 "array must not contain infs or NaNs") 

632 return a 

633 

634 

635def _piecewise_dispatcher(x, condlist, funclist, *args, **kw): 

636 yield x 

637 # support the undocumented behavior of allowing scalars 

638 if np.iterable(condlist): 

639 yield from condlist 

640 

641 

642@array_function_dispatch(_piecewise_dispatcher) 

643def piecewise(x, condlist, funclist, *args, **kw): 

644 """ 

645 Evaluate a piecewise-defined function. 

646 

647 Given a set of conditions and corresponding functions, evaluate each 

648 function on the input data wherever its condition is true. 

649 

650 Parameters 

651 ---------- 

652 x : ndarray or scalar 

653 The input domain. 

654 condlist : list of bool arrays or bool scalars 

655 Each boolean array corresponds to a function in `funclist`. Wherever 

656 `condlist[i]` is True, `funclist[i](x)` is used as the output value. 

657 

658 Each boolean array in `condlist` selects a piece of `x`, 

659 and should therefore be of the same shape as `x`. 

660 

661 The length of `condlist` must correspond to that of `funclist`. 

662 If one extra function is given, i.e. if 

663 ``len(funclist) == len(condlist) + 1``, then that extra function 

664 is the default value, used wherever all conditions are false. 

665 funclist : list of callables, f(x,*args,**kw), or scalars 

666 Each function is evaluated over `x` wherever its corresponding 

667 condition is True. It should take a 1d array as input and give an 1d 

668 array or a scalar value as output. If, instead of a callable, 

669 a scalar is provided then a constant function (``lambda x: scalar``) is 

670 assumed. 

671 args : tuple, optional 

672 Any further arguments given to `piecewise` are passed to the functions 

673 upon execution, i.e., if called ``piecewise(..., ..., 1, 'a')``, then 

674 each function is called as ``f(x, 1, 'a')``. 

675 kw : dict, optional 

676 Keyword arguments used in calling `piecewise` are passed to the 

677 functions upon execution, i.e., if called 

678 ``piecewise(..., ..., alpha=1)``, then each function is called as 

679 ``f(x, alpha=1)``. 

680 

681 Returns 

682 ------- 

683 out : ndarray 

684 The output is the same shape and type as x and is found by 

685 calling the functions in `funclist` on the appropriate portions of `x`, 

686 as defined by the boolean arrays in `condlist`. Portions not covered 

687 by any condition have a default value of 0. 

688 

689 

690 See Also 

691 -------- 

692 choose, select, where 

693 

694 Notes 

695 ----- 

696 This is similar to choose or select, except that functions are 

697 evaluated on elements of `x` that satisfy the corresponding condition from 

698 `condlist`. 

699 

700 The result is:: 

701 

702 |-- 

703 |funclist[0](x[condlist[0]]) 

704 out = |funclist[1](x[condlist[1]]) 

705 |... 

706 |funclist[n2](x[condlist[n2]]) 

707 |-- 

708 

709 Examples 

710 -------- 

711 Define the sigma function, which is -1 for ``x < 0`` and +1 for ``x >= 0``. 

712 

713 >>> x = np.linspace(-2.5, 2.5, 6) 

714 >>> np.piecewise(x, [x < 0, x >= 0], [-1, 1]) 

715 array([-1., -1., -1., 1., 1., 1.]) 

716 

717 Define the absolute value, which is ``-x`` for ``x <0`` and ``x`` for 

718 ``x >= 0``. 

719 

720 >>> np.piecewise(x, [x < 0, x >= 0], [lambda x: -x, lambda x: x]) 

721 array([2.5, 1.5, 0.5, 0.5, 1.5, 2.5]) 

722 

723 Apply the same function to a scalar value. 

724 

725 >>> y = -2 

726 >>> np.piecewise(y, [y < 0, y >= 0], [lambda x: -x, lambda x: x]) 

727 array(2) 

728 

729 """ 

730 x = asanyarray(x) 

731 n2 = len(funclist) 

732 

733 # undocumented: single condition is promoted to a list of one condition 

734 if isscalar(condlist) or ( 

735 not isinstance(condlist[0], (list, ndarray)) and x.ndim != 0): 

736 condlist = [condlist] 

737 

738 condlist = asarray(condlist, dtype=bool) 

739 n = len(condlist) 

740 

741 if n == n2 - 1: # compute the "otherwise" condition. 

742 condelse = ~np.any(condlist, axis=0, keepdims=True) 

743 condlist = np.concatenate([condlist, condelse], axis=0) 

744 n += 1 

745 elif n != n2: 

746 raise ValueError( 

747 "with {} condition(s), either {} or {} functions are expected" 

748 .format(n, n, n+1) 

749 ) 

750 

751 y = zeros_like(x) 

752 for cond, func in zip(condlist, funclist): 

753 if not isinstance(func, collections.abc.Callable): 

754 y[cond] = func 

755 else: 

756 vals = x[cond] 

757 if vals.size > 0: 

758 y[cond] = func(vals, *args, **kw) 

759 

760 return y 

761 

762 

763def _select_dispatcher(condlist, choicelist, default=None): 

764 yield from condlist 

765 yield from choicelist 

766 

767 

768@array_function_dispatch(_select_dispatcher) 

769def select(condlist, choicelist, default=0): 

770 """ 

771 Return an array drawn from elements in choicelist, depending on conditions. 

772 

773 Parameters 

774 ---------- 

775 condlist : list of bool ndarrays 

776 The list of conditions which determine from which array in `choicelist` 

777 the output elements are taken. When multiple conditions are satisfied, 

778 the first one encountered in `condlist` is used. 

779 choicelist : list of ndarrays 

780 The list of arrays from which the output elements are taken. It has 

781 to be of the same length as `condlist`. 

782 default : scalar, optional 

783 The element inserted in `output` when all conditions evaluate to False. 

784 

785 Returns 

786 ------- 

787 output : ndarray 

788 The output at position m is the m-th element of the array in 

789 `choicelist` where the m-th element of the corresponding array in 

790 `condlist` is True. 

791 

792 See Also 

793 -------- 

794 where : Return elements from one of two arrays depending on condition. 

795 take, choose, compress, diag, diagonal 

796 

797 Examples 

798 -------- 

799 >>> x = np.arange(6) 

800 >>> condlist = [x<3, x>3] 

801 >>> choicelist = [x, x**2] 

802 >>> np.select(condlist, choicelist, 42) 

803 array([ 0, 1, 2, 42, 16, 25]) 

804 

805 >>> condlist = [x<=4, x>3] 

806 >>> choicelist = [x, x**2] 

807 >>> np.select(condlist, choicelist, 55) 

808 array([ 0, 1, 2, 3, 4, 25]) 

809 

810 """ 

811 # Check the size of condlist and choicelist are the same, or abort. 

812 if len(condlist) != len(choicelist): 

813 raise ValueError( 

814 'list of cases must be same length as list of conditions') 

815 

816 # Now that the dtype is known, handle the deprecated select([], []) case 

817 if len(condlist) == 0: 

818 raise ValueError("select with an empty condition list is not possible") 

819 

820 choicelist = [np.asarray(choice) for choice in choicelist] 

821 

822 try: 

823 intermediate_dtype = np.result_type(*choicelist) 

824 except TypeError as e: 

825 msg = f'Choicelist elements do not have a common dtype: {e}' 

826 raise TypeError(msg) from None 

827 default_array = np.asarray(default) 

828 choicelist.append(default_array) 

829 

830 # need to get the result type before broadcasting for correct scalar 

831 # behaviour 

832 try: 

833 dtype = np.result_type(intermediate_dtype, default_array) 

834 except TypeError as e: 

835 msg = f'Choicelists and default value do not have a common dtype: {e}' 

836 raise TypeError(msg) from None 

837 

838 # Convert conditions to arrays and broadcast conditions and choices 

839 # as the shape is needed for the result. Doing it separately optimizes 

840 # for example when all choices are scalars. 

841 condlist = np.broadcast_arrays(*condlist) 

842 choicelist = np.broadcast_arrays(*choicelist) 

843 

844 # If cond array is not an ndarray in boolean format or scalar bool, abort. 

845 for i, cond in enumerate(condlist): 

846 if cond.dtype.type is not np.bool_: 

847 raise TypeError( 

848 'invalid entry {} in condlist: should be boolean ndarray'.format(i)) 

849 

850 if choicelist[0].ndim == 0: 

851 # This may be common, so avoid the call. 

852 result_shape = condlist[0].shape 

853 else: 

854 result_shape = np.broadcast_arrays(condlist[0], choicelist[0])[0].shape 

855 

856 result = np.full(result_shape, choicelist[-1], dtype) 

857 

858 # Use np.copyto to burn each choicelist array onto result, using the 

859 # corresponding condlist as a boolean mask. This is done in reverse 

860 # order since the first choice should take precedence. 

861 choicelist = choicelist[-2::-1] 

862 condlist = condlist[::-1] 

863 for choice, cond in zip(choicelist, condlist): 

864 np.copyto(result, choice, where=cond) 

865 

866 return result 

867 

868 

869def _copy_dispatcher(a, order=None, subok=None): 

870 return (a,) 

871 

872 

873@array_function_dispatch(_copy_dispatcher) 

874def copy(a, order='K', subok=False): 

875 """ 

876 Return an array copy of the given object. 

877 

878 Parameters 

879 ---------- 

880 a : array_like 

881 Input data. 

882 order : {'C', 'F', 'A', 'K'}, optional 

883 Controls the memory layout of the copy. 'C' means C-order, 

884 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, 

885 'C' otherwise. 'K' means match the layout of `a` as closely 

886 as possible. (Note that this function and :meth:`ndarray.copy` are very 

887 similar, but have different default values for their order= 

888 arguments.) 

889 subok : bool, optional 

890 If True, then sub-classes will be passed-through, otherwise the 

891 returned array will be forced to be a base-class array (defaults to False). 

892 

893 .. versionadded:: 1.19.0 

894 

895 Returns 

896 ------- 

897 arr : ndarray 

898 Array interpretation of `a`. 

899 

900 See Also 

901 -------- 

902 ndarray.copy : Preferred method for creating an array copy 

903 

904 Notes 

905 ----- 

906 This is equivalent to: 

907 

908 >>> np.array(a, copy=True) #doctest: +SKIP 

909 

910 Examples 

911 -------- 

912 Create an array x, with a reference y and a copy z: 

913 

914 >>> x = np.array([1, 2, 3]) 

915 >>> y = x 

916 >>> z = np.copy(x) 

917 

918 Note that, when we modify x, y changes, but not z: 

919 

920 >>> x[0] = 10 

921 >>> x[0] == y[0] 

922 True 

923 >>> x[0] == z[0] 

924 False 

925 

926 Note that, np.copy clears previously set WRITEABLE=False flag. 

927 

928 >>> a = np.array([1, 2, 3]) 

929 >>> a.flags["WRITEABLE"] = False 

930 >>> b = np.copy(a) 

931 >>> b.flags["WRITEABLE"] 

932 True 

933 >>> b[0] = 3 

934 >>> b 

935 array([3, 2, 3]) 

936 

937 Note that np.copy is a shallow copy and will not copy object 

938 elements within arrays. This is mainly important for arrays 

939 containing Python objects. The new array will contain the 

940 same object which may lead to surprises if that object can 

941 be modified (is mutable): 

942 

943 >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object) 

944 >>> b = np.copy(a) 

945 >>> b[2][0] = 10 

946 >>> a 

947 array([1, 'm', list([10, 3, 4])], dtype=object) 

948 

949 To ensure all elements within an ``object`` array are copied, 

950 use `copy.deepcopy`: 

951 

952 >>> import copy 

953 >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object) 

954 >>> c = copy.deepcopy(a) 

955 >>> c[2][0] = 10 

956 >>> c 

957 array([1, 'm', list([10, 3, 4])], dtype=object) 

958 >>> a 

959 array([1, 'm', list([2, 3, 4])], dtype=object) 

960 

961 """ 

962 return array(a, order=order, subok=subok, copy=True) 

963 

964# Basic operations 

965 

966 

967def _gradient_dispatcher(f, *varargs, axis=None, edge_order=None): 

968 yield f 

969 yield from varargs 

970 

971 

972@array_function_dispatch(_gradient_dispatcher) 

973def gradient(f, *varargs, axis=None, edge_order=1): 

974 """ 

975 Return the gradient of an N-dimensional array. 

976 

977 The gradient is computed using second order accurate central differences 

978 in the interior points and either first or second order accurate one-sides 

979 (forward or backwards) differences at the boundaries. 

980 The returned gradient hence has the same shape as the input array. 

981 

982 Parameters 

983 ---------- 

984 f : array_like 

985 An N-dimensional array containing samples of a scalar function. 

986 varargs : list of scalar or array, optional 

987 Spacing between f values. Default unitary spacing for all dimensions. 

988 Spacing can be specified using: 

989 

990 1. single scalar to specify a sample distance for all dimensions. 

991 2. N scalars to specify a constant sample distance for each dimension. 

992 i.e. `dx`, `dy`, `dz`, ... 

993 3. N arrays to specify the coordinates of the values along each 

994 dimension of F. The length of the array must match the size of 

995 the corresponding dimension 

996 4. Any combination of N scalars/arrays with the meaning of 2. and 3. 

997 

998 If `axis` is given, the number of varargs must equal the number of axes. 

999 Default: 1. 

1000 

1001 edge_order : {1, 2}, optional 

1002 Gradient is calculated using N-th order accurate differences 

1003 at the boundaries. Default: 1. 

1004 

1005 .. versionadded:: 1.9.1 

1006 

1007 axis : None or int or tuple of ints, optional 

1008 Gradient is calculated only along the given axis or axes 

1009 The default (axis = None) is to calculate the gradient for all the axes 

1010 of the input array. axis may be negative, in which case it counts from 

1011 the last to the first axis. 

1012 

1013 .. versionadded:: 1.11.0 

1014 

1015 Returns 

1016 ------- 

1017 gradient : ndarray or list of ndarray 

1018 A list of ndarrays (or a single ndarray if there is only one dimension) 

1019 corresponding to the derivatives of f with respect to each dimension. 

1020 Each derivative has the same shape as f. 

1021 

1022 Examples 

1023 -------- 

1024 >>> f = np.array([1, 2, 4, 7, 11, 16], dtype=float) 

1025 >>> np.gradient(f) 

1026 array([1. , 1.5, 2.5, 3.5, 4.5, 5. ]) 

1027 >>> np.gradient(f, 2) 

1028 array([0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ]) 

1029 

1030 Spacing can be also specified with an array that represents the coordinates 

1031 of the values F along the dimensions. 

1032 For instance a uniform spacing: 

1033 

1034 >>> x = np.arange(f.size) 

1035 >>> np.gradient(f, x) 

1036 array([1. , 1.5, 2.5, 3.5, 4.5, 5. ]) 

1037 

1038 Or a non uniform one: 

1039 

1040 >>> x = np.array([0., 1., 1.5, 3.5, 4., 6.], dtype=float) 

1041 >>> np.gradient(f, x) 

1042 array([1. , 3. , 3.5, 6.7, 6.9, 2.5]) 

1043 

1044 For two dimensional arrays, the return will be two arrays ordered by 

1045 axis. In this example the first array stands for the gradient in 

1046 rows and the second one in columns direction: 

1047 

1048 >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float)) 

1049 [array([[ 2., 2., -1.], 

1050 [ 2., 2., -1.]]), array([[1. , 2.5, 4. ], 

1051 [1. , 1. , 1. ]])] 

1052 

1053 In this example the spacing is also specified: 

1054 uniform for axis=0 and non uniform for axis=1 

1055 

1056 >>> dx = 2. 

1057 >>> y = [1., 1.5, 3.5] 

1058 >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float), dx, y) 

1059 [array([[ 1. , 1. , -0.5], 

1060 [ 1. , 1. , -0.5]]), array([[2. , 2. , 2. ], 

1061 [2. , 1.7, 0.5]])] 

1062 

1063 It is possible to specify how boundaries are treated using `edge_order` 

1064 

1065 >>> x = np.array([0, 1, 2, 3, 4]) 

1066 >>> f = x**2 

1067 >>> np.gradient(f, edge_order=1) 

1068 array([1., 2., 4., 6., 7.]) 

1069 >>> np.gradient(f, edge_order=2) 

1070 array([0., 2., 4., 6., 8.]) 

1071 

1072 The `axis` keyword can be used to specify a subset of axes of which the 

1073 gradient is calculated 

1074 

1075 >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float), axis=0) 

1076 array([[ 2., 2., -1.], 

1077 [ 2., 2., -1.]]) 

1078 

1079 Notes 

1080 ----- 

1081 Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continuous 

1082 derivatives) and let :math:`h_{*}` be a non-homogeneous stepsize, we 

1083 minimize the "consistency error" :math:`\\eta_{i}` between the true gradient 

1084 and its estimate from a linear combination of the neighboring grid-points: 

1085 

1086 .. math:: 

1087 

1088 \\eta_{i} = f_{i}^{\\left(1\\right)} - 

1089 \\left[ \\alpha f\\left(x_{i}\\right) + 

1090 \\beta f\\left(x_{i} + h_{d}\\right) + 

1091 \\gamma f\\left(x_{i}-h_{s}\\right) 

1092 \\right] 

1093 

1094 By substituting :math:`f(x_{i} + h_{d})` and :math:`f(x_{i} - h_{s})` 

1095 with their Taylor series expansion, this translates into solving 

1096 the following the linear system: 

1097 

1098 .. math:: 

1099 

1100 \\left\\{ 

1101 \\begin{array}{r} 

1102 \\alpha+\\beta+\\gamma=0 \\\\ 

1103 \\beta h_{d}-\\gamma h_{s}=1 \\\\ 

1104 \\beta h_{d}^{2}+\\gamma h_{s}^{2}=0 

1105 \\end{array} 

1106 \\right. 

1107 

1108 The resulting approximation of :math:`f_{i}^{(1)}` is the following: 

1109 

1110 .. math:: 

1111 

1112 \\hat f_{i}^{(1)} = 

1113 \\frac{ 

1114 h_{s}^{2}f\\left(x_{i} + h_{d}\\right) 

1115 + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right) 

1116 - h_{d}^{2}f\\left(x_{i}-h_{s}\\right)} 

1117 { h_{s}h_{d}\\left(h_{d} + h_{s}\\right)} 

1118 + \\mathcal{O}\\left(\\frac{h_{d}h_{s}^{2} 

1119 + h_{s}h_{d}^{2}}{h_{d} 

1120 + h_{s}}\\right) 

1121 

1122 It is worth noting that if :math:`h_{s}=h_{d}` 

1123 (i.e., data are evenly spaced) 

1124 we find the standard second order approximation: 

1125 

1126 .. math:: 

1127 

1128 \\hat f_{i}^{(1)}= 

1129 \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h} 

1130 + \\mathcal{O}\\left(h^{2}\\right) 

1131 

1132 With a similar procedure the forward/backward approximations used for 

1133 boundaries can be derived. 

1134 

1135 References 

1136 ---------- 

1137 .. [1] Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics 

1138 (Texts in Applied Mathematics). New York: Springer. 

1139 .. [2] Durran D. R. (1999) Numerical Methods for Wave Equations 

1140 in Geophysical Fluid Dynamics. New York: Springer. 

1141 .. [3] Fornberg B. (1988) Generation of Finite Difference Formulas on 

1142 Arbitrarily Spaced Grids, 

1143 Mathematics of Computation 51, no. 184 : 699-706. 

1144 `PDF <http://www.ams.org/journals/mcom/1988-51-184/ 

1145 S0025-5718-1988-0935077-0/S0025-5718-1988-0935077-0.pdf>`_. 

1146 """ 

1147 f = np.asanyarray(f) 

1148 N = f.ndim # number of dimensions 

1149 

1150 if axis is None: 

1151 axes = tuple(range(N)) 

1152 else: 

1153 axes = _nx.normalize_axis_tuple(axis, N) 

1154 

1155 len_axes = len(axes) 

1156 n = len(varargs) 

1157 if n == 0: 

1158 # no spacing argument - use 1 in all axes 

1159 dx = [1.0] * len_axes 

1160 elif n == 1 and np.ndim(varargs[0]) == 0: 

1161 # single scalar for all axes 

1162 dx = varargs * len_axes 

1163 elif n == len_axes: 

1164 # scalar or 1d array for each axis 

1165 dx = list(varargs) 

1166 for i, distances in enumerate(dx): 

1167 distances = np.asanyarray(distances) 

1168 if distances.ndim == 0: 

1169 continue 

1170 elif distances.ndim != 1: 

1171 raise ValueError("distances must be either scalars or 1d") 

1172 if len(distances) != f.shape[axes[i]]: 

1173 raise ValueError("when 1d, distances must match " 

1174 "the length of the corresponding dimension") 

1175 if np.issubdtype(distances.dtype, np.integer): 

1176 # Convert numpy integer types to float64 to avoid modular 

1177 # arithmetic in np.diff(distances). 

1178 distances = distances.astype(np.float64) 

1179 diffx = np.diff(distances) 

1180 # if distances are constant reduce to the scalar case 

1181 # since it brings a consistent speedup 

1182 if (diffx == diffx[0]).all(): 

1183 diffx = diffx[0] 

1184 dx[i] = diffx 

1185 else: 

1186 raise TypeError("invalid number of arguments") 

1187 

1188 if edge_order > 2: 

1189 raise ValueError("'edge_order' greater than 2 not supported") 

1190 

1191 # use central differences on interior and one-sided differences on the 

1192 # endpoints. This preserves second order-accuracy over the full domain. 

1193 

1194 outvals = [] 

1195 

1196 # create slice objects --- initially all are [:, :, ..., :] 

1197 slice1 = [slice(None)]*N 

1198 slice2 = [slice(None)]*N 

1199 slice3 = [slice(None)]*N 

1200 slice4 = [slice(None)]*N 

1201 

1202 otype = f.dtype 

1203 if otype.type is np.datetime64: 

1204 # the timedelta dtype with the same unit information 

1205 otype = np.dtype(otype.name.replace('datetime', 'timedelta')) 

1206 # view as timedelta to allow addition 

1207 f = f.view(otype) 

1208 elif otype.type is np.timedelta64: 

1209 pass 

1210 elif np.issubdtype(otype, np.inexact): 

1211 pass 

1212 else: 

1213 # All other types convert to floating point. 

1214 # First check if f is a numpy integer type; if so, convert f to float64 

1215 # to avoid modular arithmetic when computing the changes in f. 

1216 if np.issubdtype(otype, np.integer): 

1217 f = f.astype(np.float64) 

1218 otype = np.float64 

1219 

1220 for axis, ax_dx in zip(axes, dx): 

1221 if f.shape[axis] < edge_order + 1: 

1222 raise ValueError( 

1223 "Shape of array too small to calculate a numerical gradient, " 

1224 "at least (edge_order + 1) elements are required.") 

1225 # result allocation 

1226 out = np.empty_like(f, dtype=otype) 

1227 

1228 # spacing for the current axis 

1229 uniform_spacing = np.ndim(ax_dx) == 0 

1230 

1231 # Numerical differentiation: 2nd order interior 

1232 slice1[axis] = slice(1, -1) 

1233 slice2[axis] = slice(None, -2) 

1234 slice3[axis] = slice(1, -1) 

1235 slice4[axis] = slice(2, None) 

1236 

1237 if uniform_spacing: 

1238 out[tuple(slice1)] = (f[tuple(slice4)] - f[tuple(slice2)]) / (2. * ax_dx) 

1239 else: 

1240 dx1 = ax_dx[0:-1] 

1241 dx2 = ax_dx[1:] 

1242 a = -(dx2)/(dx1 * (dx1 + dx2)) 

1243 b = (dx2 - dx1) / (dx1 * dx2) 

1244 c = dx1 / (dx2 * (dx1 + dx2)) 

1245 # fix the shape for broadcasting 

1246 shape = np.ones(N, dtype=int) 

1247 shape[axis] = -1 

1248 a.shape = b.shape = c.shape = shape 

1249 # 1D equivalent -- out[1:-1] = a * f[:-2] + b * f[1:-1] + c * f[2:] 

1250 out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)] 

1251 

1252 # Numerical differentiation: 1st order edges 

1253 if edge_order == 1: 

1254 slice1[axis] = 0 

1255 slice2[axis] = 1 

1256 slice3[axis] = 0 

1257 dx_0 = ax_dx if uniform_spacing else ax_dx[0] 

1258 # 1D equivalent -- out[0] = (f[1] - f[0]) / (x[1] - x[0]) 

1259 out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_0 

1260 

1261 slice1[axis] = -1 

1262 slice2[axis] = -1 

1263 slice3[axis] = -2 

1264 dx_n = ax_dx if uniform_spacing else ax_dx[-1] 

1265 # 1D equivalent -- out[-1] = (f[-1] - f[-2]) / (x[-1] - x[-2]) 

1266 out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_n 

1267 

1268 # Numerical differentiation: 2nd order edges 

1269 else: 

1270 slice1[axis] = 0 

1271 slice2[axis] = 0 

1272 slice3[axis] = 1 

1273 slice4[axis] = 2 

1274 if uniform_spacing: 

1275 a = -1.5 / ax_dx 

1276 b = 2. / ax_dx 

1277 c = -0.5 / ax_dx 

1278 else: 

1279 dx1 = ax_dx[0] 

1280 dx2 = ax_dx[1] 

1281 a = -(2. * dx1 + dx2)/(dx1 * (dx1 + dx2)) 

1282 b = (dx1 + dx2) / (dx1 * dx2) 

1283 c = - dx1 / (dx2 * (dx1 + dx2)) 

1284 # 1D equivalent -- out[0] = a * f[0] + b * f[1] + c * f[2] 

1285 out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)] 

1286 

1287 slice1[axis] = -1 

1288 slice2[axis] = -3 

1289 slice3[axis] = -2 

1290 slice4[axis] = -1 

1291 if uniform_spacing: 

1292 a = 0.5 / ax_dx 

1293 b = -2. / ax_dx 

1294 c = 1.5 / ax_dx 

1295 else: 

1296 dx1 = ax_dx[-2] 

1297 dx2 = ax_dx[-1] 

1298 a = (dx2) / (dx1 * (dx1 + dx2)) 

1299 b = - (dx2 + dx1) / (dx1 * dx2) 

1300 c = (2. * dx2 + dx1) / (dx2 * (dx1 + dx2)) 

1301 # 1D equivalent -- out[-1] = a * f[-3] + b * f[-2] + c * f[-1] 

1302 out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)] 

1303 

1304 outvals.append(out) 

1305 

1306 # reset the slice object in this dimension to ":" 

1307 slice1[axis] = slice(None) 

1308 slice2[axis] = slice(None) 

1309 slice3[axis] = slice(None) 

1310 slice4[axis] = slice(None) 

1311 

1312 if len_axes == 1: 

1313 return outvals[0] 

1314 elif np._using_numpy2_behavior(): 

1315 return tuple(outvals) 

1316 else: 

1317 return outvals 

1318 

1319 

1320def _diff_dispatcher(a, n=None, axis=None, prepend=None, append=None): 

1321 return (a, prepend, append) 

1322 

1323 

1324@array_function_dispatch(_diff_dispatcher) 

1325def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue): 

1326 """ 

1327 Calculate the n-th discrete difference along the given axis. 

1328 

1329 The first difference is given by ``out[i] = a[i+1] - a[i]`` along 

1330 the given axis, higher differences are calculated by using `diff` 

1331 recursively. 

1332 

1333 Parameters 

1334 ---------- 

1335 a : array_like 

1336 Input array 

1337 n : int, optional 

1338 The number of times values are differenced. If zero, the input 

1339 is returned as-is. 

1340 axis : int, optional 

1341 The axis along which the difference is taken, default is the 

1342 last axis. 

1343 prepend, append : array_like, optional 

1344 Values to prepend or append to `a` along axis prior to 

1345 performing the difference. Scalar values are expanded to 

1346 arrays with length 1 in the direction of axis and the shape 

1347 of the input array in along all other axes. Otherwise the 

1348 dimension and shape must match `a` except along axis. 

1349 

1350 .. versionadded:: 1.16.0 

1351 

1352 Returns 

1353 ------- 

1354 diff : ndarray 

1355 The n-th differences. The shape of the output is the same as `a` 

1356 except along `axis` where the dimension is smaller by `n`. The 

1357 type of the output is the same as the type of the difference 

1358 between any two elements of `a`. This is the same as the type of 

1359 `a` in most cases. A notable exception is `datetime64`, which 

1360 results in a `timedelta64` output array. 

1361 

1362 See Also 

1363 -------- 

1364 gradient, ediff1d, cumsum 

1365 

1366 Notes 

1367 ----- 

1368 Type is preserved for boolean arrays, so the result will contain 

1369 `False` when consecutive elements are the same and `True` when they 

1370 differ. 

1371 

1372 For unsigned integer arrays, the results will also be unsigned. This 

1373 should not be surprising, as the result is consistent with 

1374 calculating the difference directly: 

1375 

1376 >>> u8_arr = np.array([1, 0], dtype=np.uint8) 

1377 >>> np.diff(u8_arr) 

1378 array([255], dtype=uint8) 

1379 >>> u8_arr[1,...] - u8_arr[0,...] 

1380 255 

1381 

1382 If this is not desirable, then the array should be cast to a larger 

1383 integer type first: 

1384 

1385 >>> i16_arr = u8_arr.astype(np.int16) 

1386 >>> np.diff(i16_arr) 

1387 array([-1], dtype=int16) 

1388 

1389 Examples 

1390 -------- 

1391 >>> x = np.array([1, 2, 4, 7, 0]) 

1392 >>> np.diff(x) 

1393 array([ 1, 2, 3, -7]) 

1394 >>> np.diff(x, n=2) 

1395 array([ 1, 1, -10]) 

1396 

1397 >>> x = np.array([[1, 3, 6, 10], [0, 5, 6, 8]]) 

1398 >>> np.diff(x) 

1399 array([[2, 3, 4], 

1400 [5, 1, 2]]) 

1401 >>> np.diff(x, axis=0) 

1402 array([[-1, 2, 0, -2]]) 

1403 

1404 >>> x = np.arange('1066-10-13', '1066-10-16', dtype=np.datetime64) 

1405 >>> np.diff(x) 

1406 array([1, 1], dtype='timedelta64[D]') 

1407 

1408 """ 

1409 if n == 0: 

1410 return a 

1411 if n < 0: 

1412 raise ValueError( 

1413 "order must be non-negative but got " + repr(n)) 

1414 

1415 a = asanyarray(a) 

1416 nd = a.ndim 

1417 if nd == 0: 

1418 raise ValueError("diff requires input that is at least one dimensional") 

1419 axis = normalize_axis_index(axis, nd) 

1420 

1421 combined = [] 

1422 if prepend is not np._NoValue: 

1423 prepend = np.asanyarray(prepend) 

1424 if prepend.ndim == 0: 

1425 shape = list(a.shape) 

1426 shape[axis] = 1 

1427 prepend = np.broadcast_to(prepend, tuple(shape)) 

1428 combined.append(prepend) 

1429 

1430 combined.append(a) 

1431 

1432 if append is not np._NoValue: 

1433 append = np.asanyarray(append) 

1434 if append.ndim == 0: 

1435 shape = list(a.shape) 

1436 shape[axis] = 1 

1437 append = np.broadcast_to(append, tuple(shape)) 

1438 combined.append(append) 

1439 

1440 if len(combined) > 1: 

1441 a = np.concatenate(combined, axis) 

1442 

1443 slice1 = [slice(None)] * nd 

1444 slice2 = [slice(None)] * nd 

1445 slice1[axis] = slice(1, None) 

1446 slice2[axis] = slice(None, -1) 

1447 slice1 = tuple(slice1) 

1448 slice2 = tuple(slice2) 

1449 

1450 op = not_equal if a.dtype == np.bool_ else subtract 

1451 for _ in range(n): 

1452 a = op(a[slice1], a[slice2]) 

1453 

1454 return a 

1455 

1456 

1457def _interp_dispatcher(x, xp, fp, left=None, right=None, period=None): 

1458 return (x, xp, fp) 

1459 

1460 

1461@array_function_dispatch(_interp_dispatcher) 

1462def interp(x, xp, fp, left=None, right=None, period=None): 

1463 """ 

1464 One-dimensional linear interpolation for monotonically increasing sample points. 

1465 

1466 Returns the one-dimensional piecewise linear interpolant to a function 

1467 with given discrete data points (`xp`, `fp`), evaluated at `x`. 

1468 

1469 Parameters 

1470 ---------- 

1471 x : array_like 

1472 The x-coordinates at which to evaluate the interpolated values. 

1473 

1474 xp : 1-D sequence of floats 

1475 The x-coordinates of the data points, must be increasing if argument 

1476 `period` is not specified. Otherwise, `xp` is internally sorted after 

1477 normalizing the periodic boundaries with ``xp = xp % period``. 

1478 

1479 fp : 1-D sequence of float or complex 

1480 The y-coordinates of the data points, same length as `xp`. 

1481 

1482 left : optional float or complex corresponding to fp 

1483 Value to return for `x < xp[0]`, default is `fp[0]`. 

1484 

1485 right : optional float or complex corresponding to fp 

1486 Value to return for `x > xp[-1]`, default is `fp[-1]`. 

1487 

1488 period : None or float, optional 

1489 A period for the x-coordinates. This parameter allows the proper 

1490 interpolation of angular x-coordinates. Parameters `left` and `right` 

1491 are ignored if `period` is specified. 

1492 

1493 .. versionadded:: 1.10.0 

1494 

1495 Returns 

1496 ------- 

1497 y : float or complex (corresponding to fp) or ndarray 

1498 The interpolated values, same shape as `x`. 

1499 

1500 Raises 

1501 ------ 

1502 ValueError 

1503 If `xp` and `fp` have different length 

1504 If `xp` or `fp` are not 1-D sequences 

1505 If `period == 0` 

1506 

1507 See Also 

1508 -------- 

1509 scipy.interpolate 

1510 

1511 Warnings 

1512 -------- 

1513 The x-coordinate sequence is expected to be increasing, but this is not 

1514 explicitly enforced. However, if the sequence `xp` is non-increasing, 

1515 interpolation results are meaningless. 

1516 

1517 Note that, since NaN is unsortable, `xp` also cannot contain NaNs. 

1518 

1519 A simple check for `xp` being strictly increasing is:: 

1520 

1521 np.all(np.diff(xp) > 0) 

1522 

1523 Examples 

1524 -------- 

1525 >>> xp = [1, 2, 3] 

1526 >>> fp = [3, 2, 0] 

1527 >>> np.interp(2.5, xp, fp) 

1528 1.0 

1529 >>> np.interp([0, 1, 1.5, 2.72, 3.14], xp, fp) 

1530 array([3. , 3. , 2.5 , 0.56, 0. ]) 

1531 >>> UNDEF = -99.0 

1532 >>> np.interp(3.14, xp, fp, right=UNDEF) 

1533 -99.0 

1534 

1535 Plot an interpolant to the sine function: 

1536 

1537 >>> x = np.linspace(0, 2*np.pi, 10) 

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

1539 >>> xvals = np.linspace(0, 2*np.pi, 50) 

1540 >>> yinterp = np.interp(xvals, x, y) 

1541 >>> import matplotlib.pyplot as plt 

1542 >>> plt.plot(x, y, 'o') 

1543 [<matplotlib.lines.Line2D object at 0x...>] 

1544 >>> plt.plot(xvals, yinterp, '-x') 

1545 [<matplotlib.lines.Line2D object at 0x...>] 

1546 >>> plt.show() 

1547 

1548 Interpolation with periodic x-coordinates: 

1549 

1550 >>> x = [-180, -170, -185, 185, -10, -5, 0, 365] 

1551 >>> xp = [190, -190, 350, -350] 

1552 >>> fp = [5, 10, 3, 4] 

1553 >>> np.interp(x, xp, fp, period=360) 

1554 array([7.5 , 5. , 8.75, 6.25, 3. , 3.25, 3.5 , 3.75]) 

1555 

1556 Complex interpolation: 

1557 

1558 >>> x = [1.5, 4.0] 

1559 >>> xp = [2,3,5] 

1560 >>> fp = [1.0j, 0, 2+3j] 

1561 >>> np.interp(x, xp, fp) 

1562 array([0.+1.j , 1.+1.5j]) 

1563 

1564 """ 

1565 

1566 fp = np.asarray(fp) 

1567 

1568 if np.iscomplexobj(fp): 

1569 interp_func = compiled_interp_complex 

1570 input_dtype = np.complex128 

1571 else: 

1572 interp_func = compiled_interp 

1573 input_dtype = np.float64 

1574 

1575 if period is not None: 

1576 if period == 0: 

1577 raise ValueError("period must be a non-zero value") 

1578 period = abs(period) 

1579 left = None 

1580 right = None 

1581 

1582 x = np.asarray(x, dtype=np.float64) 

1583 xp = np.asarray(xp, dtype=np.float64) 

1584 fp = np.asarray(fp, dtype=input_dtype) 

1585 

1586 if xp.ndim != 1 or fp.ndim != 1: 

1587 raise ValueError("Data points must be 1-D sequences") 

1588 if xp.shape[0] != fp.shape[0]: 

1589 raise ValueError("fp and xp are not of the same length") 

1590 # normalizing periodic boundaries 

1591 x = x % period 

1592 xp = xp % period 

1593 asort_xp = np.argsort(xp) 

1594 xp = xp[asort_xp] 

1595 fp = fp[asort_xp] 

1596 xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period)) 

1597 fp = np.concatenate((fp[-1:], fp, fp[0:1])) 

1598 

1599 return interp_func(x, xp, fp, left, right) 

1600 

1601 

1602def _angle_dispatcher(z, deg=None): 

1603 return (z,) 

1604 

1605 

1606@array_function_dispatch(_angle_dispatcher) 

1607def angle(z, deg=False): 

1608 """ 

1609 Return the angle of the complex argument. 

1610 

1611 Parameters 

1612 ---------- 

1613 z : array_like 

1614 A complex number or sequence of complex numbers. 

1615 deg : bool, optional 

1616 Return angle in degrees if True, radians if False (default). 

1617 

1618 Returns 

1619 ------- 

1620 angle : ndarray or scalar 

1621 The counterclockwise angle from the positive real axis on the complex 

1622 plane in the range ``(-pi, pi]``, with dtype as numpy.float64. 

1623 

1624 .. versionchanged:: 1.16.0 

1625 This function works on subclasses of ndarray like `ma.array`. 

1626 

1627 See Also 

1628 -------- 

1629 arctan2 

1630 absolute 

1631 

1632 Notes 

1633 ----- 

1634 Although the angle of the complex number 0 is undefined, ``numpy.angle(0)`` 

1635 returns the value 0. 

1636 

1637 Examples 

1638 -------- 

1639 >>> np.angle([1.0, 1.0j, 1+1j]) # in radians 

1640 array([ 0. , 1.57079633, 0.78539816]) # may vary 

1641 >>> np.angle(1+1j, deg=True) # in degrees 

1642 45.0 

1643 

1644 """ 

1645 z = asanyarray(z) 

1646 if issubclass(z.dtype.type, _nx.complexfloating): 

1647 zimag = z.imag 

1648 zreal = z.real 

1649 else: 

1650 zimag = 0 

1651 zreal = z 

1652 

1653 a = arctan2(zimag, zreal) 

1654 if deg: 

1655 a *= 180/pi 

1656 return a 

1657 

1658 

1659def _unwrap_dispatcher(p, discont=None, axis=None, *, period=None): 

1660 return (p,) 

1661 

1662 

1663@array_function_dispatch(_unwrap_dispatcher) 

1664def unwrap(p, discont=None, axis=-1, *, period=2*pi): 

1665 r""" 

1666 Unwrap by taking the complement of large deltas with respect to the period. 

1667 

1668 This unwraps a signal `p` by changing elements which have an absolute 

1669 difference from their predecessor of more than ``max(discont, period/2)`` 

1670 to their `period`-complementary values. 

1671 

1672 For the default case where `period` is :math:`2\pi` and `discont` is 

1673 :math:`\pi`, this unwraps a radian phase `p` such that adjacent differences 

1674 are never greater than :math:`\pi` by adding :math:`2k\pi` for some 

1675 integer :math:`k`. 

1676 

1677 Parameters 

1678 ---------- 

1679 p : array_like 

1680 Input array. 

1681 discont : float, optional 

1682 Maximum discontinuity between values, default is ``period/2``. 

1683 Values below ``period/2`` are treated as if they were ``period/2``. 

1684 To have an effect different from the default, `discont` should be 

1685 larger than ``period/2``. 

1686 axis : int, optional 

1687 Axis along which unwrap will operate, default is the last axis. 

1688 period : float, optional 

1689 Size of the range over which the input wraps. By default, it is 

1690 ``2 pi``. 

1691 

1692 .. versionadded:: 1.21.0 

1693 

1694 Returns 

1695 ------- 

1696 out : ndarray 

1697 Output array. 

1698 

1699 See Also 

1700 -------- 

1701 rad2deg, deg2rad 

1702 

1703 Notes 

1704 ----- 

1705 If the discontinuity in `p` is smaller than ``period/2``, 

1706 but larger than `discont`, no unwrapping is done because taking 

1707 the complement would only make the discontinuity larger. 

1708 

1709 Examples 

1710 -------- 

1711 >>> phase = np.linspace(0, np.pi, num=5) 

1712 >>> phase[3:] += np.pi 

1713 >>> phase 

1714 array([ 0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531]) # may vary 

1715 >>> np.unwrap(phase) 

1716 array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ]) # may vary 

1717 >>> np.unwrap([0, 1, 2, -1, 0], period=4) 

1718 array([0, 1, 2, 3, 4]) 

1719 >>> np.unwrap([ 1, 2, 3, 4, 5, 6, 1, 2, 3], period=6) 

1720 array([1, 2, 3, 4, 5, 6, 7, 8, 9]) 

1721 >>> np.unwrap([2, 3, 4, 5, 2, 3, 4, 5], period=4) 

1722 array([2, 3, 4, 5, 6, 7, 8, 9]) 

1723 >>> phase_deg = np.mod(np.linspace(0 ,720, 19), 360) - 180 

1724 >>> np.unwrap(phase_deg, period=360) 

1725 array([-180., -140., -100., -60., -20., 20., 60., 100., 140., 

1726 180., 220., 260., 300., 340., 380., 420., 460., 500., 

1727 540.]) 

1728 """ 

1729 p = asarray(p) 

1730 nd = p.ndim 

1731 dd = diff(p, axis=axis) 

1732 if discont is None: 

1733 discont = period/2 

1734 slice1 = [slice(None, None)]*nd # full slices 

1735 slice1[axis] = slice(1, None) 

1736 slice1 = tuple(slice1) 

1737 dtype = np.result_type(dd, period) 

1738 if _nx.issubdtype(dtype, _nx.integer): 

1739 interval_high, rem = divmod(period, 2) 

1740 boundary_ambiguous = rem == 0 

1741 else: 

1742 interval_high = period / 2 

1743 boundary_ambiguous = True 

1744 interval_low = -interval_high 

1745 ddmod = mod(dd - interval_low, period) + interval_low 

1746 if boundary_ambiguous: 

1747 # for `mask = (abs(dd) == period/2)`, the above line made 

1748 # `ddmod[mask] == -period/2`. correct these such that 

1749 # `ddmod[mask] == sign(dd[mask])*period/2`. 

1750 _nx.copyto(ddmod, interval_high, 

1751 where=(ddmod == interval_low) & (dd > 0)) 

1752 ph_correct = ddmod - dd 

1753 _nx.copyto(ph_correct, 0, where=abs(dd) < discont) 

1754 up = array(p, copy=True, dtype=dtype) 

1755 up[slice1] = p[slice1] + ph_correct.cumsum(axis) 

1756 return up 

1757 

1758 

1759def _sort_complex(a): 

1760 return (a,) 

1761 

1762 

1763@array_function_dispatch(_sort_complex) 

1764def sort_complex(a): 

1765 """ 

1766 Sort a complex array using the real part first, then the imaginary part. 

1767 

1768 Parameters 

1769 ---------- 

1770 a : array_like 

1771 Input array 

1772 

1773 Returns 

1774 ------- 

1775 out : complex ndarray 

1776 Always returns a sorted complex array. 

1777 

1778 Examples 

1779 -------- 

1780 >>> np.sort_complex([5, 3, 6, 2, 1]) 

1781 array([1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j]) 

1782 

1783 >>> np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j]) 

1784 array([1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j]) 

1785 

1786 """ 

1787 b = array(a, copy=True) 

1788 b.sort() 

1789 if not issubclass(b.dtype.type, _nx.complexfloating): 

1790 if b.dtype.char in 'bhBH': 

1791 return b.astype('F') 

1792 elif b.dtype.char == 'g': 

1793 return b.astype('G') 

1794 else: 

1795 return b.astype('D') 

1796 else: 

1797 return b 

1798 

1799 

1800def _trim_zeros(filt, trim=None): 

1801 return (filt,) 

1802 

1803 

1804@array_function_dispatch(_trim_zeros) 

1805def trim_zeros(filt, trim='fb'): 

1806 """ 

1807 Trim the leading and/or trailing zeros from a 1-D array or sequence. 

1808 

1809 Parameters 

1810 ---------- 

1811 filt : 1-D array or sequence 

1812 Input array. 

1813 trim : str, optional 

1814 A string with 'f' representing trim from front and 'b' to trim from 

1815 back. Default is 'fb', trim zeros from both front and back of the 

1816 array. 

1817 

1818 Returns 

1819 ------- 

1820 trimmed : 1-D array or sequence 

1821 The result of trimming the input. The input data type is preserved. 

1822 

1823 Examples 

1824 -------- 

1825 >>> a = np.array((0, 0, 0, 1, 2, 3, 0, 2, 1, 0)) 

1826 >>> np.trim_zeros(a) 

1827 array([1, 2, 3, 0, 2, 1]) 

1828 

1829 >>> np.trim_zeros(a, 'b') 

1830 array([0, 0, 0, ..., 0, 2, 1]) 

1831 

1832 The input data type is preserved, list/tuple in means list/tuple out. 

1833 

1834 >>> np.trim_zeros([0, 1, 2, 0]) 

1835 [1, 2] 

1836 

1837 """ 

1838 

1839 first = 0 

1840 trim = trim.upper() 

1841 if 'F' in trim: 

1842 for i in filt: 

1843 if i != 0.: 

1844 break 

1845 else: 

1846 first = first + 1 

1847 last = len(filt) 

1848 if 'B' in trim: 

1849 for i in filt[::-1]: 

1850 if i != 0.: 

1851 break 

1852 else: 

1853 last = last - 1 

1854 return filt[first:last] 

1855 

1856 

1857def _extract_dispatcher(condition, arr): 

1858 return (condition, arr) 

1859 

1860 

1861@array_function_dispatch(_extract_dispatcher) 

1862def extract(condition, arr): 

1863 """ 

1864 Return the elements of an array that satisfy some condition. 

1865 

1866 This is equivalent to ``np.compress(ravel(condition), ravel(arr))``. If 

1867 `condition` is boolean ``np.extract`` is equivalent to ``arr[condition]``. 

1868 

1869 Note that `place` does the exact opposite of `extract`. 

1870 

1871 Parameters 

1872 ---------- 

1873 condition : array_like 

1874 An array whose nonzero or True entries indicate the elements of `arr` 

1875 to extract. 

1876 arr : array_like 

1877 Input array of the same size as `condition`. 

1878 

1879 Returns 

1880 ------- 

1881 extract : ndarray 

1882 Rank 1 array of values from `arr` where `condition` is True. 

1883 

1884 See Also 

1885 -------- 

1886 take, put, copyto, compress, place 

1887 

1888 Examples 

1889 -------- 

1890 >>> arr = np.arange(12).reshape((3, 4)) 

1891 >>> arr 

1892 array([[ 0, 1, 2, 3], 

1893 [ 4, 5, 6, 7], 

1894 [ 8, 9, 10, 11]]) 

1895 >>> condition = np.mod(arr, 3)==0 

1896 >>> condition 

1897 array([[ True, False, False, True], 

1898 [False, False, True, False], 

1899 [False, True, False, False]]) 

1900 >>> np.extract(condition, arr) 

1901 array([0, 3, 6, 9]) 

1902 

1903 

1904 If `condition` is boolean: 

1905 

1906 >>> arr[condition] 

1907 array([0, 3, 6, 9]) 

1908 

1909 """ 

1910 return _nx.take(ravel(arr), nonzero(ravel(condition))[0]) 

1911 

1912 

1913def _place_dispatcher(arr, mask, vals): 

1914 return (arr, mask, vals) 

1915 

1916 

1917@array_function_dispatch(_place_dispatcher) 

1918def place(arr, mask, vals): 

1919 """ 

1920 Change elements of an array based on conditional and input values. 

1921 

1922 Similar to ``np.copyto(arr, vals, where=mask)``, the difference is that 

1923 `place` uses the first N elements of `vals`, where N is the number of 

1924 True values in `mask`, while `copyto` uses the elements where `mask` 

1925 is True. 

1926 

1927 Note that `extract` does the exact opposite of `place`. 

1928 

1929 Parameters 

1930 ---------- 

1931 arr : ndarray 

1932 Array to put data into. 

1933 mask : array_like 

1934 Boolean mask array. Must have the same size as `a`. 

1935 vals : 1-D sequence 

1936 Values to put into `a`. Only the first N elements are used, where 

1937 N is the number of True values in `mask`. If `vals` is smaller 

1938 than N, it will be repeated, and if elements of `a` are to be masked, 

1939 this sequence must be non-empty. 

1940 

1941 See Also 

1942 -------- 

1943 copyto, put, take, extract 

1944 

1945 Examples 

1946 -------- 

1947 >>> arr = np.arange(6).reshape(2, 3) 

1948 >>> np.place(arr, arr>2, [44, 55]) 

1949 >>> arr 

1950 array([[ 0, 1, 2], 

1951 [44, 55, 44]]) 

1952 

1953 """ 

1954 return _place(arr, mask, vals) 

1955 

1956 

1957def disp(mesg, device=None, linefeed=True): 

1958 """ 

1959 Display a message on a device. 

1960 

1961 Parameters 

1962 ---------- 

1963 mesg : str 

1964 Message to display. 

1965 device : object 

1966 Device to write message. If None, defaults to ``sys.stdout`` which is 

1967 very similar to ``print``. `device` needs to have ``write()`` and 

1968 ``flush()`` methods. 

1969 linefeed : bool, optional 

1970 Option whether to print a line feed or not. Defaults to True. 

1971 

1972 Raises 

1973 ------ 

1974 AttributeError 

1975 If `device` does not have a ``write()`` or ``flush()`` method. 

1976 

1977 Examples 

1978 -------- 

1979 Besides ``sys.stdout``, a file-like object can also be used as it has 

1980 both required methods: 

1981 

1982 >>> from io import StringIO 

1983 >>> buf = StringIO() 

1984 >>> np.disp(u'"Display" in a file', device=buf) 

1985 >>> buf.getvalue() 

1986 '"Display" in a file\\n' 

1987 

1988 """ 

1989 if device is None: 

1990 device = sys.stdout 

1991 if linefeed: 

1992 device.write('%s\n' % mesg) 

1993 else: 

1994 device.write('%s' % mesg) 

1995 device.flush() 

1996 return 

1997 

1998 

1999# See https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html 

2000_DIMENSION_NAME = r'\w+' 

2001_CORE_DIMENSION_LIST = '(?:{0:}(?:,{0:})*)?'.format(_DIMENSION_NAME) 

2002_ARGUMENT = r'\({}\)'.format(_CORE_DIMENSION_LIST) 

2003_ARGUMENT_LIST = '{0:}(?:,{0:})*'.format(_ARGUMENT) 

2004_SIGNATURE = '^{0:}->{0:}$'.format(_ARGUMENT_LIST) 

2005 

2006 

2007def _parse_gufunc_signature(signature): 

2008 """ 

2009 Parse string signatures for a generalized universal function. 

2010 

2011 Arguments 

2012 --------- 

2013 signature : string 

2014 Generalized universal function signature, e.g., ``(m,n),(n,p)->(m,p)`` 

2015 for ``np.matmul``. 

2016 

2017 Returns 

2018 ------- 

2019 Tuple of input and output core dimensions parsed from the signature, each 

2020 of the form List[Tuple[str, ...]]. 

2021 """ 

2022 signature = re.sub(r'\s+', '', signature) 

2023 

2024 if not re.match(_SIGNATURE, signature): 

2025 raise ValueError( 

2026 'not a valid gufunc signature: {}'.format(signature)) 

2027 return tuple([tuple(re.findall(_DIMENSION_NAME, arg)) 

2028 for arg in re.findall(_ARGUMENT, arg_list)] 

2029 for arg_list in signature.split('->')) 

2030 

2031 

2032def _update_dim_sizes(dim_sizes, arg, core_dims): 

2033 """ 

2034 Incrementally check and update core dimension sizes for a single argument. 

2035 

2036 Arguments 

2037 --------- 

2038 dim_sizes : Dict[str, int] 

2039 Sizes of existing core dimensions. Will be updated in-place. 

2040 arg : ndarray 

2041 Argument to examine. 

2042 core_dims : Tuple[str, ...] 

2043 Core dimensions for this argument. 

2044 """ 

2045 if not core_dims: 

2046 return 

2047 

2048 num_core_dims = len(core_dims) 

2049 if arg.ndim < num_core_dims: 

2050 raise ValueError( 

2051 '%d-dimensional argument does not have enough ' 

2052 'dimensions for all core dimensions %r' 

2053 % (arg.ndim, core_dims)) 

2054 

2055 core_shape = arg.shape[-num_core_dims:] 

2056 for dim, size in zip(core_dims, core_shape): 

2057 if dim in dim_sizes: 

2058 if size != dim_sizes[dim]: 

2059 raise ValueError( 

2060 'inconsistent size for core dimension %r: %r vs %r' 

2061 % (dim, size, dim_sizes[dim])) 

2062 else: 

2063 dim_sizes[dim] = size 

2064 

2065 

2066def _parse_input_dimensions(args, input_core_dims): 

2067 """ 

2068 Parse broadcast and core dimensions for vectorize with a signature. 

2069 

2070 Arguments 

2071 --------- 

2072 args : Tuple[ndarray, ...] 

2073 Tuple of input arguments to examine. 

2074 input_core_dims : List[Tuple[str, ...]] 

2075 List of core dimensions corresponding to each input. 

2076 

2077 Returns 

2078 ------- 

2079 broadcast_shape : Tuple[int, ...] 

2080 Common shape to broadcast all non-core dimensions to. 

2081 dim_sizes : Dict[str, int] 

2082 Common sizes for named core dimensions. 

2083 """ 

2084 broadcast_args = [] 

2085 dim_sizes = {} 

2086 for arg, core_dims in zip(args, input_core_dims): 

2087 _update_dim_sizes(dim_sizes, arg, core_dims) 

2088 ndim = arg.ndim - len(core_dims) 

2089 dummy_array = np.lib.stride_tricks.as_strided(0, arg.shape[:ndim]) 

2090 broadcast_args.append(dummy_array) 

2091 broadcast_shape = np.lib.stride_tricks._broadcast_shape(*broadcast_args) 

2092 return broadcast_shape, dim_sizes 

2093 

2094 

2095def _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims): 

2096 """Helper for calculating broadcast shapes with core dimensions.""" 

2097 return [broadcast_shape + tuple(dim_sizes[dim] for dim in core_dims) 

2098 for core_dims in list_of_core_dims] 

2099 

2100 

2101def _create_arrays(broadcast_shape, dim_sizes, list_of_core_dims, dtypes, 

2102 results=None): 

2103 """Helper for creating output arrays in vectorize.""" 

2104 shapes = _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims) 

2105 if dtypes is None: 

2106 dtypes = [None] * len(shapes) 

2107 if results is None: 

2108 arrays = tuple(np.empty(shape=shape, dtype=dtype) 

2109 for shape, dtype in zip(shapes, dtypes)) 

2110 else: 

2111 arrays = tuple(np.empty_like(result, shape=shape, dtype=dtype) 

2112 for result, shape, dtype 

2113 in zip(results, shapes, dtypes)) 

2114 return arrays 

2115 

2116 

2117@set_module('numpy') 

2118class vectorize: 

2119 """ 

2120 vectorize(pyfunc=np._NoValue, otypes=None, doc=None, excluded=None, 

2121 cache=False, signature=None) 

2122 

2123 Returns an object that acts like pyfunc, but takes arrays as input. 

2124 

2125 Define a vectorized function which takes a nested sequence of objects or 

2126 numpy arrays as inputs and returns a single numpy array or a tuple of numpy 

2127 arrays. The vectorized function evaluates `pyfunc` over successive tuples 

2128 of the input arrays like the python map function, except it uses the 

2129 broadcasting rules of numpy. 

2130 

2131 The data type of the output of `vectorized` is determined by calling 

2132 the function with the first element of the input. This can be avoided 

2133 by specifying the `otypes` argument. 

2134 

2135 Parameters 

2136 ---------- 

2137 pyfunc : callable, optional 

2138 A python function or method. 

2139 Can be omitted to produce a decorator with keyword arguments. 

2140 otypes : str or list of dtypes, optional 

2141 The output data type. It must be specified as either a string of 

2142 typecode characters or a list of data type specifiers. There should 

2143 be one data type specifier for each output. 

2144 doc : str, optional 

2145 The docstring for the function. If None, the docstring will be the 

2146 ``pyfunc.__doc__``. 

2147 excluded : set, optional 

2148 Set of strings or integers representing the positional or keyword 

2149 arguments for which the function will not be vectorized. These will be 

2150 passed directly to `pyfunc` unmodified. 

2151 

2152 .. versionadded:: 1.7.0 

2153 

2154 cache : bool, optional 

2155 If `True`, then cache the first function call that determines the number 

2156 of outputs if `otypes` is not provided. 

2157 

2158 .. versionadded:: 1.7.0 

2159 

2160 signature : string, optional 

2161 Generalized universal function signature, e.g., ``(m,n),(n)->(m)`` for 

2162 vectorized matrix-vector multiplication. If provided, ``pyfunc`` will 

2163 be called with (and expected to return) arrays with shapes given by the 

2164 size of corresponding core dimensions. By default, ``pyfunc`` is 

2165 assumed to take scalars as input and output. 

2166 

2167 .. versionadded:: 1.12.0 

2168 

2169 Returns 

2170 ------- 

2171 out : callable 

2172 A vectorized function if ``pyfunc`` was provided, 

2173 a decorator otherwise. 

2174 

2175 See Also 

2176 -------- 

2177 frompyfunc : Takes an arbitrary Python function and returns a ufunc 

2178 

2179 Notes 

2180 ----- 

2181 The `vectorize` function is provided primarily for convenience, not for 

2182 performance. The implementation is essentially a for loop. 

2183 

2184 If `otypes` is not specified, then a call to the function with the 

2185 first argument will be used to determine the number of outputs. The 

2186 results of this call will be cached if `cache` is `True` to prevent 

2187 calling the function twice. However, to implement the cache, the 

2188 original function must be wrapped which will slow down subsequent 

2189 calls, so only do this if your function is expensive. 

2190 

2191 The new keyword argument interface and `excluded` argument support 

2192 further degrades performance. 

2193 

2194 References 

2195 ---------- 

2196 .. [1] :doc:`/reference/c-api/generalized-ufuncs` 

2197 

2198 Examples 

2199 -------- 

2200 >>> def myfunc(a, b): 

2201 ... "Return a-b if a>b, otherwise return a+b" 

2202 ... if a > b: 

2203 ... return a - b 

2204 ... else: 

2205 ... return a + b 

2206 

2207 >>> vfunc = np.vectorize(myfunc) 

2208 >>> vfunc([1, 2, 3, 4], 2) 

2209 array([3, 4, 1, 2]) 

2210 

2211 The docstring is taken from the input function to `vectorize` unless it 

2212 is specified: 

2213 

2214 >>> vfunc.__doc__ 

2215 'Return a-b if a>b, otherwise return a+b' 

2216 >>> vfunc = np.vectorize(myfunc, doc='Vectorized `myfunc`') 

2217 >>> vfunc.__doc__ 

2218 'Vectorized `myfunc`' 

2219 

2220 The output type is determined by evaluating the first element of the input, 

2221 unless it is specified: 

2222 

2223 >>> out = vfunc([1, 2, 3, 4], 2) 

2224 >>> type(out[0]) 

2225 <class 'numpy.int64'> 

2226 >>> vfunc = np.vectorize(myfunc, otypes=[float]) 

2227 >>> out = vfunc([1, 2, 3, 4], 2) 

2228 >>> type(out[0]) 

2229 <class 'numpy.float64'> 

2230 

2231 The `excluded` argument can be used to prevent vectorizing over certain 

2232 arguments. This can be useful for array-like arguments of a fixed length 

2233 such as the coefficients for a polynomial as in `polyval`: 

2234 

2235 >>> def mypolyval(p, x): 

2236 ... _p = list(p) 

2237 ... res = _p.pop(0) 

2238 ... while _p: 

2239 ... res = res*x + _p.pop(0) 

2240 ... return res 

2241 >>> vpolyval = np.vectorize(mypolyval, excluded=['p']) 

2242 >>> vpolyval(p=[1, 2, 3], x=[0, 1]) 

2243 array([3, 6]) 

2244 

2245 Positional arguments may also be excluded by specifying their position: 

2246 

2247 >>> vpolyval.excluded.add(0) 

2248 >>> vpolyval([1, 2, 3], x=[0, 1]) 

2249 array([3, 6]) 

2250 

2251 The `signature` argument allows for vectorizing functions that act on 

2252 non-scalar arrays of fixed length. For example, you can use it for a 

2253 vectorized calculation of Pearson correlation coefficient and its p-value: 

2254 

2255 >>> import scipy.stats 

2256 >>> pearsonr = np.vectorize(scipy.stats.pearsonr, 

2257 ... signature='(n),(n)->(),()') 

2258 >>> pearsonr([[0, 1, 2, 3]], [[1, 2, 3, 4], [4, 3, 2, 1]]) 

2259 (array([ 1., -1.]), array([ 0., 0.])) 

2260 

2261 Or for a vectorized convolution: 

2262 

2263 >>> convolve = np.vectorize(np.convolve, signature='(n),(m)->(k)') 

2264 >>> convolve(np.eye(4), [1, 2, 1]) 

2265 array([[1., 2., 1., 0., 0., 0.], 

2266 [0., 1., 2., 1., 0., 0.], 

2267 [0., 0., 1., 2., 1., 0.], 

2268 [0., 0., 0., 1., 2., 1.]]) 

2269 

2270 Decorator syntax is supported. The decorator can be called as 

2271 a function to provide keyword arguments. 

2272 >>>@np.vectorize 

2273 ...def identity(x): 

2274 ... return x 

2275 ... 

2276 >>>identity([0, 1, 2]) 

2277 array([0, 1, 2]) 

2278 >>>@np.vectorize(otypes=[float]) 

2279 ...def as_float(x): 

2280 ... return x 

2281 ... 

2282 >>>as_float([0, 1, 2]) 

2283 array([0., 1., 2.]) 

2284 """ 

2285 def __init__(self, pyfunc=np._NoValue, otypes=None, doc=None, 

2286 excluded=None, cache=False, signature=None): 

2287 

2288 if (pyfunc != np._NoValue) and (not callable(pyfunc)): 

2289 #Splitting the error message to keep 

2290 #the length below 79 characters. 

2291 part1 = "When used as a decorator, " 

2292 part2 = "only accepts keyword arguments." 

2293 raise TypeError(part1 + part2) 

2294 

2295 self.pyfunc = pyfunc 

2296 self.cache = cache 

2297 self.signature = signature 

2298 if pyfunc != np._NoValue and hasattr(pyfunc, '__name__'): 

2299 self.__name__ = pyfunc.__name__ 

2300 

2301 self._ufunc = {} # Caching to improve default performance 

2302 self._doc = None 

2303 self.__doc__ = doc 

2304 if doc is None and hasattr(pyfunc, '__doc__'): 

2305 self.__doc__ = pyfunc.__doc__ 

2306 else: 

2307 self._doc = doc 

2308 

2309 if isinstance(otypes, str): 

2310 for char in otypes: 

2311 if char not in typecodes['All']: 

2312 raise ValueError("Invalid otype specified: %s" % (char,)) 

2313 elif iterable(otypes): 

2314 otypes = ''.join([_nx.dtype(x).char for x in otypes]) 

2315 elif otypes is not None: 

2316 raise ValueError("Invalid otype specification") 

2317 self.otypes = otypes 

2318 

2319 # Excluded variable support 

2320 if excluded is None: 

2321 excluded = set() 

2322 self.excluded = set(excluded) 

2323 

2324 if signature is not None: 

2325 self._in_and_out_core_dims = _parse_gufunc_signature(signature) 

2326 else: 

2327 self._in_and_out_core_dims = None 

2328 

2329 def _init_stage_2(self, pyfunc, *args, **kwargs): 

2330 self.__name__ = pyfunc.__name__ 

2331 self.pyfunc = pyfunc 

2332 if self._doc is None: 

2333 self.__doc__ = pyfunc.__doc__ 

2334 else: 

2335 self.__doc__ = self._doc 

2336 

2337 def _call_as_normal(self, *args, **kwargs): 

2338 """ 

2339 Return arrays with the results of `pyfunc` broadcast (vectorized) over 

2340 `args` and `kwargs` not in `excluded`. 

2341 """ 

2342 excluded = self.excluded 

2343 if not kwargs and not excluded: 

2344 func = self.pyfunc 

2345 vargs = args 

2346 else: 

2347 # The wrapper accepts only positional arguments: we use `names` and 

2348 # `inds` to mutate `the_args` and `kwargs` to pass to the original 

2349 # function. 

2350 nargs = len(args) 

2351 

2352 names = [_n for _n in kwargs if _n not in excluded] 

2353 inds = [_i for _i in range(nargs) if _i not in excluded] 

2354 the_args = list(args) 

2355 

2356 def func(*vargs): 

2357 for _n, _i in enumerate(inds): 

2358 the_args[_i] = vargs[_n] 

2359 kwargs.update(zip(names, vargs[len(inds):])) 

2360 return self.pyfunc(*the_args, **kwargs) 

2361 

2362 vargs = [args[_i] for _i in inds] 

2363 vargs.extend([kwargs[_n] for _n in names]) 

2364 

2365 return self._vectorize_call(func=func, args=vargs) 

2366 

2367 def __call__(self, *args, **kwargs): 

2368 if self.pyfunc is np._NoValue: 

2369 self._init_stage_2(*args, **kwargs) 

2370 return self 

2371 

2372 return self._call_as_normal(*args, **kwargs) 

2373 

2374 def _get_ufunc_and_otypes(self, func, args): 

2375 """Return (ufunc, otypes).""" 

2376 # frompyfunc will fail if args is empty 

2377 if not args: 

2378 raise ValueError('args can not be empty') 

2379 

2380 if self.otypes is not None: 

2381 otypes = self.otypes 

2382 

2383 # self._ufunc is a dictionary whose keys are the number of 

2384 # arguments (i.e. len(args)) and whose values are ufuncs created 

2385 # by frompyfunc. len(args) can be different for different calls if 

2386 # self.pyfunc has parameters with default values. We only use the 

2387 # cache when func is self.pyfunc, which occurs when the call uses 

2388 # only positional arguments and no arguments are excluded. 

2389 

2390 nin = len(args) 

2391 nout = len(self.otypes) 

2392 if func is not self.pyfunc or nin not in self._ufunc: 

2393 ufunc = frompyfunc(func, nin, nout) 

2394 else: 

2395 ufunc = None # We'll get it from self._ufunc 

2396 if func is self.pyfunc: 

2397 ufunc = self._ufunc.setdefault(nin, ufunc) 

2398 else: 

2399 # Get number of outputs and output types by calling the function on 

2400 # the first entries of args. We also cache the result to prevent 

2401 # the subsequent call when the ufunc is evaluated. 

2402 # Assumes that ufunc first evaluates the 0th elements in the input 

2403 # arrays (the input values are not checked to ensure this) 

2404 args = [asarray(arg) for arg in args] 

2405 if builtins.any(arg.size == 0 for arg in args): 

2406 raise ValueError('cannot call `vectorize` on size 0 inputs ' 

2407 'unless `otypes` is set') 

2408 

2409 inputs = [arg.flat[0] for arg in args] 

2410 outputs = func(*inputs) 

2411 

2412 # Performance note: profiling indicates that -- for simple 

2413 # functions at least -- this wrapping can almost double the 

2414 # execution time. 

2415 # Hence we make it optional. 

2416 if self.cache: 

2417 _cache = [outputs] 

2418 

2419 def _func(*vargs): 

2420 if _cache: 

2421 return _cache.pop() 

2422 else: 

2423 return func(*vargs) 

2424 else: 

2425 _func = func 

2426 

2427 if isinstance(outputs, tuple): 

2428 nout = len(outputs) 

2429 else: 

2430 nout = 1 

2431 outputs = (outputs,) 

2432 

2433 otypes = ''.join([asarray(outputs[_k]).dtype.char 

2434 for _k in range(nout)]) 

2435 

2436 # Performance note: profiling indicates that creating the ufunc is 

2437 # not a significant cost compared with wrapping so it seems not 

2438 # worth trying to cache this. 

2439 ufunc = frompyfunc(_func, len(args), nout) 

2440 

2441 return ufunc, otypes 

2442 

2443 def _vectorize_call(self, func, args): 

2444 """Vectorized call to `func` over positional `args`.""" 

2445 if self.signature is not None: 

2446 res = self._vectorize_call_with_signature(func, args) 

2447 elif not args: 

2448 res = func() 

2449 else: 

2450 ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args) 

2451 

2452 # Convert args to object arrays first 

2453 inputs = [asanyarray(a, dtype=object) for a in args] 

2454 

2455 outputs = ufunc(*inputs) 

2456 

2457 if ufunc.nout == 1: 

2458 res = asanyarray(outputs, dtype=otypes[0]) 

2459 else: 

2460 res = tuple([asanyarray(x, dtype=t) 

2461 for x, t in zip(outputs, otypes)]) 

2462 return res 

2463 

2464 def _vectorize_call_with_signature(self, func, args): 

2465 """Vectorized call over positional arguments with a signature.""" 

2466 input_core_dims, output_core_dims = self._in_and_out_core_dims 

2467 

2468 if len(args) != len(input_core_dims): 

2469 raise TypeError('wrong number of positional arguments: ' 

2470 'expected %r, got %r' 

2471 % (len(input_core_dims), len(args))) 

2472 args = tuple(asanyarray(arg) for arg in args) 

2473 

2474 broadcast_shape, dim_sizes = _parse_input_dimensions( 

2475 args, input_core_dims) 

2476 input_shapes = _calculate_shapes(broadcast_shape, dim_sizes, 

2477 input_core_dims) 

2478 args = [np.broadcast_to(arg, shape, subok=True) 

2479 for arg, shape in zip(args, input_shapes)] 

2480 

2481 outputs = None 

2482 otypes = self.otypes 

2483 nout = len(output_core_dims) 

2484 

2485 for index in np.ndindex(*broadcast_shape): 

2486 results = func(*(arg[index] for arg in args)) 

2487 

2488 n_results = len(results) if isinstance(results, tuple) else 1 

2489 

2490 if nout != n_results: 

2491 raise ValueError( 

2492 'wrong number of outputs from pyfunc: expected %r, got %r' 

2493 % (nout, n_results)) 

2494 

2495 if nout == 1: 

2496 results = (results,) 

2497 

2498 if outputs is None: 

2499 for result, core_dims in zip(results, output_core_dims): 

2500 _update_dim_sizes(dim_sizes, result, core_dims) 

2501 

2502 outputs = _create_arrays(broadcast_shape, dim_sizes, 

2503 output_core_dims, otypes, results) 

2504 

2505 for output, result in zip(outputs, results): 

2506 output[index] = result 

2507 

2508 if outputs is None: 

2509 # did not call the function even once 

2510 if otypes is None: 

2511 raise ValueError('cannot call `vectorize` on size 0 inputs ' 

2512 'unless `otypes` is set') 

2513 if builtins.any(dim not in dim_sizes 

2514 for dims in output_core_dims 

2515 for dim in dims): 

2516 raise ValueError('cannot call `vectorize` with a signature ' 

2517 'including new output dimensions on size 0 ' 

2518 'inputs') 

2519 outputs = _create_arrays(broadcast_shape, dim_sizes, 

2520 output_core_dims, otypes) 

2521 

2522 return outputs[0] if nout == 1 else outputs 

2523 

2524 

2525def _cov_dispatcher(m, y=None, rowvar=None, bias=None, ddof=None, 

2526 fweights=None, aweights=None, *, dtype=None): 

2527 return (m, y, fweights, aweights) 

2528 

2529 

2530@array_function_dispatch(_cov_dispatcher) 

2531def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None, 

2532 aweights=None, *, dtype=None): 

2533 """ 

2534 Estimate a covariance matrix, given data and weights. 

2535 

2536 Covariance indicates the level to which two variables vary together. 

2537 If we examine N-dimensional samples, :math:`X = [x_1, x_2, ... x_N]^T`, 

2538 then the covariance matrix element :math:`C_{ij}` is the covariance of 

2539 :math:`x_i` and :math:`x_j`. The element :math:`C_{ii}` is the variance 

2540 of :math:`x_i`. 

2541 

2542 See the notes for an outline of the algorithm. 

2543 

2544 Parameters 

2545 ---------- 

2546 m : array_like 

2547 A 1-D or 2-D array containing multiple variables and observations. 

2548 Each row of `m` represents a variable, and each column a single 

2549 observation of all those variables. Also see `rowvar` below. 

2550 y : array_like, optional 

2551 An additional set of variables and observations. `y` has the same form 

2552 as that of `m`. 

2553 rowvar : bool, optional 

2554 If `rowvar` is True (default), then each row represents a 

2555 variable, with observations in the columns. Otherwise, the relationship 

2556 is transposed: each column represents a variable, while the rows 

2557 contain observations. 

2558 bias : bool, optional 

2559 Default normalization (False) is by ``(N - 1)``, where ``N`` is the 

2560 number of observations given (unbiased estimate). If `bias` is True, 

2561 then normalization is by ``N``. These values can be overridden by using 

2562 the keyword ``ddof`` in numpy versions >= 1.5. 

2563 ddof : int, optional 

2564 If not ``None`` the default value implied by `bias` is overridden. 

2565 Note that ``ddof=1`` will return the unbiased estimate, even if both 

2566 `fweights` and `aweights` are specified, and ``ddof=0`` will return 

2567 the simple average. See the notes for the details. The default value 

2568 is ``None``. 

2569 

2570 .. versionadded:: 1.5 

2571 fweights : array_like, int, optional 

2572 1-D array of integer frequency weights; the number of times each 

2573 observation vector should be repeated. 

2574 

2575 .. versionadded:: 1.10 

2576 aweights : array_like, optional 

2577 1-D array of observation vector weights. These relative weights are 

2578 typically large for observations considered "important" and smaller for 

2579 observations considered less "important". If ``ddof=0`` the array of 

2580 weights can be used to assign probabilities to observation vectors. 

2581 

2582 .. versionadded:: 1.10 

2583 dtype : data-type, optional 

2584 Data-type of the result. By default, the return data-type will have 

2585 at least `numpy.float64` precision. 

2586 

2587 .. versionadded:: 1.20 

2588 

2589 Returns 

2590 ------- 

2591 out : ndarray 

2592 The covariance matrix of the variables. 

2593 

2594 See Also 

2595 -------- 

2596 corrcoef : Normalized covariance matrix 

2597 

2598 Notes 

2599 ----- 

2600 Assume that the observations are in the columns of the observation 

2601 array `m` and let ``f = fweights`` and ``a = aweights`` for brevity. The 

2602 steps to compute the weighted covariance are as follows:: 

2603 

2604 >>> m = np.arange(10, dtype=np.float64) 

2605 >>> f = np.arange(10) * 2 

2606 >>> a = np.arange(10) ** 2. 

2607 >>> ddof = 1 

2608 >>> w = f * a 

2609 >>> v1 = np.sum(w) 

2610 >>> v2 = np.sum(w * a) 

2611 >>> m -= np.sum(m * w, axis=None, keepdims=True) / v1 

2612 >>> cov = np.dot(m * w, m.T) * v1 / (v1**2 - ddof * v2) 

2613 

2614 Note that when ``a == 1``, the normalization factor 

2615 ``v1 / (v1**2 - ddof * v2)`` goes over to ``1 / (np.sum(f) - ddof)`` 

2616 as it should. 

2617 

2618 Examples 

2619 -------- 

2620 Consider two variables, :math:`x_0` and :math:`x_1`, which 

2621 correlate perfectly, but in opposite directions: 

2622 

2623 >>> x = np.array([[0, 2], [1, 1], [2, 0]]).T 

2624 >>> x 

2625 array([[0, 1, 2], 

2626 [2, 1, 0]]) 

2627 

2628 Note how :math:`x_0` increases while :math:`x_1` decreases. The covariance 

2629 matrix shows this clearly: 

2630 

2631 >>> np.cov(x) 

2632 array([[ 1., -1.], 

2633 [-1., 1.]]) 

2634 

2635 Note that element :math:`C_{0,1}`, which shows the correlation between 

2636 :math:`x_0` and :math:`x_1`, is negative. 

2637 

2638 Further, note how `x` and `y` are combined: 

2639 

2640 >>> x = [-2.1, -1, 4.3] 

2641 >>> y = [3, 1.1, 0.12] 

2642 >>> X = np.stack((x, y), axis=0) 

2643 >>> np.cov(X) 

2644 array([[11.71 , -4.286 ], # may vary 

2645 [-4.286 , 2.144133]]) 

2646 >>> np.cov(x, y) 

2647 array([[11.71 , -4.286 ], # may vary 

2648 [-4.286 , 2.144133]]) 

2649 >>> np.cov(x) 

2650 array(11.71) 

2651 

2652 """ 

2653 # Check inputs 

2654 if ddof is not None and ddof != int(ddof): 

2655 raise ValueError( 

2656 "ddof must be integer") 

2657 

2658 # Handles complex arrays too 

2659 m = np.asarray(m) 

2660 if m.ndim > 2: 

2661 raise ValueError("m has more than 2 dimensions") 

2662 

2663 if y is not None: 

2664 y = np.asarray(y) 

2665 if y.ndim > 2: 

2666 raise ValueError("y has more than 2 dimensions") 

2667 

2668 if dtype is None: 

2669 if y is None: 

2670 dtype = np.result_type(m, np.float64) 

2671 else: 

2672 dtype = np.result_type(m, y, np.float64) 

2673 

2674 X = array(m, ndmin=2, dtype=dtype) 

2675 if not rowvar and X.shape[0] != 1: 

2676 X = X.T 

2677 if X.shape[0] == 0: 

2678 return np.array([]).reshape(0, 0) 

2679 if y is not None: 

2680 y = array(y, copy=False, ndmin=2, dtype=dtype) 

2681 if not rowvar and y.shape[0] != 1: 

2682 y = y.T 

2683 X = np.concatenate((X, y), axis=0) 

2684 

2685 if ddof is None: 

2686 if bias == 0: 

2687 ddof = 1 

2688 else: 

2689 ddof = 0 

2690 

2691 # Get the product of frequencies and weights 

2692 w = None 

2693 if fweights is not None: 

2694 fweights = np.asarray(fweights, dtype=float) 

2695 if not np.all(fweights == np.around(fweights)): 

2696 raise TypeError( 

2697 "fweights must be integer") 

2698 if fweights.ndim > 1: 

2699 raise RuntimeError( 

2700 "cannot handle multidimensional fweights") 

2701 if fweights.shape[0] != X.shape[1]: 

2702 raise RuntimeError( 

2703 "incompatible numbers of samples and fweights") 

2704 if any(fweights < 0): 

2705 raise ValueError( 

2706 "fweights cannot be negative") 

2707 w = fweights 

2708 if aweights is not None: 

2709 aweights = np.asarray(aweights, dtype=float) 

2710 if aweights.ndim > 1: 

2711 raise RuntimeError( 

2712 "cannot handle multidimensional aweights") 

2713 if aweights.shape[0] != X.shape[1]: 

2714 raise RuntimeError( 

2715 "incompatible numbers of samples and aweights") 

2716 if any(aweights < 0): 

2717 raise ValueError( 

2718 "aweights cannot be negative") 

2719 if w is None: 

2720 w = aweights 

2721 else: 

2722 w *= aweights 

2723 

2724 avg, w_sum = average(X, axis=1, weights=w, returned=True) 

2725 w_sum = w_sum[0] 

2726 

2727 # Determine the normalization 

2728 if w is None: 

2729 fact = X.shape[1] - ddof 

2730 elif ddof == 0: 

2731 fact = w_sum 

2732 elif aweights is None: 

2733 fact = w_sum - ddof 

2734 else: 

2735 fact = w_sum - ddof*sum(w*aweights)/w_sum 

2736 

2737 if fact <= 0: 

2738 warnings.warn("Degrees of freedom <= 0 for slice", 

2739 RuntimeWarning, stacklevel=2) 

2740 fact = 0.0 

2741 

2742 X -= avg[:, None] 

2743 if w is None: 

2744 X_T = X.T 

2745 else: 

2746 X_T = (X*w).T 

2747 c = dot(X, X_T.conj()) 

2748 c *= np.true_divide(1, fact) 

2749 return c.squeeze() 

2750 

2751 

2752def _corrcoef_dispatcher(x, y=None, rowvar=None, bias=None, ddof=None, *, 

2753 dtype=None): 

2754 return (x, y) 

2755 

2756 

2757@array_function_dispatch(_corrcoef_dispatcher) 

2758def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, ddof=np._NoValue, *, 

2759 dtype=None): 

2760 """ 

2761 Return Pearson product-moment correlation coefficients. 

2762 

2763 Please refer to the documentation for `cov` for more detail. The 

2764 relationship between the correlation coefficient matrix, `R`, and the 

2765 covariance matrix, `C`, is 

2766 

2767 .. math:: R_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} C_{jj} } } 

2768 

2769 The values of `R` are between -1 and 1, inclusive. 

2770 

2771 Parameters 

2772 ---------- 

2773 x : array_like 

2774 A 1-D or 2-D array containing multiple variables and observations. 

2775 Each row of `x` represents a variable, and each column a single 

2776 observation of all those variables. Also see `rowvar` below. 

2777 y : array_like, optional 

2778 An additional set of variables and observations. `y` has the same 

2779 shape as `x`. 

2780 rowvar : bool, optional 

2781 If `rowvar` is True (default), then each row represents a 

2782 variable, with observations in the columns. Otherwise, the relationship 

2783 is transposed: each column represents a variable, while the rows 

2784 contain observations. 

2785 bias : _NoValue, optional 

2786 Has no effect, do not use. 

2787 

2788 .. deprecated:: 1.10.0 

2789 ddof : _NoValue, optional 

2790 Has no effect, do not use. 

2791 

2792 .. deprecated:: 1.10.0 

2793 dtype : data-type, optional 

2794 Data-type of the result. By default, the return data-type will have 

2795 at least `numpy.float64` precision. 

2796 

2797 .. versionadded:: 1.20 

2798 

2799 Returns 

2800 ------- 

2801 R : ndarray 

2802 The correlation coefficient matrix of the variables. 

2803 

2804 See Also 

2805 -------- 

2806 cov : Covariance matrix 

2807 

2808 Notes 

2809 ----- 

2810 Due to floating point rounding the resulting array may not be Hermitian, 

2811 the diagonal elements may not be 1, and the elements may not satisfy the 

2812 inequality abs(a) <= 1. The real and imaginary parts are clipped to the 

2813 interval [-1, 1] in an attempt to improve on that situation but is not 

2814 much help in the complex case. 

2815 

2816 This function accepts but discards arguments `bias` and `ddof`. This is 

2817 for backwards compatibility with previous versions of this function. These 

2818 arguments had no effect on the return values of the function and can be 

2819 safely ignored in this and previous versions of numpy. 

2820 

2821 Examples 

2822 -------- 

2823 In this example we generate two random arrays, ``xarr`` and ``yarr``, and 

2824 compute the row-wise and column-wise Pearson correlation coefficients, 

2825 ``R``. Since ``rowvar`` is true by default, we first find the row-wise 

2826 Pearson correlation coefficients between the variables of ``xarr``. 

2827 

2828 >>> import numpy as np 

2829 >>> rng = np.random.default_rng(seed=42) 

2830 >>> xarr = rng.random((3, 3)) 

2831 >>> xarr 

2832 array([[0.77395605, 0.43887844, 0.85859792], 

2833 [0.69736803, 0.09417735, 0.97562235], 

2834 [0.7611397 , 0.78606431, 0.12811363]]) 

2835 >>> R1 = np.corrcoef(xarr) 

2836 >>> R1 

2837 array([[ 1. , 0.99256089, -0.68080986], 

2838 [ 0.99256089, 1. , -0.76492172], 

2839 [-0.68080986, -0.76492172, 1. ]]) 

2840 

2841 If we add another set of variables and observations ``yarr``, we can 

2842 compute the row-wise Pearson correlation coefficients between the 

2843 variables in ``xarr`` and ``yarr``. 

2844 

2845 >>> yarr = rng.random((3, 3)) 

2846 >>> yarr 

2847 array([[0.45038594, 0.37079802, 0.92676499], 

2848 [0.64386512, 0.82276161, 0.4434142 ], 

2849 [0.22723872, 0.55458479, 0.06381726]]) 

2850 >>> R2 = np.corrcoef(xarr, yarr) 

2851 >>> R2 

2852 array([[ 1. , 0.99256089, -0.68080986, 0.75008178, -0.934284 , 

2853 -0.99004057], 

2854 [ 0.99256089, 1. , -0.76492172, 0.82502011, -0.97074098, 

2855 -0.99981569], 

2856 [-0.68080986, -0.76492172, 1. , -0.99507202, 0.89721355, 

2857 0.77714685], 

2858 [ 0.75008178, 0.82502011, -0.99507202, 1. , -0.93657855, 

2859 -0.83571711], 

2860 [-0.934284 , -0.97074098, 0.89721355, -0.93657855, 1. , 

2861 0.97517215], 

2862 [-0.99004057, -0.99981569, 0.77714685, -0.83571711, 0.97517215, 

2863 1. ]]) 

2864 

2865 Finally if we use the option ``rowvar=False``, the columns are now 

2866 being treated as the variables and we will find the column-wise Pearson 

2867 correlation coefficients between variables in ``xarr`` and ``yarr``. 

2868 

2869 >>> R3 = np.corrcoef(xarr, yarr, rowvar=False) 

2870 >>> R3 

2871 array([[ 1. , 0.77598074, -0.47458546, -0.75078643, -0.9665554 , 

2872 0.22423734], 

2873 [ 0.77598074, 1. , -0.92346708, -0.99923895, -0.58826587, 

2874 -0.44069024], 

2875 [-0.47458546, -0.92346708, 1. , 0.93773029, 0.23297648, 

2876 0.75137473], 

2877 [-0.75078643, -0.99923895, 0.93773029, 1. , 0.55627469, 

2878 0.47536961], 

2879 [-0.9665554 , -0.58826587, 0.23297648, 0.55627469, 1. , 

2880 -0.46666491], 

2881 [ 0.22423734, -0.44069024, 0.75137473, 0.47536961, -0.46666491, 

2882 1. ]]) 

2883 

2884 """ 

2885 if bias is not np._NoValue or ddof is not np._NoValue: 

2886 # 2015-03-15, 1.10 

2887 warnings.warn('bias and ddof have no effect and are deprecated', 

2888 DeprecationWarning, stacklevel=2) 

2889 c = cov(x, y, rowvar, dtype=dtype) 

2890 try: 

2891 d = diag(c) 

2892 except ValueError: 

2893 # scalar covariance 

2894 # nan if incorrect value (nan, inf, 0), 1 otherwise 

2895 return c / c 

2896 stddev = sqrt(d.real) 

2897 c /= stddev[:, None] 

2898 c /= stddev[None, :] 

2899 

2900 # Clip real and imaginary parts to [-1, 1]. This does not guarantee 

2901 # abs(a[i,j]) <= 1 for complex arrays, but is the best we can do without 

2902 # excessive work. 

2903 np.clip(c.real, -1, 1, out=c.real) 

2904 if np.iscomplexobj(c): 

2905 np.clip(c.imag, -1, 1, out=c.imag) 

2906 

2907 return c 

2908 

2909 

2910@set_module('numpy') 

2911def blackman(M): 

2912 """ 

2913 Return the Blackman window. 

2914 

2915 The Blackman window is a taper formed by using the first three 

2916 terms of a summation of cosines. It was designed to have close to the 

2917 minimal leakage possible. It is close to optimal, only slightly worse 

2918 than a Kaiser window. 

2919 

2920 Parameters 

2921 ---------- 

2922 M : int 

2923 Number of points in the output window. If zero or less, an empty 

2924 array is returned. 

2925 

2926 Returns 

2927 ------- 

2928 out : ndarray 

2929 The window, with the maximum value normalized to one (the value one 

2930 appears only if the number of samples is odd). 

2931 

2932 See Also 

2933 -------- 

2934 bartlett, hamming, hanning, kaiser 

2935 

2936 Notes 

2937 ----- 

2938 The Blackman window is defined as 

2939 

2940 .. math:: w(n) = 0.42 - 0.5 \\cos(2\\pi n/M) + 0.08 \\cos(4\\pi n/M) 

2941 

2942 Most references to the Blackman window come from the signal processing 

2943 literature, where it is used as one of many windowing functions for 

2944 smoothing values. It is also known as an apodization (which means 

2945 "removing the foot", i.e. smoothing discontinuities at the beginning 

2946 and end of the sampled signal) or tapering function. It is known as a 

2947 "near optimal" tapering function, almost as good (by some measures) 

2948 as the kaiser window. 

2949 

2950 References 

2951 ---------- 

2952 Blackman, R.B. and Tukey, J.W., (1958) The measurement of power spectra, 

2953 Dover Publications, New York. 

2954 

2955 Oppenheim, A.V., and R.W. Schafer. Discrete-Time Signal Processing. 

2956 Upper Saddle River, NJ: Prentice-Hall, 1999, pp. 468-471. 

2957 

2958 Examples 

2959 -------- 

2960 >>> import matplotlib.pyplot as plt 

2961 >>> np.blackman(12) 

2962 array([-1.38777878e-17, 3.26064346e-02, 1.59903635e-01, # may vary 

2963 4.14397981e-01, 7.36045180e-01, 9.67046769e-01, 

2964 9.67046769e-01, 7.36045180e-01, 4.14397981e-01, 

2965 1.59903635e-01, 3.26064346e-02, -1.38777878e-17]) 

2966 

2967 Plot the window and the frequency response: 

2968 

2969 >>> from numpy.fft import fft, fftshift 

2970 >>> window = np.blackman(51) 

2971 >>> plt.plot(window) 

2972 [<matplotlib.lines.Line2D object at 0x...>] 

2973 >>> plt.title("Blackman window") 

2974 Text(0.5, 1.0, 'Blackman window') 

2975 >>> plt.ylabel("Amplitude") 

2976 Text(0, 0.5, 'Amplitude') 

2977 >>> plt.xlabel("Sample") 

2978 Text(0.5, 0, 'Sample') 

2979 >>> plt.show() 

2980 

2981 >>> plt.figure() 

2982 <Figure size 640x480 with 0 Axes> 

2983 >>> A = fft(window, 2048) / 25.5 

2984 >>> mag = np.abs(fftshift(A)) 

2985 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

2986 >>> with np.errstate(divide='ignore', invalid='ignore'): 

2987 ... response = 20 * np.log10(mag) 

2988 ... 

2989 >>> response = np.clip(response, -100, 100) 

2990 >>> plt.plot(freq, response) 

2991 [<matplotlib.lines.Line2D object at 0x...>] 

2992 >>> plt.title("Frequency response of Blackman window") 

2993 Text(0.5, 1.0, 'Frequency response of Blackman window') 

2994 >>> plt.ylabel("Magnitude [dB]") 

2995 Text(0, 0.5, 'Magnitude [dB]') 

2996 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

2997 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

2998 >>> _ = plt.axis('tight') 

2999 >>> plt.show() 

3000 

3001 """ 

3002 # Ensures at least float64 via 0.0. M should be an integer, but conversion 

3003 # to double is safe for a range. 

3004 values = np.array([0.0, M]) 

3005 M = values[1] 

3006 

3007 if M < 1: 

3008 return array([], dtype=values.dtype) 

3009 if M == 1: 

3010 return ones(1, dtype=values.dtype) 

3011 n = arange(1-M, M, 2) 

3012 return 0.42 + 0.5*cos(pi*n/(M-1)) + 0.08*cos(2.0*pi*n/(M-1)) 

3013 

3014 

3015@set_module('numpy') 

3016def bartlett(M): 

3017 """ 

3018 Return the Bartlett window. 

3019 

3020 The Bartlett window is very similar to a triangular window, except 

3021 that the end points are at zero. It is often used in signal 

3022 processing for tapering a signal, without generating too much 

3023 ripple in the frequency domain. 

3024 

3025 Parameters 

3026 ---------- 

3027 M : int 

3028 Number of points in the output window. If zero or less, an 

3029 empty array is returned. 

3030 

3031 Returns 

3032 ------- 

3033 out : array 

3034 The triangular window, with the maximum value normalized to one 

3035 (the value one appears only if the number of samples is odd), with 

3036 the first and last samples equal to zero. 

3037 

3038 See Also 

3039 -------- 

3040 blackman, hamming, hanning, kaiser 

3041 

3042 Notes 

3043 ----- 

3044 The Bartlett window is defined as 

3045 

3046 .. math:: w(n) = \\frac{2}{M-1} \\left( 

3047 \\frac{M-1}{2} - \\left|n - \\frac{M-1}{2}\\right| 

3048 \\right) 

3049 

3050 Most references to the Bartlett window come from the signal processing 

3051 literature, where it is used as one of many windowing functions for 

3052 smoothing values. Note that convolution with this window produces linear 

3053 interpolation. It is also known as an apodization (which means "removing 

3054 the foot", i.e. smoothing discontinuities at the beginning and end of the 

3055 sampled signal) or tapering function. The Fourier transform of the 

3056 Bartlett window is the product of two sinc functions. Note the excellent 

3057 discussion in Kanasewich [2]_. 

3058 

3059 References 

3060 ---------- 

3061 .. [1] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra", 

3062 Biometrika 37, 1-16, 1950. 

3063 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", 

3064 The University of Alberta Press, 1975, pp. 109-110. 

3065 .. [3] A.V. Oppenheim and R.W. Schafer, "Discrete-Time Signal 

3066 Processing", Prentice-Hall, 1999, pp. 468-471. 

3067 .. [4] Wikipedia, "Window function", 

3068 https://en.wikipedia.org/wiki/Window_function 

3069 .. [5] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, 

3070 "Numerical Recipes", Cambridge University Press, 1986, page 429. 

3071 

3072 Examples 

3073 -------- 

3074 >>> import matplotlib.pyplot as plt 

3075 >>> np.bartlett(12) 

3076 array([ 0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273, # may vary 

3077 0.90909091, 0.90909091, 0.72727273, 0.54545455, 0.36363636, 

3078 0.18181818, 0. ]) 

3079 

3080 Plot the window and its frequency response (requires SciPy and matplotlib): 

3081 

3082 >>> from numpy.fft import fft, fftshift 

3083 >>> window = np.bartlett(51) 

3084 >>> plt.plot(window) 

3085 [<matplotlib.lines.Line2D object at 0x...>] 

3086 >>> plt.title("Bartlett window") 

3087 Text(0.5, 1.0, 'Bartlett window') 

3088 >>> plt.ylabel("Amplitude") 

3089 Text(0, 0.5, 'Amplitude') 

3090 >>> plt.xlabel("Sample") 

3091 Text(0.5, 0, 'Sample') 

3092 >>> plt.show() 

3093 

3094 >>> plt.figure() 

3095 <Figure size 640x480 with 0 Axes> 

3096 >>> A = fft(window, 2048) / 25.5 

3097 >>> mag = np.abs(fftshift(A)) 

3098 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3099 >>> with np.errstate(divide='ignore', invalid='ignore'): 

3100 ... response = 20 * np.log10(mag) 

3101 ... 

3102 >>> response = np.clip(response, -100, 100) 

3103 >>> plt.plot(freq, response) 

3104 [<matplotlib.lines.Line2D object at 0x...>] 

3105 >>> plt.title("Frequency response of Bartlett window") 

3106 Text(0.5, 1.0, 'Frequency response of Bartlett window') 

3107 >>> plt.ylabel("Magnitude [dB]") 

3108 Text(0, 0.5, 'Magnitude [dB]') 

3109 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3110 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3111 >>> _ = plt.axis('tight') 

3112 >>> plt.show() 

3113 

3114 """ 

3115 # Ensures at least float64 via 0.0. M should be an integer, but conversion 

3116 # to double is safe for a range. 

3117 values = np.array([0.0, M]) 

3118 M = values[1] 

3119 

3120 if M < 1: 

3121 return array([], dtype=values.dtype) 

3122 if M == 1: 

3123 return ones(1, dtype=values.dtype) 

3124 n = arange(1-M, M, 2) 

3125 return where(less_equal(n, 0), 1 + n/(M-1), 1 - n/(M-1)) 

3126 

3127 

3128@set_module('numpy') 

3129def hanning(M): 

3130 """ 

3131 Return the Hanning window. 

3132 

3133 The Hanning window is a taper formed by using a weighted cosine. 

3134 

3135 Parameters 

3136 ---------- 

3137 M : int 

3138 Number of points in the output window. If zero or less, an 

3139 empty array is returned. 

3140 

3141 Returns 

3142 ------- 

3143 out : ndarray, shape(M,) 

3144 The window, with the maximum value normalized to one (the value 

3145 one appears only if `M` is odd). 

3146 

3147 See Also 

3148 -------- 

3149 bartlett, blackman, hamming, kaiser 

3150 

3151 Notes 

3152 ----- 

3153 The Hanning window is defined as 

3154 

3155 .. math:: w(n) = 0.5 - 0.5\\cos\\left(\\frac{2\\pi{n}}{M-1}\\right) 

3156 \\qquad 0 \\leq n \\leq M-1 

3157 

3158 The Hanning was named for Julius von Hann, an Austrian meteorologist. 

3159 It is also known as the Cosine Bell. Some authors prefer that it be 

3160 called a Hann window, to help avoid confusion with the very similar 

3161 Hamming window. 

3162 

3163 Most references to the Hanning window come from the signal processing 

3164 literature, where it is used as one of many windowing functions for 

3165 smoothing values. It is also known as an apodization (which means 

3166 "removing the foot", i.e. smoothing discontinuities at the beginning 

3167 and end of the sampled signal) or tapering function. 

3168 

3169 References 

3170 ---------- 

3171 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power 

3172 spectra, Dover Publications, New York. 

3173 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", 

3174 The University of Alberta Press, 1975, pp. 106-108. 

3175 .. [3] Wikipedia, "Window function", 

3176 https://en.wikipedia.org/wiki/Window_function 

3177 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, 

3178 "Numerical Recipes", Cambridge University Press, 1986, page 425. 

3179 

3180 Examples 

3181 -------- 

3182 >>> np.hanning(12) 

3183 array([0. , 0.07937323, 0.29229249, 0.57115742, 0.82743037, 

3184 0.97974649, 0.97974649, 0.82743037, 0.57115742, 0.29229249, 

3185 0.07937323, 0. ]) 

3186 

3187 Plot the window and its frequency response: 

3188 

3189 >>> import matplotlib.pyplot as plt 

3190 >>> from numpy.fft import fft, fftshift 

3191 >>> window = np.hanning(51) 

3192 >>> plt.plot(window) 

3193 [<matplotlib.lines.Line2D object at 0x...>] 

3194 >>> plt.title("Hann window") 

3195 Text(0.5, 1.0, 'Hann window') 

3196 >>> plt.ylabel("Amplitude") 

3197 Text(0, 0.5, 'Amplitude') 

3198 >>> plt.xlabel("Sample") 

3199 Text(0.5, 0, 'Sample') 

3200 >>> plt.show() 

3201 

3202 >>> plt.figure() 

3203 <Figure size 640x480 with 0 Axes> 

3204 >>> A = fft(window, 2048) / 25.5 

3205 >>> mag = np.abs(fftshift(A)) 

3206 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3207 >>> with np.errstate(divide='ignore', invalid='ignore'): 

3208 ... response = 20 * np.log10(mag) 

3209 ... 

3210 >>> response = np.clip(response, -100, 100) 

3211 >>> plt.plot(freq, response) 

3212 [<matplotlib.lines.Line2D object at 0x...>] 

3213 >>> plt.title("Frequency response of the Hann window") 

3214 Text(0.5, 1.0, 'Frequency response of the Hann window') 

3215 >>> plt.ylabel("Magnitude [dB]") 

3216 Text(0, 0.5, 'Magnitude [dB]') 

3217 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3218 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3219 >>> plt.axis('tight') 

3220 ... 

3221 >>> plt.show() 

3222 

3223 """ 

3224 # Ensures at least float64 via 0.0. M should be an integer, but conversion 

3225 # to double is safe for a range. 

3226 values = np.array([0.0, M]) 

3227 M = values[1] 

3228 

3229 if M < 1: 

3230 return array([], dtype=values.dtype) 

3231 if M == 1: 

3232 return ones(1, dtype=values.dtype) 

3233 n = arange(1-M, M, 2) 

3234 return 0.5 + 0.5*cos(pi*n/(M-1)) 

3235 

3236 

3237@set_module('numpy') 

3238def hamming(M): 

3239 """ 

3240 Return the Hamming window. 

3241 

3242 The Hamming window is a taper formed by using a weighted cosine. 

3243 

3244 Parameters 

3245 ---------- 

3246 M : int 

3247 Number of points in the output window. If zero or less, an 

3248 empty array is returned. 

3249 

3250 Returns 

3251 ------- 

3252 out : ndarray 

3253 The window, with the maximum value normalized to one (the value 

3254 one appears only if the number of samples is odd). 

3255 

3256 See Also 

3257 -------- 

3258 bartlett, blackman, hanning, kaiser 

3259 

3260 Notes 

3261 ----- 

3262 The Hamming window is defined as 

3263 

3264 .. math:: w(n) = 0.54 - 0.46\\cos\\left(\\frac{2\\pi{n}}{M-1}\\right) 

3265 \\qquad 0 \\leq n \\leq M-1 

3266 

3267 The Hamming was named for R. W. Hamming, an associate of J. W. Tukey 

3268 and is described in Blackman and Tukey. It was recommended for 

3269 smoothing the truncated autocovariance function in the time domain. 

3270 Most references to the Hamming window come from the signal processing 

3271 literature, where it is used as one of many windowing functions for 

3272 smoothing values. It is also known as an apodization (which means 

3273 "removing the foot", i.e. smoothing discontinuities at the beginning 

3274 and end of the sampled signal) or tapering function. 

3275 

3276 References 

3277 ---------- 

3278 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power 

3279 spectra, Dover Publications, New York. 

3280 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The 

3281 University of Alberta Press, 1975, pp. 109-110. 

3282 .. [3] Wikipedia, "Window function", 

3283 https://en.wikipedia.org/wiki/Window_function 

3284 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, 

3285 "Numerical Recipes", Cambridge University Press, 1986, page 425. 

3286 

3287 Examples 

3288 -------- 

3289 >>> np.hamming(12) 

3290 array([ 0.08 , 0.15302337, 0.34890909, 0.60546483, 0.84123594, # may vary 

3291 0.98136677, 0.98136677, 0.84123594, 0.60546483, 0.34890909, 

3292 0.15302337, 0.08 ]) 

3293 

3294 Plot the window and the frequency response: 

3295 

3296 >>> import matplotlib.pyplot as plt 

3297 >>> from numpy.fft import fft, fftshift 

3298 >>> window = np.hamming(51) 

3299 >>> plt.plot(window) 

3300 [<matplotlib.lines.Line2D object at 0x...>] 

3301 >>> plt.title("Hamming window") 

3302 Text(0.5, 1.0, 'Hamming window') 

3303 >>> plt.ylabel("Amplitude") 

3304 Text(0, 0.5, 'Amplitude') 

3305 >>> plt.xlabel("Sample") 

3306 Text(0.5, 0, 'Sample') 

3307 >>> plt.show() 

3308 

3309 >>> plt.figure() 

3310 <Figure size 640x480 with 0 Axes> 

3311 >>> A = fft(window, 2048) / 25.5 

3312 >>> mag = np.abs(fftshift(A)) 

3313 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3314 >>> response = 20 * np.log10(mag) 

3315 >>> response = np.clip(response, -100, 100) 

3316 >>> plt.plot(freq, response) 

3317 [<matplotlib.lines.Line2D object at 0x...>] 

3318 >>> plt.title("Frequency response of Hamming window") 

3319 Text(0.5, 1.0, 'Frequency response of Hamming window') 

3320 >>> plt.ylabel("Magnitude [dB]") 

3321 Text(0, 0.5, 'Magnitude [dB]') 

3322 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3323 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3324 >>> plt.axis('tight') 

3325 ... 

3326 >>> plt.show() 

3327 

3328 """ 

3329 # Ensures at least float64 via 0.0. M should be an integer, but conversion 

3330 # to double is safe for a range. 

3331 values = np.array([0.0, M]) 

3332 M = values[1] 

3333 

3334 if M < 1: 

3335 return array([], dtype=values.dtype) 

3336 if M == 1: 

3337 return ones(1, dtype=values.dtype) 

3338 n = arange(1-M, M, 2) 

3339 return 0.54 + 0.46*cos(pi*n/(M-1)) 

3340 

3341 

3342## Code from cephes for i0 

3343 

3344_i0A = [ 

3345 -4.41534164647933937950E-18, 

3346 3.33079451882223809783E-17, 

3347 -2.43127984654795469359E-16, 

3348 1.71539128555513303061E-15, 

3349 -1.16853328779934516808E-14, 

3350 7.67618549860493561688E-14, 

3351 -4.85644678311192946090E-13, 

3352 2.95505266312963983461E-12, 

3353 -1.72682629144155570723E-11, 

3354 9.67580903537323691224E-11, 

3355 -5.18979560163526290666E-10, 

3356 2.65982372468238665035E-9, 

3357 -1.30002500998624804212E-8, 

3358 6.04699502254191894932E-8, 

3359 -2.67079385394061173391E-7, 

3360 1.11738753912010371815E-6, 

3361 -4.41673835845875056359E-6, 

3362 1.64484480707288970893E-5, 

3363 -5.75419501008210370398E-5, 

3364 1.88502885095841655729E-4, 

3365 -5.76375574538582365885E-4, 

3366 1.63947561694133579842E-3, 

3367 -4.32430999505057594430E-3, 

3368 1.05464603945949983183E-2, 

3369 -2.37374148058994688156E-2, 

3370 4.93052842396707084878E-2, 

3371 -9.49010970480476444210E-2, 

3372 1.71620901522208775349E-1, 

3373 -3.04682672343198398683E-1, 

3374 6.76795274409476084995E-1 

3375 ] 

3376 

3377_i0B = [ 

3378 -7.23318048787475395456E-18, 

3379 -4.83050448594418207126E-18, 

3380 4.46562142029675999901E-17, 

3381 3.46122286769746109310E-17, 

3382 -2.82762398051658348494E-16, 

3383 -3.42548561967721913462E-16, 

3384 1.77256013305652638360E-15, 

3385 3.81168066935262242075E-15, 

3386 -9.55484669882830764870E-15, 

3387 -4.15056934728722208663E-14, 

3388 1.54008621752140982691E-14, 

3389 3.85277838274214270114E-13, 

3390 7.18012445138366623367E-13, 

3391 -1.79417853150680611778E-12, 

3392 -1.32158118404477131188E-11, 

3393 -3.14991652796324136454E-11, 

3394 1.18891471078464383424E-11, 

3395 4.94060238822496958910E-10, 

3396 3.39623202570838634515E-9, 

3397 2.26666899049817806459E-8, 

3398 2.04891858946906374183E-7, 

3399 2.89137052083475648297E-6, 

3400 6.88975834691682398426E-5, 

3401 3.36911647825569408990E-3, 

3402 8.04490411014108831608E-1 

3403 ] 

3404 

3405 

3406def _chbevl(x, vals): 

3407 b0 = vals[0] 

3408 b1 = 0.0 

3409 

3410 for i in range(1, len(vals)): 

3411 b2 = b1 

3412 b1 = b0 

3413 b0 = x*b1 - b2 + vals[i] 

3414 

3415 return 0.5*(b0 - b2) 

3416 

3417 

3418def _i0_1(x): 

3419 return exp(x) * _chbevl(x/2.0-2, _i0A) 

3420 

3421 

3422def _i0_2(x): 

3423 return exp(x) * _chbevl(32.0/x - 2.0, _i0B) / sqrt(x) 

3424 

3425 

3426def _i0_dispatcher(x): 

3427 return (x,) 

3428 

3429 

3430@array_function_dispatch(_i0_dispatcher) 

3431def i0(x): 

3432 """ 

3433 Modified Bessel function of the first kind, order 0. 

3434 

3435 Usually denoted :math:`I_0`. 

3436 

3437 Parameters 

3438 ---------- 

3439 x : array_like of float 

3440 Argument of the Bessel function. 

3441 

3442 Returns 

3443 ------- 

3444 out : ndarray, shape = x.shape, dtype = float 

3445 The modified Bessel function evaluated at each of the elements of `x`. 

3446 

3447 See Also 

3448 -------- 

3449 scipy.special.i0, scipy.special.iv, scipy.special.ive 

3450 

3451 Notes 

3452 ----- 

3453 The scipy implementation is recommended over this function: it is a 

3454 proper ufunc written in C, and more than an order of magnitude faster. 

3455 

3456 We use the algorithm published by Clenshaw [1]_ and referenced by 

3457 Abramowitz and Stegun [2]_, for which the function domain is 

3458 partitioned into the two intervals [0,8] and (8,inf), and Chebyshev 

3459 polynomial expansions are employed in each interval. Relative error on 

3460 the domain [0,30] using IEEE arithmetic is documented [3]_ as having a 

3461 peak of 5.8e-16 with an rms of 1.4e-16 (n = 30000). 

3462 

3463 References 

3464 ---------- 

3465 .. [1] C. W. Clenshaw, "Chebyshev series for mathematical functions", in 

3466 *National Physical Laboratory Mathematical Tables*, vol. 5, London: 

3467 Her Majesty's Stationery Office, 1962. 

3468 .. [2] M. Abramowitz and I. A. Stegun, *Handbook of Mathematical 

3469 Functions*, 10th printing, New York: Dover, 1964, pp. 379. 

3470 https://personal.math.ubc.ca/~cbm/aands/page_379.htm 

3471 .. [3] https://metacpan.org/pod/distribution/Math-Cephes/lib/Math/Cephes.pod#i0:-Modified-Bessel-function-of-order-zero 

3472 

3473 Examples 

3474 -------- 

3475 >>> np.i0(0.) 

3476 array(1.0) 

3477 >>> np.i0([0, 1, 2, 3]) 

3478 array([1. , 1.26606588, 2.2795853 , 4.88079259]) 

3479 

3480 """ 

3481 x = np.asanyarray(x) 

3482 if x.dtype.kind == 'c': 

3483 raise TypeError("i0 not supported for complex values") 

3484 if x.dtype.kind != 'f': 

3485 x = x.astype(float) 

3486 x = np.abs(x) 

3487 return piecewise(x, [x <= 8.0], [_i0_1, _i0_2]) 

3488 

3489## End of cephes code for i0 

3490 

3491 

3492@set_module('numpy') 

3493def kaiser(M, beta): 

3494 """ 

3495 Return the Kaiser window. 

3496 

3497 The Kaiser window is a taper formed by using a Bessel function. 

3498 

3499 Parameters 

3500 ---------- 

3501 M : int 

3502 Number of points in the output window. If zero or less, an 

3503 empty array is returned. 

3504 beta : float 

3505 Shape parameter for window. 

3506 

3507 Returns 

3508 ------- 

3509 out : array 

3510 The window, with the maximum value normalized to one (the value 

3511 one appears only if the number of samples is odd). 

3512 

3513 See Also 

3514 -------- 

3515 bartlett, blackman, hamming, hanning 

3516 

3517 Notes 

3518 ----- 

3519 The Kaiser window is defined as 

3520 

3521 .. math:: w(n) = I_0\\left( \\beta \\sqrt{1-\\frac{4n^2}{(M-1)^2}} 

3522 \\right)/I_0(\\beta) 

3523 

3524 with 

3525 

3526 .. math:: \\quad -\\frac{M-1}{2} \\leq n \\leq \\frac{M-1}{2}, 

3527 

3528 where :math:`I_0` is the modified zeroth-order Bessel function. 

3529 

3530 The Kaiser was named for Jim Kaiser, who discovered a simple 

3531 approximation to the DPSS window based on Bessel functions. The Kaiser 

3532 window is a very good approximation to the Digital Prolate Spheroidal 

3533 Sequence, or Slepian window, which is the transform which maximizes the 

3534 energy in the main lobe of the window relative to total energy. 

3535 

3536 The Kaiser can approximate many other windows by varying the beta 

3537 parameter. 

3538 

3539 ==== ======================= 

3540 beta Window shape 

3541 ==== ======================= 

3542 0 Rectangular 

3543 5 Similar to a Hamming 

3544 6 Similar to a Hanning 

3545 8.6 Similar to a Blackman 

3546 ==== ======================= 

3547 

3548 A beta value of 14 is probably a good starting point. Note that as beta 

3549 gets large, the window narrows, and so the number of samples needs to be 

3550 large enough to sample the increasingly narrow spike, otherwise NaNs will 

3551 get returned. 

3552 

3553 Most references to the Kaiser window come from the signal processing 

3554 literature, where it is used as one of many windowing functions for 

3555 smoothing values. It is also known as an apodization (which means 

3556 "removing the foot", i.e. smoothing discontinuities at the beginning 

3557 and end of the sampled signal) or tapering function. 

3558 

3559 References 

3560 ---------- 

3561 .. [1] J. F. Kaiser, "Digital Filters" - Ch 7 in "Systems analysis by 

3562 digital computer", Editors: F.F. Kuo and J.F. Kaiser, p 218-285. 

3563 John Wiley and Sons, New York, (1966). 

3564 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The 

3565 University of Alberta Press, 1975, pp. 177-178. 

3566 .. [3] Wikipedia, "Window function", 

3567 https://en.wikipedia.org/wiki/Window_function 

3568 

3569 Examples 

3570 -------- 

3571 >>> import matplotlib.pyplot as plt 

3572 >>> np.kaiser(12, 14) 

3573 array([7.72686684e-06, 3.46009194e-03, 4.65200189e-02, # may vary 

3574 2.29737120e-01, 5.99885316e-01, 9.45674898e-01, 

3575 9.45674898e-01, 5.99885316e-01, 2.29737120e-01, 

3576 4.65200189e-02, 3.46009194e-03, 7.72686684e-06]) 

3577 

3578 

3579 Plot the window and the frequency response: 

3580 

3581 >>> from numpy.fft import fft, fftshift 

3582 >>> window = np.kaiser(51, 14) 

3583 >>> plt.plot(window) 

3584 [<matplotlib.lines.Line2D object at 0x...>] 

3585 >>> plt.title("Kaiser window") 

3586 Text(0.5, 1.0, 'Kaiser window') 

3587 >>> plt.ylabel("Amplitude") 

3588 Text(0, 0.5, 'Amplitude') 

3589 >>> plt.xlabel("Sample") 

3590 Text(0.5, 0, 'Sample') 

3591 >>> plt.show() 

3592 

3593 >>> plt.figure() 

3594 <Figure size 640x480 with 0 Axes> 

3595 >>> A = fft(window, 2048) / 25.5 

3596 >>> mag = np.abs(fftshift(A)) 

3597 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3598 >>> response = 20 * np.log10(mag) 

3599 >>> response = np.clip(response, -100, 100) 

3600 >>> plt.plot(freq, response) 

3601 [<matplotlib.lines.Line2D object at 0x...>] 

3602 >>> plt.title("Frequency response of Kaiser window") 

3603 Text(0.5, 1.0, 'Frequency response of Kaiser window') 

3604 >>> plt.ylabel("Magnitude [dB]") 

3605 Text(0, 0.5, 'Magnitude [dB]') 

3606 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3607 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3608 >>> plt.axis('tight') 

3609 (-0.5, 0.5, -100.0, ...) # may vary 

3610 >>> plt.show() 

3611 

3612 """ 

3613 # Ensures at least float64 via 0.0. M should be an integer, but conversion 

3614 # to double is safe for a range. (Simplified result_type with 0.0 

3615 # strongly typed. result-type is not/less order sensitive, but that mainly 

3616 # matters for integers anyway.) 

3617 values = np.array([0.0, M, beta]) 

3618 M = values[1] 

3619 beta = values[2] 

3620 

3621 if M == 1: 

3622 return np.ones(1, dtype=values.dtype) 

3623 n = arange(0, M) 

3624 alpha = (M-1)/2.0 

3625 return i0(beta * sqrt(1-((n-alpha)/alpha)**2.0))/i0(beta) 

3626 

3627 

3628def _sinc_dispatcher(x): 

3629 return (x,) 

3630 

3631 

3632@array_function_dispatch(_sinc_dispatcher) 

3633def sinc(x): 

3634 r""" 

3635 Return the normalized sinc function. 

3636 

3637 The sinc function is equal to :math:`\sin(\pi x)/(\pi x)` for any argument 

3638 :math:`x\ne 0`. ``sinc(0)`` takes the limit value 1, making ``sinc`` not 

3639 only everywhere continuous but also infinitely differentiable. 

3640 

3641 .. note:: 

3642 

3643 Note the normalization factor of ``pi`` used in the definition. 

3644 This is the most commonly used definition in signal processing. 

3645 Use ``sinc(x / np.pi)`` to obtain the unnormalized sinc function 

3646 :math:`\sin(x)/x` that is more common in mathematics. 

3647 

3648 Parameters 

3649 ---------- 

3650 x : ndarray 

3651 Array (possibly multi-dimensional) of values for which to calculate 

3652 ``sinc(x)``. 

3653 

3654 Returns 

3655 ------- 

3656 out : ndarray 

3657 ``sinc(x)``, which has the same shape as the input. 

3658 

3659 Notes 

3660 ----- 

3661 The name sinc is short for "sine cardinal" or "sinus cardinalis". 

3662 

3663 The sinc function is used in various signal processing applications, 

3664 including in anti-aliasing, in the construction of a Lanczos resampling 

3665 filter, and in interpolation. 

3666 

3667 For bandlimited interpolation of discrete-time signals, the ideal 

3668 interpolation kernel is proportional to the sinc function. 

3669 

3670 References 

3671 ---------- 

3672 .. [1] Weisstein, Eric W. "Sinc Function." From MathWorld--A Wolfram Web 

3673 Resource. http://mathworld.wolfram.com/SincFunction.html 

3674 .. [2] Wikipedia, "Sinc function", 

3675 https://en.wikipedia.org/wiki/Sinc_function 

3676 

3677 Examples 

3678 -------- 

3679 >>> import matplotlib.pyplot as plt 

3680 >>> x = np.linspace(-4, 4, 41) 

3681 >>> np.sinc(x) 

3682 array([-3.89804309e-17, -4.92362781e-02, -8.40918587e-02, # may vary 

3683 -8.90384387e-02, -5.84680802e-02, 3.89804309e-17, 

3684 6.68206631e-02, 1.16434881e-01, 1.26137788e-01, 

3685 8.50444803e-02, -3.89804309e-17, -1.03943254e-01, 

3686 -1.89206682e-01, -2.16236208e-01, -1.55914881e-01, 

3687 3.89804309e-17, 2.33872321e-01, 5.04551152e-01, 

3688 7.56826729e-01, 9.35489284e-01, 1.00000000e+00, 

3689 9.35489284e-01, 7.56826729e-01, 5.04551152e-01, 

3690 2.33872321e-01, 3.89804309e-17, -1.55914881e-01, 

3691 -2.16236208e-01, -1.89206682e-01, -1.03943254e-01, 

3692 -3.89804309e-17, 8.50444803e-02, 1.26137788e-01, 

3693 1.16434881e-01, 6.68206631e-02, 3.89804309e-17, 

3694 -5.84680802e-02, -8.90384387e-02, -8.40918587e-02, 

3695 -4.92362781e-02, -3.89804309e-17]) 

3696 

3697 >>> plt.plot(x, np.sinc(x)) 

3698 [<matplotlib.lines.Line2D object at 0x...>] 

3699 >>> plt.title("Sinc Function") 

3700 Text(0.5, 1.0, 'Sinc Function') 

3701 >>> plt.ylabel("Amplitude") 

3702 Text(0, 0.5, 'Amplitude') 

3703 >>> plt.xlabel("X") 

3704 Text(0.5, 0, 'X') 

3705 >>> plt.show() 

3706 

3707 """ 

3708 x = np.asanyarray(x) 

3709 y = pi * where(x == 0, 1.0e-20, x) 

3710 return sin(y)/y 

3711 

3712 

3713def _msort_dispatcher(a): 

3714 return (a,) 

3715 

3716 

3717@array_function_dispatch(_msort_dispatcher) 

3718def msort(a): 

3719 """ 

3720 Return a copy of an array sorted along the first axis. 

3721 

3722 .. deprecated:: 1.24 

3723 

3724 msort is deprecated, use ``np.sort(a, axis=0)`` instead. 

3725 

3726 Parameters 

3727 ---------- 

3728 a : array_like 

3729 Array to be sorted. 

3730 

3731 Returns 

3732 ------- 

3733 sorted_array : ndarray 

3734 Array of the same type and shape as `a`. 

3735 

3736 See Also 

3737 -------- 

3738 sort 

3739 

3740 Notes 

3741 ----- 

3742 ``np.msort(a)`` is equivalent to ``np.sort(a, axis=0)``. 

3743 

3744 Examples 

3745 -------- 

3746 >>> a = np.array([[1, 4], [3, 1]]) 

3747 >>> np.msort(a) # sort along the first axis 

3748 array([[1, 1], 

3749 [3, 4]]) 

3750 

3751 """ 

3752 # 2022-10-20 1.24 

3753 warnings.warn( 

3754 "msort is deprecated, use np.sort(a, axis=0) instead", 

3755 DeprecationWarning, 

3756 stacklevel=2, 

3757 ) 

3758 b = array(a, subok=True, copy=True) 

3759 b.sort(0) 

3760 return b 

3761 

3762 

3763def _ureduce(a, func, keepdims=False, **kwargs): 

3764 """ 

3765 Internal Function. 

3766 Call `func` with `a` as first argument swapping the axes to use extended 

3767 axis on functions that don't support it natively. 

3768 

3769 Returns result and a.shape with axis dims set to 1. 

3770 

3771 Parameters 

3772 ---------- 

3773 a : array_like 

3774 Input array or object that can be converted to an array. 

3775 func : callable 

3776 Reduction function capable of receiving a single axis argument. 

3777 It is called with `a` as first argument followed by `kwargs`. 

3778 kwargs : keyword arguments 

3779 additional keyword arguments to pass to `func`. 

3780 

3781 Returns 

3782 ------- 

3783 result : tuple 

3784 Result of func(a, **kwargs) and a.shape with axis dims set to 1 

3785 which can be used to reshape the result to the same shape a ufunc with 

3786 keepdims=True would produce. 

3787 

3788 """ 

3789 a = np.asanyarray(a) 

3790 axis = kwargs.get('axis', None) 

3791 out = kwargs.get('out', None) 

3792 

3793 if keepdims is np._NoValue: 

3794 keepdims = False 

3795 

3796 nd = a.ndim 

3797 if axis is not None: 

3798 axis = _nx.normalize_axis_tuple(axis, nd) 

3799 

3800 if keepdims: 

3801 if out is not None: 

3802 index_out = tuple( 

3803 0 if i in axis else slice(None) for i in range(nd)) 

3804 kwargs['out'] = out[(Ellipsis, ) + index_out] 

3805 

3806 if len(axis) == 1: 

3807 kwargs['axis'] = axis[0] 

3808 else: 

3809 keep = set(range(nd)) - set(axis) 

3810 nkeep = len(keep) 

3811 # swap axis that should not be reduced to front 

3812 for i, s in enumerate(sorted(keep)): 

3813 a = a.swapaxes(i, s) 

3814 # merge reduced axis 

3815 a = a.reshape(a.shape[:nkeep] + (-1,)) 

3816 kwargs['axis'] = -1 

3817 else: 

3818 if keepdims: 

3819 if out is not None: 

3820 index_out = (0, ) * nd 

3821 kwargs['out'] = out[(Ellipsis, ) + index_out] 

3822 

3823 r = func(a, **kwargs) 

3824 

3825 if out is not None: 

3826 return out 

3827 

3828 if keepdims: 

3829 if axis is None: 

3830 index_r = (np.newaxis, ) * nd 

3831 else: 

3832 index_r = tuple( 

3833 np.newaxis if i in axis else slice(None) 

3834 for i in range(nd)) 

3835 r = r[(Ellipsis, ) + index_r] 

3836 

3837 return r 

3838 

3839 

3840def _median_dispatcher( 

3841 a, axis=None, out=None, overwrite_input=None, keepdims=None): 

3842 return (a, out) 

3843 

3844 

3845@array_function_dispatch(_median_dispatcher) 

3846def median(a, axis=None, out=None, overwrite_input=False, keepdims=False): 

3847 """ 

3848 Compute the median along the specified axis. 

3849 

3850 Returns the median of the array elements. 

3851 

3852 Parameters 

3853 ---------- 

3854 a : array_like 

3855 Input array or object that can be converted to an array. 

3856 axis : {int, sequence of int, None}, optional 

3857 Axis or axes along which the medians are computed. The default 

3858 is to compute the median along a flattened version of the array. 

3859 A sequence of axes is supported since version 1.9.0. 

3860 out : ndarray, optional 

3861 Alternative output array in which to place the result. It must 

3862 have the same shape and buffer length as the expected output, 

3863 but the type (of the output) will be cast if necessary. 

3864 overwrite_input : bool, optional 

3865 If True, then allow use of memory of input array `a` for 

3866 calculations. The input array will be modified by the call to 

3867 `median`. This will save memory when you do not need to preserve 

3868 the contents of the input array. Treat the input as undefined, 

3869 but it will probably be fully or partially sorted. Default is 

3870 False. If `overwrite_input` is ``True`` and `a` is not already an 

3871 `ndarray`, an error will be raised. 

3872 keepdims : bool, optional 

3873 If this is set to True, the axes which are reduced are left 

3874 in the result as dimensions with size one. With this option, 

3875 the result will broadcast correctly against the original `arr`. 

3876 

3877 .. versionadded:: 1.9.0 

3878 

3879 Returns 

3880 ------- 

3881 median : ndarray 

3882 A new array holding the result. If the input contains integers 

3883 or floats smaller than ``float64``, then the output data-type is 

3884 ``np.float64``. Otherwise, the data-type of the output is the 

3885 same as that of the input. If `out` is specified, that array is 

3886 returned instead. 

3887 

3888 See Also 

3889 -------- 

3890 mean, percentile 

3891 

3892 Notes 

3893 ----- 

3894 Given a vector ``V`` of length ``N``, the median of ``V`` is the 

3895 middle value of a sorted copy of ``V``, ``V_sorted`` - i 

3896 e., ``V_sorted[(N-1)/2]``, when ``N`` is odd, and the average of the 

3897 two middle values of ``V_sorted`` when ``N`` is even. 

3898 

3899 Examples 

3900 -------- 

3901 >>> a = np.array([[10, 7, 4], [3, 2, 1]]) 

3902 >>> a 

3903 array([[10, 7, 4], 

3904 [ 3, 2, 1]]) 

3905 >>> np.median(a) 

3906 3.5 

3907 >>> np.median(a, axis=0) 

3908 array([6.5, 4.5, 2.5]) 

3909 >>> np.median(a, axis=1) 

3910 array([7., 2.]) 

3911 >>> m = np.median(a, axis=0) 

3912 >>> out = np.zeros_like(m) 

3913 >>> np.median(a, axis=0, out=m) 

3914 array([6.5, 4.5, 2.5]) 

3915 >>> m 

3916 array([6.5, 4.5, 2.5]) 

3917 >>> b = a.copy() 

3918 >>> np.median(b, axis=1, overwrite_input=True) 

3919 array([7., 2.]) 

3920 >>> assert not np.all(a==b) 

3921 >>> b = a.copy() 

3922 >>> np.median(b, axis=None, overwrite_input=True) 

3923 3.5 

3924 >>> assert not np.all(a==b) 

3925 

3926 """ 

3927 return _ureduce(a, func=_median, keepdims=keepdims, axis=axis, out=out, 

3928 overwrite_input=overwrite_input) 

3929 

3930 

3931def _median(a, axis=None, out=None, overwrite_input=False): 

3932 # can't be reasonably be implemented in terms of percentile as we have to 

3933 # call mean to not break astropy 

3934 a = np.asanyarray(a) 

3935 

3936 # Set the partition indexes 

3937 if axis is None: 

3938 sz = a.size 

3939 else: 

3940 sz = a.shape[axis] 

3941 if sz % 2 == 0: 

3942 szh = sz // 2 

3943 kth = [szh - 1, szh] 

3944 else: 

3945 kth = [(sz - 1) // 2] 

3946 

3947 # We have to check for NaNs (as of writing 'M' doesn't actually work). 

3948 supports_nans = np.issubdtype(a.dtype, np.inexact) or a.dtype.kind in 'Mm' 

3949 if supports_nans: 

3950 kth.append(-1) 

3951 

3952 if overwrite_input: 

3953 if axis is None: 

3954 part = a.ravel() 

3955 part.partition(kth) 

3956 else: 

3957 a.partition(kth, axis=axis) 

3958 part = a 

3959 else: 

3960 part = partition(a, kth, axis=axis) 

3961 

3962 if part.shape == (): 

3963 # make 0-D arrays work 

3964 return part.item() 

3965 if axis is None: 

3966 axis = 0 

3967 

3968 indexer = [slice(None)] * part.ndim 

3969 index = part.shape[axis] // 2 

3970 if part.shape[axis] % 2 == 1: 

3971 # index with slice to allow mean (below) to work 

3972 indexer[axis] = slice(index, index+1) 

3973 else: 

3974 indexer[axis] = slice(index-1, index+1) 

3975 indexer = tuple(indexer) 

3976 

3977 # Use mean in both odd and even case to coerce data type, 

3978 # using out array if needed. 

3979 rout = mean(part[indexer], axis=axis, out=out) 

3980 if supports_nans and sz > 0: 

3981 # If nans are possible, warn and replace by nans like mean would. 

3982 rout = np.lib.utils._median_nancheck(part, rout, axis) 

3983 

3984 return rout 

3985 

3986 

3987def _percentile_dispatcher(a, q, axis=None, out=None, overwrite_input=None, 

3988 method=None, keepdims=None, *, interpolation=None): 

3989 return (a, q, out) 

3990 

3991 

3992@array_function_dispatch(_percentile_dispatcher) 

3993def percentile(a, 

3994 q, 

3995 axis=None, 

3996 out=None, 

3997 overwrite_input=False, 

3998 method="linear", 

3999 keepdims=False, 

4000 *, 

4001 interpolation=None): 

4002 """ 

4003 Compute the q-th percentile of the data along the specified axis. 

4004 

4005 Returns the q-th percentile(s) of the array elements. 

4006 

4007 Parameters 

4008 ---------- 

4009 a : array_like of real numbers 

4010 Input array or object that can be converted to an array. 

4011 q : array_like of float 

4012 Percentage or sequence of percentages for the percentiles to compute. 

4013 Values must be between 0 and 100 inclusive. 

4014 axis : {int, tuple of int, None}, optional 

4015 Axis or axes along which the percentiles are computed. The 

4016 default is to compute the percentile(s) along a flattened 

4017 version of the array. 

4018 

4019 .. versionchanged:: 1.9.0 

4020 A tuple of axes is supported 

4021 out : ndarray, optional 

4022 Alternative output array in which to place the result. It must 

4023 have the same shape and buffer length as the expected output, 

4024 but the type (of the output) will be cast if necessary. 

4025 overwrite_input : bool, optional 

4026 If True, then allow the input array `a` to be modified by intermediate 

4027 calculations, to save memory. In this case, the contents of the input 

4028 `a` after this function completes is undefined. 

4029 method : str, optional 

4030 This parameter specifies the method to use for estimating the 

4031 percentile. There are many different methods, some unique to NumPy. 

4032 See the notes for explanation. The options sorted by their R type 

4033 as summarized in the H&F paper [1]_ are: 

4034 

4035 1. 'inverted_cdf' 

4036 2. 'averaged_inverted_cdf' 

4037 3. 'closest_observation' 

4038 4. 'interpolated_inverted_cdf' 

4039 5. 'hazen' 

4040 6. 'weibull' 

4041 7. 'linear' (default) 

4042 8. 'median_unbiased' 

4043 9. 'normal_unbiased' 

4044 

4045 The first three methods are discontinuous. NumPy further defines the 

4046 following discontinuous variations of the default 'linear' (7.) option: 

4047 

4048 * 'lower' 

4049 * 'higher', 

4050 * 'midpoint' 

4051 * 'nearest' 

4052 

4053 .. versionchanged:: 1.22.0 

4054 This argument was previously called "interpolation" and only 

4055 offered the "linear" default and last four options. 

4056 

4057 keepdims : bool, optional 

4058 If this is set to True, the axes which are reduced are left in 

4059 the result as dimensions with size one. With this option, the 

4060 result will broadcast correctly against the original array `a`. 

4061 

4062 .. versionadded:: 1.9.0 

4063 

4064 interpolation : str, optional 

4065 Deprecated name for the method keyword argument. 

4066 

4067 .. deprecated:: 1.22.0 

4068 

4069 Returns 

4070 ------- 

4071 percentile : scalar or ndarray 

4072 If `q` is a single percentile and `axis=None`, then the result 

4073 is a scalar. If multiple percentiles are given, first axis of 

4074 the result corresponds to the percentiles. The other axes are 

4075 the axes that remain after the reduction of `a`. If the input 

4076 contains integers or floats smaller than ``float64``, the output 

4077 data-type is ``float64``. Otherwise, the output data-type is the 

4078 same as that of the input. If `out` is specified, that array is 

4079 returned instead. 

4080 

4081 See Also 

4082 -------- 

4083 mean 

4084 median : equivalent to ``percentile(..., 50)`` 

4085 nanpercentile 

4086 quantile : equivalent to percentile, except q in the range [0, 1]. 

4087 

4088 Notes 

4089 ----- 

4090 Given a vector ``V`` of length ``n``, the q-th percentile of ``V`` is 

4091 the value ``q/100`` of the way from the minimum to the maximum in a 

4092 sorted copy of ``V``. The values and distances of the two nearest 

4093 neighbors as well as the `method` parameter will determine the 

4094 percentile if the normalized ranking does not match the location of 

4095 ``q`` exactly. This function is the same as the median if ``q=50``, the 

4096 same as the minimum if ``q=0`` and the same as the maximum if 

4097 ``q=100``. 

4098 

4099 The optional `method` parameter specifies the method to use when the 

4100 desired percentile lies between two indexes ``i`` and ``j = i + 1``. 

4101 In that case, we first determine ``i + g``, a virtual index that lies 

4102 between ``i`` and ``j``, where ``i`` is the floor and ``g`` is the 

4103 fractional part of the index. The final result is, then, an interpolation 

4104 of ``a[i]`` and ``a[j]`` based on ``g``. During the computation of ``g``, 

4105 ``i`` and ``j`` are modified using correction constants ``alpha`` and 

4106 ``beta`` whose choices depend on the ``method`` used. Finally, note that 

4107 since Python uses 0-based indexing, the code subtracts another 1 from the 

4108 index internally. 

4109 

4110 The following formula determines the virtual index ``i + g``, the location 

4111 of the percentile in the sorted sample: 

4112 

4113 .. math:: 

4114 i + g = (q / 100) * ( n - alpha - beta + 1 ) + alpha 

4115 

4116 The different methods then work as follows 

4117 

4118 inverted_cdf: 

4119 method 1 of H&F [1]_. 

4120 This method gives discontinuous results: 

4121 

4122 * if g > 0 ; then take j 

4123 * if g = 0 ; then take i 

4124 

4125 averaged_inverted_cdf: 

4126 method 2 of H&F [1]_. 

4127 This method give discontinuous results: 

4128 

4129 * if g > 0 ; then take j 

4130 * if g = 0 ; then average between bounds 

4131 

4132 closest_observation: 

4133 method 3 of H&F [1]_. 

4134 This method give discontinuous results: 

4135 

4136 * if g > 0 ; then take j 

4137 * if g = 0 and index is odd ; then take j 

4138 * if g = 0 and index is even ; then take i 

4139 

4140 interpolated_inverted_cdf: 

4141 method 4 of H&F [1]_. 

4142 This method give continuous results using: 

4143 

4144 * alpha = 0 

4145 * beta = 1 

4146 

4147 hazen: 

4148 method 5 of H&F [1]_. 

4149 This method give continuous results using: 

4150 

4151 * alpha = 1/2 

4152 * beta = 1/2 

4153 

4154 weibull: 

4155 method 6 of H&F [1]_. 

4156 This method give continuous results using: 

4157 

4158 * alpha = 0 

4159 * beta = 0 

4160 

4161 linear: 

4162 method 7 of H&F [1]_. 

4163 This method give continuous results using: 

4164 

4165 * alpha = 1 

4166 * beta = 1 

4167 

4168 median_unbiased: 

4169 method 8 of H&F [1]_. 

4170 This method is probably the best method if the sample 

4171 distribution function is unknown (see reference). 

4172 This method give continuous results using: 

4173 

4174 * alpha = 1/3 

4175 * beta = 1/3 

4176 

4177 normal_unbiased: 

4178 method 9 of H&F [1]_. 

4179 This method is probably the best method if the sample 

4180 distribution function is known to be normal. 

4181 This method give continuous results using: 

4182 

4183 * alpha = 3/8 

4184 * beta = 3/8 

4185 

4186 lower: 

4187 NumPy method kept for backwards compatibility. 

4188 Takes ``i`` as the interpolation point. 

4189 

4190 higher: 

4191 NumPy method kept for backwards compatibility. 

4192 Takes ``j`` as the interpolation point. 

4193 

4194 nearest: 

4195 NumPy method kept for backwards compatibility. 

4196 Takes ``i`` or ``j``, whichever is nearest. 

4197 

4198 midpoint: 

4199 NumPy method kept for backwards compatibility. 

4200 Uses ``(i + j) / 2``. 

4201 

4202 Examples 

4203 -------- 

4204 >>> a = np.array([[10, 7, 4], [3, 2, 1]]) 

4205 >>> a 

4206 array([[10, 7, 4], 

4207 [ 3, 2, 1]]) 

4208 >>> np.percentile(a, 50) 

4209 3.5 

4210 >>> np.percentile(a, 50, axis=0) 

4211 array([6.5, 4.5, 2.5]) 

4212 >>> np.percentile(a, 50, axis=1) 

4213 array([7., 2.]) 

4214 >>> np.percentile(a, 50, axis=1, keepdims=True) 

4215 array([[7.], 

4216 [2.]]) 

4217 

4218 >>> m = np.percentile(a, 50, axis=0) 

4219 >>> out = np.zeros_like(m) 

4220 >>> np.percentile(a, 50, axis=0, out=out) 

4221 array([6.5, 4.5, 2.5]) 

4222 >>> m 

4223 array([6.5, 4.5, 2.5]) 

4224 

4225 >>> b = a.copy() 

4226 >>> np.percentile(b, 50, axis=1, overwrite_input=True) 

4227 array([7., 2.]) 

4228 >>> assert not np.all(a == b) 

4229 

4230 The different methods can be visualized graphically: 

4231 

4232 .. plot:: 

4233 

4234 import matplotlib.pyplot as plt 

4235 

4236 a = np.arange(4) 

4237 p = np.linspace(0, 100, 6001) 

4238 ax = plt.gca() 

4239 lines = [ 

4240 ('linear', '-', 'C0'), 

4241 ('inverted_cdf', ':', 'C1'), 

4242 # Almost the same as `inverted_cdf`: 

4243 ('averaged_inverted_cdf', '-.', 'C1'), 

4244 ('closest_observation', ':', 'C2'), 

4245 ('interpolated_inverted_cdf', '--', 'C1'), 

4246 ('hazen', '--', 'C3'), 

4247 ('weibull', '-.', 'C4'), 

4248 ('median_unbiased', '--', 'C5'), 

4249 ('normal_unbiased', '-.', 'C6'), 

4250 ] 

4251 for method, style, color in lines: 

4252 ax.plot( 

4253 p, np.percentile(a, p, method=method), 

4254 label=method, linestyle=style, color=color) 

4255 ax.set( 

4256 title='Percentiles for different methods and data: ' + str(a), 

4257 xlabel='Percentile', 

4258 ylabel='Estimated percentile value', 

4259 yticks=a) 

4260 ax.legend(bbox_to_anchor=(1.03, 1)) 

4261 plt.tight_layout() 

4262 plt.show() 

4263 

4264 References 

4265 ---------- 

4266 .. [1] R. J. Hyndman and Y. Fan, 

4267 "Sample quantiles in statistical packages," 

4268 The American Statistician, 50(4), pp. 361-365, 1996 

4269 

4270 """ 

4271 if interpolation is not None: 

4272 method = _check_interpolation_as_method( 

4273 method, interpolation, "percentile") 

4274 

4275 a = np.asanyarray(a) 

4276 if a.dtype.kind == "c": 

4277 raise TypeError("a must be an array of real numbers") 

4278 

4279 q = np.true_divide(q, 100) 

4280 q = asanyarray(q) # undo any decay that the ufunc performed (see gh-13105) 

4281 if not _quantile_is_valid(q): 

4282 raise ValueError("Percentiles must be in the range [0, 100]") 

4283 return _quantile_unchecked( 

4284 a, q, axis, out, overwrite_input, method, keepdims) 

4285 

4286 

4287def _quantile_dispatcher(a, q, axis=None, out=None, overwrite_input=None, 

4288 method=None, keepdims=None, *, interpolation=None): 

4289 return (a, q, out) 

4290 

4291 

4292@array_function_dispatch(_quantile_dispatcher) 

4293def quantile(a, 

4294 q, 

4295 axis=None, 

4296 out=None, 

4297 overwrite_input=False, 

4298 method="linear", 

4299 keepdims=False, 

4300 *, 

4301 interpolation=None): 

4302 """ 

4303 Compute the q-th quantile of the data along the specified axis. 

4304 

4305 .. versionadded:: 1.15.0 

4306 

4307 Parameters 

4308 ---------- 

4309 a : array_like of real numbers 

4310 Input array or object that can be converted to an array. 

4311 q : array_like of float 

4312 Probability or sequence of probabilities for the quantiles to compute. 

4313 Values must be between 0 and 1 inclusive. 

4314 axis : {int, tuple of int, None}, optional 

4315 Axis or axes along which the quantiles are computed. The default is 

4316 to compute the quantile(s) along a flattened version of the array. 

4317 out : ndarray, optional 

4318 Alternative output array in which to place the result. It must have 

4319 the same shape and buffer length as the expected output, but the 

4320 type (of the output) will be cast if necessary. 

4321 overwrite_input : bool, optional 

4322 If True, then allow the input array `a` to be modified by 

4323 intermediate calculations, to save memory. In this case, the 

4324 contents of the input `a` after this function completes is 

4325 undefined. 

4326 method : str, optional 

4327 This parameter specifies the method to use for estimating the 

4328 quantile. There are many different methods, some unique to NumPy. 

4329 See the notes for explanation. The options sorted by their R type 

4330 as summarized in the H&F paper [1]_ are: 

4331 

4332 1. 'inverted_cdf' 

4333 2. 'averaged_inverted_cdf' 

4334 3. 'closest_observation' 

4335 4. 'interpolated_inverted_cdf' 

4336 5. 'hazen' 

4337 6. 'weibull' 

4338 7. 'linear' (default) 

4339 8. 'median_unbiased' 

4340 9. 'normal_unbiased' 

4341 

4342 The first three methods are discontinuous. NumPy further defines the 

4343 following discontinuous variations of the default 'linear' (7.) option: 

4344 

4345 * 'lower' 

4346 * 'higher', 

4347 * 'midpoint' 

4348 * 'nearest' 

4349 

4350 .. versionchanged:: 1.22.0 

4351 This argument was previously called "interpolation" and only 

4352 offered the "linear" default and last four options. 

4353 

4354 keepdims : bool, optional 

4355 If this is set to True, the axes which are reduced are left in 

4356 the result as dimensions with size one. With this option, the 

4357 result will broadcast correctly against the original array `a`. 

4358 

4359 interpolation : str, optional 

4360 Deprecated name for the method keyword argument. 

4361 

4362 .. deprecated:: 1.22.0 

4363 

4364 Returns 

4365 ------- 

4366 quantile : scalar or ndarray 

4367 If `q` is a single probability and `axis=None`, then the result 

4368 is a scalar. If multiple probabilies levels are given, first axis of 

4369 the result corresponds to the quantiles. The other axes are 

4370 the axes that remain after the reduction of `a`. If the input 

4371 contains integers or floats smaller than ``float64``, the output 

4372 data-type is ``float64``. Otherwise, the output data-type is the 

4373 same as that of the input. If `out` is specified, that array is 

4374 returned instead. 

4375 

4376 See Also 

4377 -------- 

4378 mean 

4379 percentile : equivalent to quantile, but with q in the range [0, 100]. 

4380 median : equivalent to ``quantile(..., 0.5)`` 

4381 nanquantile 

4382 

4383 Notes 

4384 ----- 

4385 Given a vector ``V`` of length ``n``, the q-th quantile of ``V`` is 

4386 the value ``q`` of the way from the minimum to the maximum in a 

4387 sorted copy of ``V``. The values and distances of the two nearest 

4388 neighbors as well as the `method` parameter will determine the 

4389 quantile if the normalized ranking does not match the location of 

4390 ``q`` exactly. This function is the same as the median if ``q=0.5``, the 

4391 same as the minimum if ``q=0.0`` and the same as the maximum if 

4392 ``q=1.0``. 

4393 

4394 The optional `method` parameter specifies the method to use when the 

4395 desired quantile lies between two indexes ``i`` and ``j = i + 1``. 

4396 In that case, we first determine ``i + g``, a virtual index that lies 

4397 between ``i`` and ``j``, where ``i`` is the floor and ``g`` is the 

4398 fractional part of the index. The final result is, then, an interpolation 

4399 of ``a[i]`` and ``a[j]`` based on ``g``. During the computation of ``g``, 

4400 ``i`` and ``j`` are modified using correction constants ``alpha`` and 

4401 ``beta`` whose choices depend on the ``method`` used. Finally, note that 

4402 since Python uses 0-based indexing, the code subtracts another 1 from the 

4403 index internally. 

4404 

4405 The following formula determines the virtual index ``i + g``, the location 

4406 of the quantile in the sorted sample: 

4407 

4408 .. math:: 

4409 i + g = q * ( n - alpha - beta + 1 ) + alpha 

4410 

4411 The different methods then work as follows 

4412 

4413 inverted_cdf: 

4414 method 1 of H&F [1]_. 

4415 This method gives discontinuous results: 

4416 

4417 * if g > 0 ; then take j 

4418 * if g = 0 ; then take i 

4419 

4420 averaged_inverted_cdf: 

4421 method 2 of H&F [1]_. 

4422 This method gives discontinuous results: 

4423 

4424 * if g > 0 ; then take j 

4425 * if g = 0 ; then average between bounds 

4426 

4427 closest_observation: 

4428 method 3 of H&F [1]_. 

4429 This method gives discontinuous results: 

4430 

4431 * if g > 0 ; then take j 

4432 * if g = 0 and index is odd ; then take j 

4433 * if g = 0 and index is even ; then take i 

4434 

4435 interpolated_inverted_cdf: 

4436 method 4 of H&F [1]_. 

4437 This method gives continuous results using: 

4438 

4439 * alpha = 0 

4440 * beta = 1 

4441 

4442 hazen: 

4443 method 5 of H&F [1]_. 

4444 This method gives continuous results using: 

4445 

4446 * alpha = 1/2 

4447 * beta = 1/2 

4448 

4449 weibull: 

4450 method 6 of H&F [1]_. 

4451 This method gives continuous results using: 

4452 

4453 * alpha = 0 

4454 * beta = 0 

4455 

4456 linear: 

4457 method 7 of H&F [1]_. 

4458 This method gives continuous results using: 

4459 

4460 * alpha = 1 

4461 * beta = 1 

4462 

4463 median_unbiased: 

4464 method 8 of H&F [1]_. 

4465 This method is probably the best method if the sample 

4466 distribution function is unknown (see reference). 

4467 This method gives continuous results using: 

4468 

4469 * alpha = 1/3 

4470 * beta = 1/3 

4471 

4472 normal_unbiased: 

4473 method 9 of H&F [1]_. 

4474 This method is probably the best method if the sample 

4475 distribution function is known to be normal. 

4476 This method gives continuous results using: 

4477 

4478 * alpha = 3/8 

4479 * beta = 3/8 

4480 

4481 lower: 

4482 NumPy method kept for backwards compatibility. 

4483 Takes ``i`` as the interpolation point. 

4484 

4485 higher: 

4486 NumPy method kept for backwards compatibility. 

4487 Takes ``j`` as the interpolation point. 

4488 

4489 nearest: 

4490 NumPy method kept for backwards compatibility. 

4491 Takes ``i`` or ``j``, whichever is nearest. 

4492 

4493 midpoint: 

4494 NumPy method kept for backwards compatibility. 

4495 Uses ``(i + j) / 2``. 

4496 

4497 Examples 

4498 -------- 

4499 >>> a = np.array([[10, 7, 4], [3, 2, 1]]) 

4500 >>> a 

4501 array([[10, 7, 4], 

4502 [ 3, 2, 1]]) 

4503 >>> np.quantile(a, 0.5) 

4504 3.5 

4505 >>> np.quantile(a, 0.5, axis=0) 

4506 array([6.5, 4.5, 2.5]) 

4507 >>> np.quantile(a, 0.5, axis=1) 

4508 array([7., 2.]) 

4509 >>> np.quantile(a, 0.5, axis=1, keepdims=True) 

4510 array([[7.], 

4511 [2.]]) 

4512 >>> m = np.quantile(a, 0.5, axis=0) 

4513 >>> out = np.zeros_like(m) 

4514 >>> np.quantile(a, 0.5, axis=0, out=out) 

4515 array([6.5, 4.5, 2.5]) 

4516 >>> m 

4517 array([6.5, 4.5, 2.5]) 

4518 >>> b = a.copy() 

4519 >>> np.quantile(b, 0.5, axis=1, overwrite_input=True) 

4520 array([7., 2.]) 

4521 >>> assert not np.all(a == b) 

4522 

4523 See also `numpy.percentile` for a visualization of most methods. 

4524 

4525 References 

4526 ---------- 

4527 .. [1] R. J. Hyndman and Y. Fan, 

4528 "Sample quantiles in statistical packages," 

4529 The American Statistician, 50(4), pp. 361-365, 1996 

4530 

4531 """ 

4532 if interpolation is not None: 

4533 method = _check_interpolation_as_method( 

4534 method, interpolation, "quantile") 

4535 

4536 a = np.asanyarray(a) 

4537 if a.dtype.kind == "c": 

4538 raise TypeError("a must be an array of real numbers") 

4539 

4540 q = np.asanyarray(q) 

4541 if not _quantile_is_valid(q): 

4542 raise ValueError("Quantiles must be in the range [0, 1]") 

4543 return _quantile_unchecked( 

4544 a, q, axis, out, overwrite_input, method, keepdims) 

4545 

4546 

4547def _quantile_unchecked(a, 

4548 q, 

4549 axis=None, 

4550 out=None, 

4551 overwrite_input=False, 

4552 method="linear", 

4553 keepdims=False): 

4554 """Assumes that q is in [0, 1], and is an ndarray""" 

4555 return _ureduce(a, 

4556 func=_quantile_ureduce_func, 

4557 q=q, 

4558 keepdims=keepdims, 

4559 axis=axis, 

4560 out=out, 

4561 overwrite_input=overwrite_input, 

4562 method=method) 

4563 

4564 

4565def _quantile_is_valid(q): 

4566 # avoid expensive reductions, relevant for arrays with < O(1000) elements 

4567 if q.ndim == 1 and q.size < 10: 

4568 for i in range(q.size): 

4569 if not (0.0 <= q[i] <= 1.0): 

4570 return False 

4571 else: 

4572 if not (np.all(0 <= q) and np.all(q <= 1)): 

4573 return False 

4574 return True 

4575 

4576 

4577def _check_interpolation_as_method(method, interpolation, fname): 

4578 # Deprecated NumPy 1.22, 2021-11-08 

4579 warnings.warn( 

4580 f"the `interpolation=` argument to {fname} was renamed to " 

4581 "`method=`, which has additional options.\n" 

4582 "Users of the modes 'nearest', 'lower', 'higher', or " 

4583 "'midpoint' are encouraged to review the method they used. " 

4584 "(Deprecated NumPy 1.22)", 

4585 DeprecationWarning, stacklevel=4) 

4586 if method != "linear": 

4587 # sanity check, we assume this basically never happens 

4588 raise TypeError( 

4589 "You shall not pass both `method` and `interpolation`!\n" 

4590 "(`interpolation` is Deprecated in favor of `method`)") 

4591 return interpolation 

4592 

4593 

4594def _compute_virtual_index(n, quantiles, alpha: float, beta: float): 

4595 """ 

4596 Compute the floating point indexes of an array for the linear 

4597 interpolation of quantiles. 

4598 n : array_like 

4599 The sample sizes. 

4600 quantiles : array_like 

4601 The quantiles values. 

4602 alpha : float 

4603 A constant used to correct the index computed. 

4604 beta : float 

4605 A constant used to correct the index computed. 

4606 

4607 alpha and beta values depend on the chosen method 

4608 (see quantile documentation) 

4609 

4610 Reference: 

4611 Hyndman&Fan paper "Sample Quantiles in Statistical Packages", 

4612 DOI: 10.1080/00031305.1996.10473566 

4613 """ 

4614 return n * quantiles + ( 

4615 alpha + quantiles * (1 - alpha - beta) 

4616 ) - 1 

4617 

4618 

4619def _get_gamma(virtual_indexes, previous_indexes, method): 

4620 """ 

4621 Compute gamma (a.k.a 'm' or 'weight') for the linear interpolation 

4622 of quantiles. 

4623 

4624 virtual_indexes : array_like 

4625 The indexes where the percentile is supposed to be found in the sorted 

4626 sample. 

4627 previous_indexes : array_like 

4628 The floor values of virtual_indexes. 

4629 interpolation : dict 

4630 The interpolation method chosen, which may have a specific rule 

4631 modifying gamma. 

4632 

4633 gamma is usually the fractional part of virtual_indexes but can be modified 

4634 by the interpolation method. 

4635 """ 

4636 gamma = np.asanyarray(virtual_indexes - previous_indexes) 

4637 gamma = method["fix_gamma"](gamma, virtual_indexes) 

4638 return np.asanyarray(gamma) 

4639 

4640 

4641def _lerp(a, b, t, out=None): 

4642 """ 

4643 Compute the linear interpolation weighted by gamma on each point of 

4644 two same shape array. 

4645 

4646 a : array_like 

4647 Left bound. 

4648 b : array_like 

4649 Right bound. 

4650 t : array_like 

4651 The interpolation weight. 

4652 out : array_like 

4653 Output array. 

4654 """ 

4655 diff_b_a = subtract(b, a) 

4656 # asanyarray is a stop-gap until gh-13105 

4657 lerp_interpolation = asanyarray(add(a, diff_b_a * t, out=out)) 

4658 subtract(b, diff_b_a * (1 - t), out=lerp_interpolation, where=t >= 0.5, 

4659 casting='unsafe', dtype=type(lerp_interpolation.dtype)) 

4660 if lerp_interpolation.ndim == 0 and out is None: 

4661 lerp_interpolation = lerp_interpolation[()] # unpack 0d arrays 

4662 return lerp_interpolation 

4663 

4664 

4665def _get_gamma_mask(shape, default_value, conditioned_value, where): 

4666 out = np.full(shape, default_value) 

4667 np.copyto(out, conditioned_value, where=where, casting="unsafe") 

4668 return out 

4669 

4670 

4671def _discret_interpolation_to_boundaries(index, gamma_condition_fun): 

4672 previous = np.floor(index) 

4673 next = previous + 1 

4674 gamma = index - previous 

4675 res = _get_gamma_mask(shape=index.shape, 

4676 default_value=next, 

4677 conditioned_value=previous, 

4678 where=gamma_condition_fun(gamma, index) 

4679 ).astype(np.intp) 

4680 # Some methods can lead to out-of-bound integers, clip them: 

4681 res[res < 0] = 0 

4682 return res 

4683 

4684 

4685def _closest_observation(n, quantiles): 

4686 gamma_fun = lambda gamma, index: (gamma == 0) & (np.floor(index) % 2 == 0) 

4687 return _discret_interpolation_to_boundaries((n * quantiles) - 1 - 0.5, 

4688 gamma_fun) 

4689 

4690 

4691def _inverted_cdf(n, quantiles): 

4692 gamma_fun = lambda gamma, _: (gamma == 0) 

4693 return _discret_interpolation_to_boundaries((n * quantiles) - 1, 

4694 gamma_fun) 

4695 

4696 

4697def _quantile_ureduce_func( 

4698 a: np.array, 

4699 q: np.array, 

4700 axis: int = None, 

4701 out=None, 

4702 overwrite_input: bool = False, 

4703 method="linear", 

4704) -> np.array: 

4705 if q.ndim > 2: 

4706 # The code below works fine for nd, but it might not have useful 

4707 # semantics. For now, keep the supported dimensions the same as it was 

4708 # before. 

4709 raise ValueError("q must be a scalar or 1d") 

4710 if overwrite_input: 

4711 if axis is None: 

4712 axis = 0 

4713 arr = a.ravel() 

4714 else: 

4715 arr = a 

4716 else: 

4717 if axis is None: 

4718 axis = 0 

4719 arr = a.flatten() 

4720 else: 

4721 arr = a.copy() 

4722 result = _quantile(arr, 

4723 quantiles=q, 

4724 axis=axis, 

4725 method=method, 

4726 out=out) 

4727 return result 

4728 

4729 

4730def _get_indexes(arr, virtual_indexes, valid_values_count): 

4731 """ 

4732 Get the valid indexes of arr neighbouring virtual_indexes. 

4733 Note 

4734 This is a companion function to linear interpolation of 

4735 Quantiles 

4736 

4737 Returns 

4738 ------- 

4739 (previous_indexes, next_indexes): Tuple 

4740 A Tuple of virtual_indexes neighbouring indexes 

4741 """ 

4742 previous_indexes = np.asanyarray(np.floor(virtual_indexes)) 

4743 next_indexes = np.asanyarray(previous_indexes + 1) 

4744 indexes_above_bounds = virtual_indexes >= valid_values_count - 1 

4745 # When indexes is above max index, take the max value of the array 

4746 if indexes_above_bounds.any(): 

4747 previous_indexes[indexes_above_bounds] = -1 

4748 next_indexes[indexes_above_bounds] = -1 

4749 # When indexes is below min index, take the min value of the array 

4750 indexes_below_bounds = virtual_indexes < 0 

4751 if indexes_below_bounds.any(): 

4752 previous_indexes[indexes_below_bounds] = 0 

4753 next_indexes[indexes_below_bounds] = 0 

4754 if np.issubdtype(arr.dtype, np.inexact): 

4755 # After the sort, slices having NaNs will have for last element a NaN 

4756 virtual_indexes_nans = np.isnan(virtual_indexes) 

4757 if virtual_indexes_nans.any(): 

4758 previous_indexes[virtual_indexes_nans] = -1 

4759 next_indexes[virtual_indexes_nans] = -1 

4760 previous_indexes = previous_indexes.astype(np.intp) 

4761 next_indexes = next_indexes.astype(np.intp) 

4762 return previous_indexes, next_indexes 

4763 

4764 

4765def _quantile( 

4766 arr: np.array, 

4767 quantiles: np.array, 

4768 axis: int = -1, 

4769 method="linear", 

4770 out=None, 

4771): 

4772 """ 

4773 Private function that doesn't support extended axis or keepdims. 

4774 These methods are extended to this function using _ureduce 

4775 See nanpercentile for parameter usage 

4776 It computes the quantiles of the array for the given axis. 

4777 A linear interpolation is performed based on the `interpolation`. 

4778 

4779 By default, the method is "linear" where alpha == beta == 1 which 

4780 performs the 7th method of Hyndman&Fan. 

4781 With "median_unbiased" we get alpha == beta == 1/3 

4782 thus the 8th method of Hyndman&Fan. 

4783 """ 

4784 # --- Setup 

4785 arr = np.asanyarray(arr) 

4786 values_count = arr.shape[axis] 

4787 # The dimensions of `q` are prepended to the output shape, so we need the 

4788 # axis being sampled from `arr` to be last. 

4789 

4790 if axis != 0: # But moveaxis is slow, so only call it if necessary. 

4791 arr = np.moveaxis(arr, axis, destination=0) 

4792 # --- Computation of indexes 

4793 # Index where to find the value in the sorted array. 

4794 # Virtual because it is a floating point value, not an valid index. 

4795 # The nearest neighbours are used for interpolation 

4796 try: 

4797 method = _QuantileMethods[method] 

4798 except KeyError: 

4799 raise ValueError( 

4800 f"{method!r} is not a valid method. Use one of: " 

4801 f"{_QuantileMethods.keys()}") from None 

4802 virtual_indexes = method["get_virtual_index"](values_count, quantiles) 

4803 virtual_indexes = np.asanyarray(virtual_indexes) 

4804 

4805 supports_nans = ( 

4806 np.issubdtype(arr.dtype, np.inexact) or arr.dtype.kind in 'Mm') 

4807 

4808 if np.issubdtype(virtual_indexes.dtype, np.integer): 

4809 # No interpolation needed, take the points along axis 

4810 if supports_nans: 

4811 # may contain nan, which would sort to the end 

4812 arr.partition(concatenate((virtual_indexes.ravel(), [-1])), axis=0) 

4813 slices_having_nans = np.isnan(arr[-1, ...]) 

4814 else: 

4815 # cannot contain nan 

4816 arr.partition(virtual_indexes.ravel(), axis=0) 

4817 slices_having_nans = np.array(False, dtype=bool) 

4818 result = take(arr, virtual_indexes, axis=0, out=out) 

4819 else: 

4820 previous_indexes, next_indexes = _get_indexes(arr, 

4821 virtual_indexes, 

4822 values_count) 

4823 # --- Sorting 

4824 arr.partition( 

4825 np.unique(np.concatenate(([0, -1], 

4826 previous_indexes.ravel(), 

4827 next_indexes.ravel(), 

4828 ))), 

4829 axis=0) 

4830 if supports_nans: 

4831 slices_having_nans = np.isnan(arr[-1, ...]) 

4832 else: 

4833 slices_having_nans = None 

4834 # --- Get values from indexes 

4835 previous = arr[previous_indexes] 

4836 next = arr[next_indexes] 

4837 # --- Linear interpolation 

4838 gamma = _get_gamma(virtual_indexes, previous_indexes, method) 

4839 result_shape = virtual_indexes.shape + (1,) * (arr.ndim - 1) 

4840 gamma = gamma.reshape(result_shape) 

4841 result = _lerp(previous, 

4842 next, 

4843 gamma, 

4844 out=out) 

4845 if np.any(slices_having_nans): 

4846 if result.ndim == 0 and out is None: 

4847 # can't write to a scalar, but indexing will be correct 

4848 result = arr[-1] 

4849 else: 

4850 np.copyto(result, arr[-1, ...], where=slices_having_nans) 

4851 return result 

4852 

4853 

4854def _trapz_dispatcher(y, x=None, dx=None, axis=None): 

4855 return (y, x) 

4856 

4857 

4858@array_function_dispatch(_trapz_dispatcher) 

4859def trapz(y, x=None, dx=1.0, axis=-1): 

4860 r""" 

4861 Integrate along the given axis using the composite trapezoidal rule. 

4862 

4863 If `x` is provided, the integration happens in sequence along its 

4864 elements - they are not sorted. 

4865 

4866 Integrate `y` (`x`) along each 1d slice on the given axis, compute 

4867 :math:`\int y(x) dx`. 

4868 When `x` is specified, this integrates along the parametric curve, 

4869 computing :math:`\int_t y(t) dt = 

4870 \int_t y(t) \left.\frac{dx}{dt}\right|_{x=x(t)} dt`. 

4871 

4872 Parameters 

4873 ---------- 

4874 y : array_like 

4875 Input array to integrate. 

4876 x : array_like, optional 

4877 The sample points corresponding to the `y` values. If `x` is None, 

4878 the sample points are assumed to be evenly spaced `dx` apart. The 

4879 default is None. 

4880 dx : scalar, optional 

4881 The spacing between sample points when `x` is None. The default is 1. 

4882 axis : int, optional 

4883 The axis along which to integrate. 

4884 

4885 Returns 

4886 ------- 

4887 trapz : float or ndarray 

4888 Definite integral of `y` = n-dimensional array as approximated along 

4889 a single axis by the trapezoidal rule. If `y` is a 1-dimensional array, 

4890 then the result is a float. If `n` is greater than 1, then the result 

4891 is an `n`-1 dimensional array. 

4892 

4893 See Also 

4894 -------- 

4895 sum, cumsum 

4896 

4897 Notes 

4898 ----- 

4899 Image [2]_ illustrates trapezoidal rule -- y-axis locations of points 

4900 will be taken from `y` array, by default x-axis distances between 

4901 points will be 1.0, alternatively they can be provided with `x` array 

4902 or with `dx` scalar. Return value will be equal to combined area under 

4903 the red lines. 

4904 

4905 

4906 References 

4907 ---------- 

4908 .. [1] Wikipedia page: https://en.wikipedia.org/wiki/Trapezoidal_rule 

4909 

4910 .. [2] Illustration image: 

4911 https://en.wikipedia.org/wiki/File:Composite_trapezoidal_rule_illustration.png 

4912 

4913 Examples 

4914 -------- 

4915 Use the trapezoidal rule on evenly spaced points: 

4916 

4917 >>> np.trapz([1, 2, 3]) 

4918 4.0 

4919 

4920 The spacing between sample points can be selected by either the 

4921 ``x`` or ``dx`` arguments: 

4922 

4923 >>> np.trapz([1, 2, 3], x=[4, 6, 8]) 

4924 8.0 

4925 >>> np.trapz([1, 2, 3], dx=2) 

4926 8.0 

4927 

4928 Using a decreasing ``x`` corresponds to integrating in reverse: 

4929 

4930 >>> np.trapz([1, 2, 3], x=[8, 6, 4]) 

4931 -8.0 

4932 

4933 More generally ``x`` is used to integrate along a parametric curve. We can 

4934 estimate the integral :math:`\int_0^1 x^2 = 1/3` using: 

4935 

4936 >>> x = np.linspace(0, 1, num=50) 

4937 >>> y = x**2 

4938 >>> np.trapz(y, x) 

4939 0.33340274885464394 

4940 

4941 Or estimate the area of a circle, noting we repeat the sample which closes 

4942 the curve: 

4943 

4944 >>> theta = np.linspace(0, 2 * np.pi, num=1000, endpoint=True) 

4945 >>> np.trapz(np.cos(theta), x=np.sin(theta)) 

4946 3.141571941375841 

4947 

4948 ``np.trapz`` can be applied along a specified axis to do multiple 

4949 computations in one call: 

4950 

4951 >>> a = np.arange(6).reshape(2, 3) 

4952 >>> a 

4953 array([[0, 1, 2], 

4954 [3, 4, 5]]) 

4955 >>> np.trapz(a, axis=0) 

4956 array([1.5, 2.5, 3.5]) 

4957 >>> np.trapz(a, axis=1) 

4958 array([2., 8.]) 

4959 """ 

4960 y = asanyarray(y) 

4961 if x is None: 

4962 d = dx 

4963 else: 

4964 x = asanyarray(x) 

4965 if x.ndim == 1: 

4966 d = diff(x) 

4967 # reshape to correct shape 

4968 shape = [1]*y.ndim 

4969 shape[axis] = d.shape[0] 

4970 d = d.reshape(shape) 

4971 else: 

4972 d = diff(x, axis=axis) 

4973 nd = y.ndim 

4974 slice1 = [slice(None)]*nd 

4975 slice2 = [slice(None)]*nd 

4976 slice1[axis] = slice(1, None) 

4977 slice2[axis] = slice(None, -1) 

4978 try: 

4979 ret = (d * (y[tuple(slice1)] + y[tuple(slice2)]) / 2.0).sum(axis) 

4980 except ValueError: 

4981 # Operations didn't work, cast to ndarray 

4982 d = np.asarray(d) 

4983 y = np.asarray(y) 

4984 ret = add.reduce(d * (y[tuple(slice1)]+y[tuple(slice2)])/2.0, axis) 

4985 return ret 

4986 

4987 

4988# __array_function__ has no __code__ or other attributes normal Python funcs we 

4989# wrap everything into a C callable. SciPy however, tries to "clone" `trapz` 

4990# into a new Python function which requires `__code__` and a few other 

4991# attributes. So we create a dummy clone and copy over its attributes allowing 

4992# SciPy <= 1.10 to work: https://github.com/scipy/scipy/issues/17811 

4993assert not hasattr(trapz, "__code__") 

4994 

4995def _fake_trapz(y, x=None, dx=1.0, axis=-1): 

4996 return trapz(y, x=x, dx=dx, axis=axis) 

4997 

4998 

4999trapz.__code__ = _fake_trapz.__code__ 

5000trapz.__globals__ = _fake_trapz.__globals__ 

5001trapz.__defaults__ = _fake_trapz.__defaults__ 

5002trapz.__closure__ = _fake_trapz.__closure__ 

5003trapz.__kwdefaults__ = _fake_trapz.__kwdefaults__ 

5004 

5005 

5006def _meshgrid_dispatcher(*xi, copy=None, sparse=None, indexing=None): 

5007 return xi 

5008 

5009 

5010# Based on scitools meshgrid 

5011@array_function_dispatch(_meshgrid_dispatcher) 

5012def meshgrid(*xi, copy=True, sparse=False, indexing='xy'): 

5013 """ 

5014 Return a list of coordinate matrices from coordinate vectors. 

5015 

5016 Make N-D coordinate arrays for vectorized evaluations of 

5017 N-D scalar/vector fields over N-D grids, given 

5018 one-dimensional coordinate arrays x1, x2,..., xn. 

5019 

5020 .. versionchanged:: 1.9 

5021 1-D and 0-D cases are allowed. 

5022 

5023 Parameters 

5024 ---------- 

5025 x1, x2,..., xn : array_like 

5026 1-D arrays representing the coordinates of a grid. 

5027 indexing : {'xy', 'ij'}, optional 

5028 Cartesian ('xy', default) or matrix ('ij') indexing of output. 

5029 See Notes for more details. 

5030 

5031 .. versionadded:: 1.7.0 

5032 sparse : bool, optional 

5033 If True the shape of the returned coordinate array for dimension *i* 

5034 is reduced from ``(N1, ..., Ni, ... Nn)`` to 

5035 ``(1, ..., 1, Ni, 1, ..., 1)``. These sparse coordinate grids are 

5036 intended to be use with :ref:`basics.broadcasting`. When all 

5037 coordinates are used in an expression, broadcasting still leads to a 

5038 fully-dimensonal result array. 

5039 

5040 Default is False. 

5041 

5042 .. versionadded:: 1.7.0 

5043 copy : bool, optional 

5044 If False, a view into the original arrays are returned in order to 

5045 conserve memory. Default is True. Please note that 

5046 ``sparse=False, copy=False`` will likely return non-contiguous 

5047 arrays. Furthermore, more than one element of a broadcast array 

5048 may refer to a single memory location. If you need to write to the 

5049 arrays, make copies first. 

5050 

5051 .. versionadded:: 1.7.0 

5052 

5053 Returns 

5054 ------- 

5055 X1, X2,..., XN : list of ndarrays 

5056 For vectors `x1`, `x2`,..., `xn` with lengths ``Ni=len(xi)``, 

5057 returns ``(N1, N2, N3,..., Nn)`` shaped arrays if indexing='ij' 

5058 or ``(N2, N1, N3,..., Nn)`` shaped arrays if indexing='xy' 

5059 with the elements of `xi` repeated to fill the matrix along 

5060 the first dimension for `x1`, the second for `x2` and so on. 

5061 

5062 Notes 

5063 ----- 

5064 This function supports both indexing conventions through the indexing 

5065 keyword argument. Giving the string 'ij' returns a meshgrid with 

5066 matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing. 

5067 In the 2-D case with inputs of length M and N, the outputs are of shape 

5068 (N, M) for 'xy' indexing and (M, N) for 'ij' indexing. In the 3-D case 

5069 with inputs of length M, N and P, outputs are of shape (N, M, P) for 

5070 'xy' indexing and (M, N, P) for 'ij' indexing. The difference is 

5071 illustrated by the following code snippet:: 

5072 

5073 xv, yv = np.meshgrid(x, y, indexing='ij') 

5074 for i in range(nx): 

5075 for j in range(ny): 

5076 # treat xv[i,j], yv[i,j] 

5077 

5078 xv, yv = np.meshgrid(x, y, indexing='xy') 

5079 for i in range(nx): 

5080 for j in range(ny): 

5081 # treat xv[j,i], yv[j,i] 

5082 

5083 In the 1-D and 0-D case, the indexing and sparse keywords have no effect. 

5084 

5085 See Also 

5086 -------- 

5087 mgrid : Construct a multi-dimensional "meshgrid" using indexing notation. 

5088 ogrid : Construct an open multi-dimensional "meshgrid" using indexing 

5089 notation. 

5090 how-to-index 

5091 

5092 Examples 

5093 -------- 

5094 >>> nx, ny = (3, 2) 

5095 >>> x = np.linspace(0, 1, nx) 

5096 >>> y = np.linspace(0, 1, ny) 

5097 >>> xv, yv = np.meshgrid(x, y) 

5098 >>> xv 

5099 array([[0. , 0.5, 1. ], 

5100 [0. , 0.5, 1. ]]) 

5101 >>> yv 

5102 array([[0., 0., 0.], 

5103 [1., 1., 1.]]) 

5104 

5105 The result of `meshgrid` is a coordinate grid: 

5106 

5107 >>> import matplotlib.pyplot as plt 

5108 >>> plt.plot(xv, yv, marker='o', color='k', linestyle='none') 

5109 >>> plt.show() 

5110 

5111 You can create sparse output arrays to save memory and computation time. 

5112 

5113 >>> xv, yv = np.meshgrid(x, y, sparse=True) 

5114 >>> xv 

5115 array([[0. , 0.5, 1. ]]) 

5116 >>> yv 

5117 array([[0.], 

5118 [1.]]) 

5119 

5120 `meshgrid` is very useful to evaluate functions on a grid. If the 

5121 function depends on all coordinates, both dense and sparse outputs can be 

5122 used. 

5123 

5124 >>> x = np.linspace(-5, 5, 101) 

5125 >>> y = np.linspace(-5, 5, 101) 

5126 >>> # full coordinate arrays 

5127 >>> xx, yy = np.meshgrid(x, y) 

5128 >>> zz = np.sqrt(xx**2 + yy**2) 

5129 >>> xx.shape, yy.shape, zz.shape 

5130 ((101, 101), (101, 101), (101, 101)) 

5131 >>> # sparse coordinate arrays 

5132 >>> xs, ys = np.meshgrid(x, y, sparse=True) 

5133 >>> zs = np.sqrt(xs**2 + ys**2) 

5134 >>> xs.shape, ys.shape, zs.shape 

5135 ((1, 101), (101, 1), (101, 101)) 

5136 >>> np.array_equal(zz, zs) 

5137 True 

5138 

5139 >>> h = plt.contourf(x, y, zs) 

5140 >>> plt.axis('scaled') 

5141 >>> plt.colorbar() 

5142 >>> plt.show() 

5143 """ 

5144 ndim = len(xi) 

5145 

5146 if indexing not in ['xy', 'ij']: 

5147 raise ValueError( 

5148 "Valid values for `indexing` are 'xy' and 'ij'.") 

5149 

5150 s0 = (1,) * ndim 

5151 output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1:]) 

5152 for i, x in enumerate(xi)] 

5153 

5154 if indexing == 'xy' and ndim > 1: 

5155 # switch first and second axis 

5156 output[0].shape = (1, -1) + s0[2:] 

5157 output[1].shape = (-1, 1) + s0[2:] 

5158 

5159 if not sparse: 

5160 # Return the full N-D matrix (not only the 1-D vector) 

5161 output = np.broadcast_arrays(*output, subok=True) 

5162 

5163 if copy: 

5164 output = [x.copy() for x in output] 

5165 

5166 return output 

5167 

5168 

5169def _delete_dispatcher(arr, obj, axis=None): 

5170 return (arr, obj) 

5171 

5172 

5173@array_function_dispatch(_delete_dispatcher) 

5174def delete(arr, obj, axis=None): 

5175 """ 

5176 Return a new array with sub-arrays along an axis deleted. For a one 

5177 dimensional array, this returns those entries not returned by 

5178 `arr[obj]`. 

5179 

5180 Parameters 

5181 ---------- 

5182 arr : array_like 

5183 Input array. 

5184 obj : slice, int or array of ints 

5185 Indicate indices of sub-arrays to remove along the specified axis. 

5186 

5187 .. versionchanged:: 1.19.0 

5188 Boolean indices are now treated as a mask of elements to remove, 

5189 rather than being cast to the integers 0 and 1. 

5190 

5191 axis : int, optional 

5192 The axis along which to delete the subarray defined by `obj`. 

5193 If `axis` is None, `obj` is applied to the flattened array. 

5194 

5195 Returns 

5196 ------- 

5197 out : ndarray 

5198 A copy of `arr` with the elements specified by `obj` removed. Note 

5199 that `delete` does not occur in-place. If `axis` is None, `out` is 

5200 a flattened array. 

5201 

5202 See Also 

5203 -------- 

5204 insert : Insert elements into an array. 

5205 append : Append elements at the end of an array. 

5206 

5207 Notes 

5208 ----- 

5209 Often it is preferable to use a boolean mask. For example: 

5210 

5211 >>> arr = np.arange(12) + 1 

5212 >>> mask = np.ones(len(arr), dtype=bool) 

5213 >>> mask[[0,2,4]] = False 

5214 >>> result = arr[mask,...] 

5215 

5216 Is equivalent to ``np.delete(arr, [0,2,4], axis=0)``, but allows further 

5217 use of `mask`. 

5218 

5219 Examples 

5220 -------- 

5221 >>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]]) 

5222 >>> arr 

5223 array([[ 1, 2, 3, 4], 

5224 [ 5, 6, 7, 8], 

5225 [ 9, 10, 11, 12]]) 

5226 >>> np.delete(arr, 1, 0) 

5227 array([[ 1, 2, 3, 4], 

5228 [ 9, 10, 11, 12]]) 

5229 

5230 >>> np.delete(arr, np.s_[::2], 1) 

5231 array([[ 2, 4], 

5232 [ 6, 8], 

5233 [10, 12]]) 

5234 >>> np.delete(arr, [1,3,5], None) 

5235 array([ 1, 3, 5, 7, 8, 9, 10, 11, 12]) 

5236 

5237 """ 

5238 wrap = None 

5239 if type(arr) is not ndarray: 

5240 try: 

5241 wrap = arr.__array_wrap__ 

5242 except AttributeError: 

5243 pass 

5244 

5245 arr = asarray(arr) 

5246 ndim = arr.ndim 

5247 arrorder = 'F' if arr.flags.fnc else 'C' 

5248 if axis is None: 

5249 if ndim != 1: 

5250 arr = arr.ravel() 

5251 # needed for np.matrix, which is still not 1d after being ravelled 

5252 ndim = arr.ndim 

5253 axis = ndim - 1 

5254 else: 

5255 axis = normalize_axis_index(axis, ndim) 

5256 

5257 slobj = [slice(None)]*ndim 

5258 N = arr.shape[axis] 

5259 newshape = list(arr.shape) 

5260 

5261 if isinstance(obj, slice): 

5262 start, stop, step = obj.indices(N) 

5263 xr = range(start, stop, step) 

5264 numtodel = len(xr) 

5265 

5266 if numtodel <= 0: 

5267 if wrap: 

5268 return wrap(arr.copy(order=arrorder)) 

5269 else: 

5270 return arr.copy(order=arrorder) 

5271 

5272 # Invert if step is negative: 

5273 if step < 0: 

5274 step = -step 

5275 start = xr[-1] 

5276 stop = xr[0] + 1 

5277 

5278 newshape[axis] -= numtodel 

5279 new = empty(newshape, arr.dtype, arrorder) 

5280 # copy initial chunk 

5281 if start == 0: 

5282 pass 

5283 else: 

5284 slobj[axis] = slice(None, start) 

5285 new[tuple(slobj)] = arr[tuple(slobj)] 

5286 # copy end chunk 

5287 if stop == N: 

5288 pass 

5289 else: 

5290 slobj[axis] = slice(stop-numtodel, None) 

5291 slobj2 = [slice(None)]*ndim 

5292 slobj2[axis] = slice(stop, None) 

5293 new[tuple(slobj)] = arr[tuple(slobj2)] 

5294 # copy middle pieces 

5295 if step == 1: 

5296 pass 

5297 else: # use array indexing. 

5298 keep = ones(stop-start, dtype=bool) 

5299 keep[:stop-start:step] = False 

5300 slobj[axis] = slice(start, stop-numtodel) 

5301 slobj2 = [slice(None)]*ndim 

5302 slobj2[axis] = slice(start, stop) 

5303 arr = arr[tuple(slobj2)] 

5304 slobj2[axis] = keep 

5305 new[tuple(slobj)] = arr[tuple(slobj2)] 

5306 if wrap: 

5307 return wrap(new) 

5308 else: 

5309 return new 

5310 

5311 if isinstance(obj, (int, integer)) and not isinstance(obj, bool): 

5312 single_value = True 

5313 else: 

5314 single_value = False 

5315 _obj = obj 

5316 obj = np.asarray(obj) 

5317 # `size == 0` to allow empty lists similar to indexing, but (as there) 

5318 # is really too generic: 

5319 if obj.size == 0 and not isinstance(_obj, np.ndarray): 

5320 obj = obj.astype(intp) 

5321 elif obj.size == 1 and obj.dtype.kind in "ui": 

5322 # For a size 1 integer array we can use the single-value path 

5323 # (most dtypes, except boolean, should just fail later). 

5324 obj = obj.item() 

5325 single_value = True 

5326 

5327 if single_value: 

5328 # optimization for a single value 

5329 if (obj < -N or obj >= N): 

5330 raise IndexError( 

5331 "index %i is out of bounds for axis %i with " 

5332 "size %i" % (obj, axis, N)) 

5333 if (obj < 0): 

5334 obj += N 

5335 newshape[axis] -= 1 

5336 new = empty(newshape, arr.dtype, arrorder) 

5337 slobj[axis] = slice(None, obj) 

5338 new[tuple(slobj)] = arr[tuple(slobj)] 

5339 slobj[axis] = slice(obj, None) 

5340 slobj2 = [slice(None)]*ndim 

5341 slobj2[axis] = slice(obj+1, None) 

5342 new[tuple(slobj)] = arr[tuple(slobj2)] 

5343 else: 

5344 if obj.dtype == bool: 

5345 if obj.shape != (N,): 

5346 raise ValueError('boolean array argument obj to delete ' 

5347 'must be one dimensional and match the axis ' 

5348 'length of {}'.format(N)) 

5349 

5350 # optimization, the other branch is slower 

5351 keep = ~obj 

5352 else: 

5353 keep = ones(N, dtype=bool) 

5354 keep[obj,] = False 

5355 

5356 slobj[axis] = keep 

5357 new = arr[tuple(slobj)] 

5358 

5359 if wrap: 

5360 return wrap(new) 

5361 else: 

5362 return new 

5363 

5364 

5365def _insert_dispatcher(arr, obj, values, axis=None): 

5366 return (arr, obj, values) 

5367 

5368 

5369@array_function_dispatch(_insert_dispatcher) 

5370def insert(arr, obj, values, axis=None): 

5371 """ 

5372 Insert values along the given axis before the given indices. 

5373 

5374 Parameters 

5375 ---------- 

5376 arr : array_like 

5377 Input array. 

5378 obj : int, slice or sequence of ints 

5379 Object that defines the index or indices before which `values` is 

5380 inserted. 

5381 

5382 .. versionadded:: 1.8.0 

5383 

5384 Support for multiple insertions when `obj` is a single scalar or a 

5385 sequence with one element (similar to calling insert multiple 

5386 times). 

5387 values : array_like 

5388 Values to insert into `arr`. If the type of `values` is different 

5389 from that of `arr`, `values` is converted to the type of `arr`. 

5390 `values` should be shaped so that ``arr[...,obj,...] = values`` 

5391 is legal. 

5392 axis : int, optional 

5393 Axis along which to insert `values`. If `axis` is None then `arr` 

5394 is flattened first. 

5395 

5396 Returns 

5397 ------- 

5398 out : ndarray 

5399 A copy of `arr` with `values` inserted. Note that `insert` 

5400 does not occur in-place: a new array is returned. If 

5401 `axis` is None, `out` is a flattened array. 

5402 

5403 See Also 

5404 -------- 

5405 append : Append elements at the end of an array. 

5406 concatenate : Join a sequence of arrays along an existing axis. 

5407 delete : Delete elements from an array. 

5408 

5409 Notes 

5410 ----- 

5411 Note that for higher dimensional inserts ``obj=0`` behaves very different 

5412 from ``obj=[0]`` just like ``arr[:,0,:] = values`` is different from 

5413 ``arr[:,[0],:] = values``. 

5414 

5415 Examples 

5416 -------- 

5417 >>> a = np.array([[1, 1], [2, 2], [3, 3]]) 

5418 >>> a 

5419 array([[1, 1], 

5420 [2, 2], 

5421 [3, 3]]) 

5422 >>> np.insert(a, 1, 5) 

5423 array([1, 5, 1, ..., 2, 3, 3]) 

5424 >>> np.insert(a, 1, 5, axis=1) 

5425 array([[1, 5, 1], 

5426 [2, 5, 2], 

5427 [3, 5, 3]]) 

5428 

5429 Difference between sequence and scalars: 

5430 

5431 >>> np.insert(a, [1], [[1],[2],[3]], axis=1) 

5432 array([[1, 1, 1], 

5433 [2, 2, 2], 

5434 [3, 3, 3]]) 

5435 >>> np.array_equal(np.insert(a, 1, [1, 2, 3], axis=1), 

5436 ... np.insert(a, [1], [[1],[2],[3]], axis=1)) 

5437 True 

5438 

5439 >>> b = a.flatten() 

5440 >>> b 

5441 array([1, 1, 2, 2, 3, 3]) 

5442 >>> np.insert(b, [2, 2], [5, 6]) 

5443 array([1, 1, 5, ..., 2, 3, 3]) 

5444 

5445 >>> np.insert(b, slice(2, 4), [5, 6]) 

5446 array([1, 1, 5, ..., 2, 3, 3]) 

5447 

5448 >>> np.insert(b, [2, 2], [7.13, False]) # type casting 

5449 array([1, 1, 7, ..., 2, 3, 3]) 

5450 

5451 >>> x = np.arange(8).reshape(2, 4) 

5452 >>> idx = (1, 3) 

5453 >>> np.insert(x, idx, 999, axis=1) 

5454 array([[ 0, 999, 1, 2, 999, 3], 

5455 [ 4, 999, 5, 6, 999, 7]]) 

5456 

5457 """ 

5458 wrap = None 

5459 if type(arr) is not ndarray: 

5460 try: 

5461 wrap = arr.__array_wrap__ 

5462 except AttributeError: 

5463 pass 

5464 

5465 arr = asarray(arr) 

5466 ndim = arr.ndim 

5467 arrorder = 'F' if arr.flags.fnc else 'C' 

5468 if axis is None: 

5469 if ndim != 1: 

5470 arr = arr.ravel() 

5471 # needed for np.matrix, which is still not 1d after being ravelled 

5472 ndim = arr.ndim 

5473 axis = ndim - 1 

5474 else: 

5475 axis = normalize_axis_index(axis, ndim) 

5476 slobj = [slice(None)]*ndim 

5477 N = arr.shape[axis] 

5478 newshape = list(arr.shape) 

5479 

5480 if isinstance(obj, slice): 

5481 # turn it into a range object 

5482 indices = arange(*obj.indices(N), dtype=intp) 

5483 else: 

5484 # need to copy obj, because indices will be changed in-place 

5485 indices = np.array(obj) 

5486 if indices.dtype == bool: 

5487 # See also delete 

5488 # 2012-10-11, NumPy 1.8 

5489 warnings.warn( 

5490 "in the future insert will treat boolean arrays and " 

5491 "array-likes as a boolean index instead of casting it to " 

5492 "integer", FutureWarning, stacklevel=2) 

5493 indices = indices.astype(intp) 

5494 # Code after warning period: 

5495 #if obj.ndim != 1: 

5496 # raise ValueError('boolean array argument obj to insert ' 

5497 # 'must be one dimensional') 

5498 #indices = np.flatnonzero(obj) 

5499 elif indices.ndim > 1: 

5500 raise ValueError( 

5501 "index array argument obj to insert must be one dimensional " 

5502 "or scalar") 

5503 if indices.size == 1: 

5504 index = indices.item() 

5505 if index < -N or index > N: 

5506 raise IndexError(f"index {obj} is out of bounds for axis {axis} " 

5507 f"with size {N}") 

5508 if (index < 0): 

5509 index += N 

5510 

5511 # There are some object array corner cases here, but we cannot avoid 

5512 # that: 

5513 values = array(values, copy=False, ndmin=arr.ndim, dtype=arr.dtype) 

5514 if indices.ndim == 0: 

5515 # broadcasting is very different here, since a[:,0,:] = ... behaves 

5516 # very different from a[:,[0],:] = ...! This changes values so that 

5517 # it works likes the second case. (here a[:,0:1,:]) 

5518 values = np.moveaxis(values, 0, axis) 

5519 numnew = values.shape[axis] 

5520 newshape[axis] += numnew 

5521 new = empty(newshape, arr.dtype, arrorder) 

5522 slobj[axis] = slice(None, index) 

5523 new[tuple(slobj)] = arr[tuple(slobj)] 

5524 slobj[axis] = slice(index, index+numnew) 

5525 new[tuple(slobj)] = values 

5526 slobj[axis] = slice(index+numnew, None) 

5527 slobj2 = [slice(None)] * ndim 

5528 slobj2[axis] = slice(index, None) 

5529 new[tuple(slobj)] = arr[tuple(slobj2)] 

5530 if wrap: 

5531 return wrap(new) 

5532 return new 

5533 elif indices.size == 0 and not isinstance(obj, np.ndarray): 

5534 # Can safely cast the empty list to intp 

5535 indices = indices.astype(intp) 

5536 

5537 indices[indices < 0] += N 

5538 

5539 numnew = len(indices) 

5540 order = indices.argsort(kind='mergesort') # stable sort 

5541 indices[order] += np.arange(numnew) 

5542 

5543 newshape[axis] += numnew 

5544 old_mask = ones(newshape[axis], dtype=bool) 

5545 old_mask[indices] = False 

5546 

5547 new = empty(newshape, arr.dtype, arrorder) 

5548 slobj2 = [slice(None)]*ndim 

5549 slobj[axis] = indices 

5550 slobj2[axis] = old_mask 

5551 new[tuple(slobj)] = values 

5552 new[tuple(slobj2)] = arr 

5553 

5554 if wrap: 

5555 return wrap(new) 

5556 return new 

5557 

5558 

5559def _append_dispatcher(arr, values, axis=None): 

5560 return (arr, values) 

5561 

5562 

5563@array_function_dispatch(_append_dispatcher) 

5564def append(arr, values, axis=None): 

5565 """ 

5566 Append values to the end of an array. 

5567 

5568 Parameters 

5569 ---------- 

5570 arr : array_like 

5571 Values are appended to a copy of this array. 

5572 values : array_like 

5573 These values are appended to a copy of `arr`. It must be of the 

5574 correct shape (the same shape as `arr`, excluding `axis`). If 

5575 `axis` is not specified, `values` can be any shape and will be 

5576 flattened before use. 

5577 axis : int, optional 

5578 The axis along which `values` are appended. If `axis` is not 

5579 given, both `arr` and `values` are flattened before use. 

5580 

5581 Returns 

5582 ------- 

5583 append : ndarray 

5584 A copy of `arr` with `values` appended to `axis`. Note that 

5585 `append` does not occur in-place: a new array is allocated and 

5586 filled. If `axis` is None, `out` is a flattened array. 

5587 

5588 See Also 

5589 -------- 

5590 insert : Insert elements into an array. 

5591 delete : Delete elements from an array. 

5592 

5593 Examples 

5594 -------- 

5595 >>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]]) 

5596 array([1, 2, 3, ..., 7, 8, 9]) 

5597 

5598 When `axis` is specified, `values` must have the correct shape. 

5599 

5600 >>> np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0) 

5601 array([[1, 2, 3], 

5602 [4, 5, 6], 

5603 [7, 8, 9]]) 

5604 >>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0) 

5605 Traceback (most recent call last): 

5606 ... 

5607 ValueError: all the input arrays must have same number of dimensions, but 

5608 the array at index 0 has 2 dimension(s) and the array at index 1 has 1 

5609 dimension(s) 

5610 

5611 """ 

5612 arr = asanyarray(arr) 

5613 if axis is None: 

5614 if arr.ndim != 1: 

5615 arr = arr.ravel() 

5616 values = ravel(values) 

5617 axis = arr.ndim-1 

5618 return concatenate((arr, values), axis=axis) 

5619 

5620 

5621def _digitize_dispatcher(x, bins, right=None): 

5622 return (x, bins) 

5623 

5624 

5625@array_function_dispatch(_digitize_dispatcher) 

5626def digitize(x, bins, right=False): 

5627 """ 

5628 Return the indices of the bins to which each value in input array belongs. 

5629 

5630 ========= ============= ============================ 

5631 `right` order of bins returned index `i` satisfies 

5632 ========= ============= ============================ 

5633 ``False`` increasing ``bins[i-1] <= x < bins[i]`` 

5634 ``True`` increasing ``bins[i-1] < x <= bins[i]`` 

5635 ``False`` decreasing ``bins[i-1] > x >= bins[i]`` 

5636 ``True`` decreasing ``bins[i-1] >= x > bins[i]`` 

5637 ========= ============= ============================ 

5638 

5639 If values in `x` are beyond the bounds of `bins`, 0 or ``len(bins)`` is 

5640 returned as appropriate. 

5641 

5642 Parameters 

5643 ---------- 

5644 x : array_like 

5645 Input array to be binned. Prior to NumPy 1.10.0, this array had to 

5646 be 1-dimensional, but can now have any shape. 

5647 bins : array_like 

5648 Array of bins. It has to be 1-dimensional and monotonic. 

5649 right : bool, optional 

5650 Indicating whether the intervals include the right or the left bin 

5651 edge. Default behavior is (right==False) indicating that the interval 

5652 does not include the right edge. The left bin end is open in this 

5653 case, i.e., bins[i-1] <= x < bins[i] is the default behavior for 

5654 monotonically increasing bins. 

5655 

5656 Returns 

5657 ------- 

5658 indices : ndarray of ints 

5659 Output array of indices, of same shape as `x`. 

5660 

5661 Raises 

5662 ------ 

5663 ValueError 

5664 If `bins` is not monotonic. 

5665 TypeError 

5666 If the type of the input is complex. 

5667 

5668 See Also 

5669 -------- 

5670 bincount, histogram, unique, searchsorted 

5671 

5672 Notes 

5673 ----- 

5674 If values in `x` are such that they fall outside the bin range, 

5675 attempting to index `bins` with the indices that `digitize` returns 

5676 will result in an IndexError. 

5677 

5678 .. versionadded:: 1.10.0 

5679 

5680 `np.digitize` is implemented in terms of `np.searchsorted`. This means 

5681 that a binary search is used to bin the values, which scales much better 

5682 for larger number of bins than the previous linear search. It also removes 

5683 the requirement for the input array to be 1-dimensional. 

5684 

5685 For monotonically _increasing_ `bins`, the following are equivalent:: 

5686 

5687 np.digitize(x, bins, right=True) 

5688 np.searchsorted(bins, x, side='left') 

5689 

5690 Note that as the order of the arguments are reversed, the side must be too. 

5691 The `searchsorted` call is marginally faster, as it does not do any 

5692 monotonicity checks. Perhaps more importantly, it supports all dtypes. 

5693 

5694 Examples 

5695 -------- 

5696 >>> x = np.array([0.2, 6.4, 3.0, 1.6]) 

5697 >>> bins = np.array([0.0, 1.0, 2.5, 4.0, 10.0]) 

5698 >>> inds = np.digitize(x, bins) 

5699 >>> inds 

5700 array([1, 4, 3, 2]) 

5701 >>> for n in range(x.size): 

5702 ... print(bins[inds[n]-1], "<=", x[n], "<", bins[inds[n]]) 

5703 ... 

5704 0.0 <= 0.2 < 1.0 

5705 4.0 <= 6.4 < 10.0 

5706 2.5 <= 3.0 < 4.0 

5707 1.0 <= 1.6 < 2.5 

5708 

5709 >>> x = np.array([1.2, 10.0, 12.4, 15.5, 20.]) 

5710 >>> bins = np.array([0, 5, 10, 15, 20]) 

5711 >>> np.digitize(x,bins,right=True) 

5712 array([1, 2, 3, 4, 4]) 

5713 >>> np.digitize(x,bins,right=False) 

5714 array([1, 3, 3, 4, 5]) 

5715 """ 

5716 x = _nx.asarray(x) 

5717 bins = _nx.asarray(bins) 

5718 

5719 # here for compatibility, searchsorted below is happy to take this 

5720 if np.issubdtype(x.dtype, _nx.complexfloating): 

5721 raise TypeError("x may not be complex") 

5722 

5723 mono = _monotonicity(bins) 

5724 if mono == 0: 

5725 raise ValueError("bins must be monotonically increasing or decreasing") 

5726 

5727 # this is backwards because the arguments below are swapped 

5728 side = 'left' if right else 'right' 

5729 if mono == -1: 

5730 # reverse the bins, and invert the results 

5731 return len(bins) - _nx.searchsorted(bins[::-1], x, side=side) 

5732 else: 

5733 return _nx.searchsorted(bins, x, side=side)