Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/numpy/lib/index_tricks.py: 24%

257 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1import functools 

2import sys 

3import math 

4import warnings 

5 

6import numpy.core.numeric as _nx 

7from numpy.core.numeric import ( 

8 asarray, ScalarType, array, alltrue, cumprod, arange, ndim 

9) 

10from numpy.core.numerictypes import find_common_type, issubdtype 

11 

12import numpy.matrixlib as matrixlib 

13from .function_base import diff 

14from numpy.core.multiarray import ravel_multi_index, unravel_index 

15from numpy.core.overrides import set_module 

16from numpy.core import overrides, linspace 

17from numpy.lib.stride_tricks import as_strided 

18 

19 

20array_function_dispatch = functools.partial( 

21 overrides.array_function_dispatch, module='numpy') 

22 

23 

24__all__ = [ 

25 'ravel_multi_index', 'unravel_index', 'mgrid', 'ogrid', 'r_', 'c_', 

26 's_', 'index_exp', 'ix_', 'ndenumerate', 'ndindex', 'fill_diagonal', 

27 'diag_indices', 'diag_indices_from' 

28] 

29 

30 

31def _ix__dispatcher(*args): 

32 return args 

33 

34 

35@array_function_dispatch(_ix__dispatcher) 

36def ix_(*args): 

37 """ 

38 Construct an open mesh from multiple sequences. 

39 

40 This function takes N 1-D sequences and returns N outputs with N 

41 dimensions each, such that the shape is 1 in all but one dimension 

42 and the dimension with the non-unit shape value cycles through all 

43 N dimensions. 

44 

45 Using `ix_` one can quickly construct index arrays that will index 

46 the cross product. ``a[np.ix_([1,3],[2,5])]`` returns the array 

47 ``[[a[1,2] a[1,5]], [a[3,2] a[3,5]]]``. 

48 

49 Parameters 

50 ---------- 

51 args : 1-D sequences 

52 Each sequence should be of integer or boolean type. 

53 Boolean sequences will be interpreted as boolean masks for the 

54 corresponding dimension (equivalent to passing in 

55 ``np.nonzero(boolean_sequence)``). 

56 

57 Returns 

58 ------- 

59 out : tuple of ndarrays 

60 N arrays with N dimensions each, with N the number of input 

61 sequences. Together these arrays form an open mesh. 

62 

63 See Also 

64 -------- 

65 ogrid, mgrid, meshgrid 

66 

67 Examples 

68 -------- 

69 >>> a = np.arange(10).reshape(2, 5) 

70 >>> a 

71 array([[0, 1, 2, 3, 4], 

72 [5, 6, 7, 8, 9]]) 

73 >>> ixgrid = np.ix_([0, 1], [2, 4]) 

74 >>> ixgrid 

75 (array([[0], 

76 [1]]), array([[2, 4]])) 

77 >>> ixgrid[0].shape, ixgrid[1].shape 

78 ((2, 1), (1, 2)) 

79 >>> a[ixgrid] 

80 array([[2, 4], 

81 [7, 9]]) 

82 

83 >>> ixgrid = np.ix_([True, True], [2, 4]) 

84 >>> a[ixgrid] 

85 array([[2, 4], 

86 [7, 9]]) 

87 >>> ixgrid = np.ix_([True, True], [False, False, True, False, True]) 

88 >>> a[ixgrid] 

89 array([[2, 4], 

90 [7, 9]]) 

91 

92 """ 

93 out = [] 

94 nd = len(args) 

95 for k, new in enumerate(args): 

96 if not isinstance(new, _nx.ndarray): 

97 new = asarray(new) 

98 if new.size == 0: 

99 # Explicitly type empty arrays to avoid float default 

100 new = new.astype(_nx.intp) 

101 if new.ndim != 1: 

102 raise ValueError("Cross index must be 1 dimensional") 

103 if issubdtype(new.dtype, _nx.bool_): 

104 new, = new.nonzero() 

105 new = new.reshape((1,)*k + (new.size,) + (1,)*(nd-k-1)) 

106 out.append(new) 

107 return tuple(out) 

108 

109 

110class nd_grid: 

111 """ 

112 Construct a multi-dimensional "meshgrid". 

113 

114 ``grid = nd_grid()`` creates an instance which will return a mesh-grid 

115 when indexed. The dimension and number of the output arrays are equal 

116 to the number of indexing dimensions. If the step length is not a 

117 complex number, then the stop is not inclusive. 

118 

119 However, if the step length is a **complex number** (e.g. 5j), then the 

120 integer part of its magnitude is interpreted as specifying the 

121 number of points to create between the start and stop values, where 

122 the stop value **is inclusive**. 

123 

124 If instantiated with an argument of ``sparse=True``, the mesh-grid is 

125 open (or not fleshed out) so that only one-dimension of each returned 

126 argument is greater than 1. 

127 

128 Parameters 

129 ---------- 

130 sparse : bool, optional 

131 Whether the grid is sparse or not. Default is False. 

132 

133 Notes 

134 ----- 

135 Two instances of `nd_grid` are made available in the NumPy namespace, 

136 `mgrid` and `ogrid`, approximately defined as:: 

137 

138 mgrid = nd_grid(sparse=False) 

139 ogrid = nd_grid(sparse=True) 

140 

141 Users should use these pre-defined instances instead of using `nd_grid` 

142 directly. 

143 """ 

144 

145 def __init__(self, sparse=False): 

146 self.sparse = sparse 

147 

148 def __getitem__(self, key): 

149 try: 

150 size = [] 

151 typ = int 

152 for kk in key: 

153 step = kk.step 

154 start = kk.start 

155 if start is None: 

156 start = 0 

157 if step is None: 

158 step = 1 

159 if isinstance(step, (_nx.complexfloating, complex)): 

160 size.append(int(abs(step))) 

161 typ = float 

162 else: 

163 size.append( 

164 int(math.ceil((kk.stop - start) / (step * 1.0)))) 

165 if (isinstance(step, (_nx.floating, float)) or 

166 isinstance(start, (_nx.floating, float)) or 

167 isinstance(kk.stop, (_nx.floating, float))): 

168 typ = float 

169 if self.sparse: 

170 nn = [_nx.arange(_x, dtype=_t) 

171 for _x, _t in zip(size, (typ,)*len(size))] 

172 else: 

173 nn = _nx.indices(size, typ) 

174 for k, kk in enumerate(key): 

175 step = kk.step 

176 start = kk.start 

177 if start is None: 

178 start = 0 

179 if step is None: 

180 step = 1 

181 if isinstance(step, (_nx.complexfloating, complex)): 

182 step = int(abs(step)) 

183 if step != 1: 

184 step = (kk.stop - start) / float(step - 1) 

185 nn[k] = (nn[k]*step+start) 

186 if self.sparse: 

187 slobj = [_nx.newaxis]*len(size) 

188 for k in range(len(size)): 

189 slobj[k] = slice(None, None) 

190 nn[k] = nn[k][tuple(slobj)] 

191 slobj[k] = _nx.newaxis 

192 return nn 

193 except (IndexError, TypeError): 

194 step = key.step 

195 stop = key.stop 

196 start = key.start 

197 if start is None: 

198 start = 0 

199 if isinstance(step, (_nx.complexfloating, complex)): 

200 step = abs(step) 

201 length = int(step) 

202 if step != 1: 

203 step = (key.stop-start)/float(step-1) 

204 return _nx.arange(0, length, 1, float)*step + start 

205 else: 

206 return _nx.arange(start, stop, step) 

207 

208 

209class MGridClass(nd_grid): 

210 """ 

211 `nd_grid` instance which returns a dense multi-dimensional "meshgrid". 

212 

213 An instance of `numpy.lib.index_tricks.nd_grid` which returns an dense 

214 (or fleshed out) mesh-grid when indexed, so that each returned argument 

215 has the same shape. The dimensions and number of the output arrays are 

216 equal to the number of indexing dimensions. If the step length is not a 

217 complex number, then the stop is not inclusive. 

218 

219 However, if the step length is a **complex number** (e.g. 5j), then 

220 the integer part of its magnitude is interpreted as specifying the 

221 number of points to create between the start and stop values, where 

222 the stop value **is inclusive**. 

223 

224 Returns 

225 ------- 

226 mesh-grid `ndarrays` all of the same dimensions 

227 

228 See Also 

229 -------- 

230 lib.index_tricks.nd_grid : class of `ogrid` and `mgrid` objects 

231 ogrid : like mgrid but returns open (not fleshed out) mesh grids 

232 r_ : array concatenator 

233 

234 Examples 

235 -------- 

236 >>> np.mgrid[0:5, 0:5] 

237 array([[[0, 0, 0, 0, 0], 

238 [1, 1, 1, 1, 1], 

239 [2, 2, 2, 2, 2], 

240 [3, 3, 3, 3, 3], 

241 [4, 4, 4, 4, 4]], 

242 [[0, 1, 2, 3, 4], 

243 [0, 1, 2, 3, 4], 

244 [0, 1, 2, 3, 4], 

245 [0, 1, 2, 3, 4], 

246 [0, 1, 2, 3, 4]]]) 

247 >>> np.mgrid[-1:1:5j] 

248 array([-1. , -0.5, 0. , 0.5, 1. ]) 

249 

250 """ 

251 

252 def __init__(self): 

253 super().__init__(sparse=False) 

254 

255 

256mgrid = MGridClass() 

257 

258 

259class OGridClass(nd_grid): 

260 """ 

261 `nd_grid` instance which returns an open multi-dimensional "meshgrid". 

262 

263 An instance of `numpy.lib.index_tricks.nd_grid` which returns an open 

264 (i.e. not fleshed out) mesh-grid when indexed, so that only one dimension 

265 of each returned array is greater than 1. The dimension and number of the 

266 output arrays are equal to the number of indexing dimensions. If the step 

267 length is not a complex number, then the stop is not inclusive. 

268 

269 However, if the step length is a **complex number** (e.g. 5j), then 

270 the integer part of its magnitude is interpreted as specifying the 

271 number of points to create between the start and stop values, where 

272 the stop value **is inclusive**. 

273 

274 Returns 

275 ------- 

276 mesh-grid 

277 `ndarrays` with only one dimension not equal to 1 

278 

279 See Also 

280 -------- 

281 np.lib.index_tricks.nd_grid : class of `ogrid` and `mgrid` objects 

282 mgrid : like `ogrid` but returns dense (or fleshed out) mesh grids 

283 r_ : array concatenator 

284 

285 Examples 

286 -------- 

287 >>> from numpy import ogrid 

288 >>> ogrid[-1:1:5j] 

289 array([-1. , -0.5, 0. , 0.5, 1. ]) 

290 >>> ogrid[0:5,0:5] 

291 [array([[0], 

292 [1], 

293 [2], 

294 [3], 

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

296 

297 """ 

298 

299 def __init__(self): 

300 super().__init__(sparse=True) 

301 

302 

303ogrid = OGridClass() 

304 

305 

306class AxisConcatenator: 

307 """ 

308 Translates slice objects to concatenation along an axis. 

309 

310 For detailed documentation on usage, see `r_`. 

311 """ 

312 # allow ma.mr_ to override this 

313 concatenate = staticmethod(_nx.concatenate) 

314 makemat = staticmethod(matrixlib.matrix) 

315 

316 def __init__(self, axis=0, matrix=False, ndmin=1, trans1d=-1): 

317 self.axis = axis 

318 self.matrix = matrix 

319 self.trans1d = trans1d 

320 self.ndmin = ndmin 

321 

322 def __getitem__(self, key): 

323 # handle matrix builder syntax 

324 if isinstance(key, str): 

325 frame = sys._getframe().f_back 

326 mymat = matrixlib.bmat(key, frame.f_globals, frame.f_locals) 

327 return mymat 

328 

329 if not isinstance(key, tuple): 

330 key = (key,) 

331 

332 # copy attributes, since they can be overridden in the first argument 

333 trans1d = self.trans1d 

334 ndmin = self.ndmin 

335 matrix = self.matrix 

336 axis = self.axis 

337 

338 objs = [] 

339 scalars = [] 

340 arraytypes = [] 

341 scalartypes = [] 

342 

343 for k, item in enumerate(key): 

344 scalar = False 

345 if isinstance(item, slice): 

346 step = item.step 

347 start = item.start 

348 stop = item.stop 

349 if start is None: 

350 start = 0 

351 if step is None: 

352 step = 1 

353 if isinstance(step, (_nx.complexfloating, complex)): 

354 size = int(abs(step)) 

355 newobj = linspace(start, stop, num=size) 

356 else: 

357 newobj = _nx.arange(start, stop, step) 

358 if ndmin > 1: 

359 newobj = array(newobj, copy=False, ndmin=ndmin) 

360 if trans1d != -1: 

361 newobj = newobj.swapaxes(-1, trans1d) 

362 elif isinstance(item, str): 

363 if k != 0: 

364 raise ValueError("special directives must be the " 

365 "first entry.") 

366 if item in ('r', 'c'): 

367 matrix = True 

368 col = (item == 'c') 

369 continue 

370 if ',' in item: 

371 vec = item.split(',') 

372 try: 

373 axis, ndmin = [int(x) for x in vec[:2]] 

374 if len(vec) == 3: 

375 trans1d = int(vec[2]) 

376 continue 

377 except Exception as e: 

378 raise ValueError( 

379 "unknown special directive {!r}".format(item) 

380 ) from e 

381 try: 

382 axis = int(item) 

383 continue 

384 except (ValueError, TypeError) as e: 

385 raise ValueError("unknown special directive") from e 

386 elif type(item) in ScalarType: 

387 newobj = array(item, ndmin=ndmin) 

388 scalars.append(len(objs)) 

389 scalar = True 

390 scalartypes.append(newobj.dtype) 

391 else: 

392 item_ndim = ndim(item) 

393 newobj = array(item, copy=False, subok=True, ndmin=ndmin) 

394 if trans1d != -1 and item_ndim < ndmin: 

395 k2 = ndmin - item_ndim 

396 k1 = trans1d 

397 if k1 < 0: 

398 k1 += k2 + 1 

399 defaxes = list(range(ndmin)) 

400 axes = defaxes[:k1] + defaxes[k2:] + defaxes[k1:k2] 

401 newobj = newobj.transpose(axes) 

402 objs.append(newobj) 

403 if not scalar and isinstance(newobj, _nx.ndarray): 

404 arraytypes.append(newobj.dtype) 

405 

406 # Ensure that scalars won't up-cast unless warranted 

407 final_dtype = find_common_type(arraytypes, scalartypes) 

408 if final_dtype is not None: 

409 for k in scalars: 

410 objs[k] = objs[k].astype(final_dtype) 

411 

412 res = self.concatenate(tuple(objs), axis=axis) 

413 

414 if matrix: 

415 oldndim = res.ndim 

416 res = self.makemat(res) 

417 if oldndim == 1 and col: 

418 res = res.T 

419 return res 

420 

421 def __len__(self): 

422 return 0 

423 

424# separate classes are used here instead of just making r_ = concatentor(0), 

425# etc. because otherwise we couldn't get the doc string to come out right 

426# in help(r_) 

427 

428 

429class RClass(AxisConcatenator): 

430 """ 

431 Translates slice objects to concatenation along the first axis. 

432 

433 This is a simple way to build up arrays quickly. There are two use cases. 

434 

435 1. If the index expression contains comma separated arrays, then stack 

436 them along their first axis. 

437 2. If the index expression contains slice notation or scalars then create 

438 a 1-D array with a range indicated by the slice notation. 

439 

440 If slice notation is used, the syntax ``start:stop:step`` is equivalent 

441 to ``np.arange(start, stop, step)`` inside of the brackets. However, if 

442 ``step`` is an imaginary number (i.e. 100j) then its integer portion is 

443 interpreted as a number-of-points desired and the start and stop are 

444 inclusive. In other words ``start:stop:stepj`` is interpreted as 

445 ``np.linspace(start, stop, step, endpoint=1)`` inside of the brackets. 

446 After expansion of slice notation, all comma separated sequences are 

447 concatenated together. 

448 

449 Optional character strings placed as the first element of the index 

450 expression can be used to change the output. The strings 'r' or 'c' result 

451 in matrix output. If the result is 1-D and 'r' is specified a 1 x N (row) 

452 matrix is produced. If the result is 1-D and 'c' is specified, then a N x 1 

453 (column) matrix is produced. If the result is 2-D then both provide the 

454 same matrix result. 

455 

456 A string integer specifies which axis to stack multiple comma separated 

457 arrays along. A string of two comma-separated integers allows indication 

458 of the minimum number of dimensions to force each entry into as the 

459 second integer (the axis to concatenate along is still the first integer). 

460 

461 A string with three comma-separated integers allows specification of the 

462 axis to concatenate along, the minimum number of dimensions to force the 

463 entries to, and which axis should contain the start of the arrays which 

464 are less than the specified number of dimensions. In other words the third 

465 integer allows you to specify where the 1's should be placed in the shape 

466 of the arrays that have their shapes upgraded. By default, they are placed 

467 in the front of the shape tuple. The third argument allows you to specify 

468 where the start of the array should be instead. Thus, a third argument of 

469 '0' would place the 1's at the end of the array shape. Negative integers 

470 specify where in the new shape tuple the last dimension of upgraded arrays 

471 should be placed, so the default is '-1'. 

472 

473 Parameters 

474 ---------- 

475 Not a function, so takes no parameters 

476 

477 

478 Returns 

479 ------- 

480 A concatenated ndarray or matrix. 

481 

482 See Also 

483 -------- 

484 concatenate : Join a sequence of arrays along an existing axis. 

485 c_ : Translates slice objects to concatenation along the second axis. 

486 

487 Examples 

488 -------- 

489 >>> np.r_[np.array([1,2,3]), 0, 0, np.array([4,5,6])] 

490 array([1, 2, 3, ..., 4, 5, 6]) 

491 >>> np.r_[-1:1:6j, [0]*3, 5, 6] 

492 array([-1. , -0.6, -0.2, 0.2, 0.6, 1. , 0. , 0. , 0. , 5. , 6. ]) 

493 

494 String integers specify the axis to concatenate along or the minimum 

495 number of dimensions to force entries into. 

496 

497 >>> a = np.array([[0, 1, 2], [3, 4, 5]]) 

498 >>> np.r_['-1', a, a] # concatenate along last axis 

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

500 [3, 4, 5, 3, 4, 5]]) 

501 >>> np.r_['0,2', [1,2,3], [4,5,6]] # concatenate along first axis, dim>=2 

502 array([[1, 2, 3], 

503 [4, 5, 6]]) 

504 

505 >>> np.r_['0,2,0', [1,2,3], [4,5,6]] 

506 array([[1], 

507 [2], 

508 [3], 

509 [4], 

510 [5], 

511 [6]]) 

512 >>> np.r_['1,2,0', [1,2,3], [4,5,6]] 

513 array([[1, 4], 

514 [2, 5], 

515 [3, 6]]) 

516 

517 Using 'r' or 'c' as a first string argument creates a matrix. 

518 

519 >>> np.r_['r',[1,2,3], [4,5,6]] 

520 matrix([[1, 2, 3, 4, 5, 6]]) 

521 

522 """ 

523 

524 def __init__(self): 

525 AxisConcatenator.__init__(self, 0) 

526 

527 

528r_ = RClass() 

529 

530 

531class CClass(AxisConcatenator): 

532 """ 

533 Translates slice objects to concatenation along the second axis. 

534 

535 This is short-hand for ``np.r_['-1,2,0', index expression]``, which is 

536 useful because of its common occurrence. In particular, arrays will be 

537 stacked along their last axis after being upgraded to at least 2-D with 

538 1's post-pended to the shape (column vectors made out of 1-D arrays). 

539 

540 See Also 

541 -------- 

542 column_stack : Stack 1-D arrays as columns into a 2-D array. 

543 r_ : For more detailed documentation. 

544 

545 Examples 

546 -------- 

547 >>> np.c_[np.array([1,2,3]), np.array([4,5,6])] 

548 array([[1, 4], 

549 [2, 5], 

550 [3, 6]]) 

551 >>> np.c_[np.array([[1,2,3]]), 0, 0, np.array([[4,5,6]])] 

552 array([[1, 2, 3, ..., 4, 5, 6]]) 

553 

554 """ 

555 

556 def __init__(self): 

557 AxisConcatenator.__init__(self, -1, ndmin=2, trans1d=0) 

558 

559 

560c_ = CClass() 

561 

562 

563@set_module('numpy') 

564class ndenumerate: 

565 """ 

566 Multidimensional index iterator. 

567 

568 Return an iterator yielding pairs of array coordinates and values. 

569 

570 Parameters 

571 ---------- 

572 arr : ndarray 

573 Input array. 

574 

575 See Also 

576 -------- 

577 ndindex, flatiter 

578 

579 Examples 

580 -------- 

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

582 >>> for index, x in np.ndenumerate(a): 

583 ... print(index, x) 

584 (0, 0) 1 

585 (0, 1) 2 

586 (1, 0) 3 

587 (1, 1) 4 

588 

589 """ 

590 

591 def __init__(self, arr): 

592 self.iter = asarray(arr).flat 

593 

594 def __next__(self): 

595 """ 

596 Standard iterator method, returns the index tuple and array value. 

597 

598 Returns 

599 ------- 

600 coords : tuple of ints 

601 The indices of the current iteration. 

602 val : scalar 

603 The array element of the current iteration. 

604 

605 """ 

606 return self.iter.coords, next(self.iter) 

607 

608 def __iter__(self): 

609 return self 

610 

611 

612@set_module('numpy') 

613class ndindex: 

614 """ 

615 An N-dimensional iterator object to index arrays. 

616 

617 Given the shape of an array, an `ndindex` instance iterates over 

618 the N-dimensional index of the array. At each iteration a tuple 

619 of indices is returned, the last dimension is iterated over first. 

620 

621 Parameters 

622 ---------- 

623 shape : ints, or a single tuple of ints 

624 The size of each dimension of the array can be passed as  

625 individual parameters or as the elements of a tuple. 

626 

627 See Also 

628 -------- 

629 ndenumerate, flatiter 

630 

631 Examples 

632 -------- 

633 Dimensions as individual arguments 

634  

635 >>> for index in np.ndindex(3, 2, 1): 

636 ... print(index) 

637 (0, 0, 0) 

638 (0, 1, 0) 

639 (1, 0, 0) 

640 (1, 1, 0) 

641 (2, 0, 0) 

642 (2, 1, 0) 

643 

644 Same dimensions - but in a tuple ``(3, 2, 1)`` 

645  

646 >>> for index in np.ndindex((3, 2, 1)): 

647 ... print(index) 

648 (0, 0, 0) 

649 (0, 1, 0) 

650 (1, 0, 0) 

651 (1, 1, 0) 

652 (2, 0, 0) 

653 (2, 1, 0) 

654 

655 """ 

656 

657 def __init__(self, *shape): 

658 if len(shape) == 1 and isinstance(shape[0], tuple): 

659 shape = shape[0] 

660 x = as_strided(_nx.zeros(1), shape=shape, 

661 strides=_nx.zeros_like(shape)) 

662 self._it = _nx.nditer(x, flags=['multi_index', 'zerosize_ok'], 

663 order='C') 

664 

665 def __iter__(self): 

666 return self 

667 

668 def ndincr(self): 

669 """ 

670 Increment the multi-dimensional index by one. 

671 

672 This method is for backward compatibility only: do not use. 

673 

674 .. deprecated:: 1.20.0 

675 This method has been advised against since numpy 1.8.0, but only 

676 started emitting DeprecationWarning as of this version. 

677 """ 

678 # NumPy 1.20.0, 2020-09-08 

679 warnings.warn( 

680 "`ndindex.ndincr()` is deprecated, use `next(ndindex)` instead", 

681 DeprecationWarning, stacklevel=2) 

682 next(self) 

683 

684 def __next__(self): 

685 """ 

686 Standard iterator method, updates the index and returns the index 

687 tuple. 

688 

689 Returns 

690 ------- 

691 val : tuple of ints 

692 Returns a tuple containing the indices of the current 

693 iteration. 

694 

695 """ 

696 next(self._it) 

697 return self._it.multi_index 

698 

699 

700# You can do all this with slice() plus a few special objects, 

701# but there's a lot to remember. This version is simpler because 

702# it uses the standard array indexing syntax. 

703# 

704# Written by Konrad Hinsen <hinsen@cnrs-orleans.fr> 

705# last revision: 1999-7-23 

706# 

707# Cosmetic changes by T. Oliphant 2001 

708# 

709# 

710 

711class IndexExpression: 

712 """ 

713 A nicer way to build up index tuples for arrays. 

714 

715 .. note:: 

716 Use one of the two predefined instances `index_exp` or `s_` 

717 rather than directly using `IndexExpression`. 

718 

719 For any index combination, including slicing and axis insertion, 

720 ``a[indices]`` is the same as ``a[np.index_exp[indices]]`` for any 

721 array `a`. However, ``np.index_exp[indices]`` can be used anywhere 

722 in Python code and returns a tuple of slice objects that can be 

723 used in the construction of complex index expressions. 

724 

725 Parameters 

726 ---------- 

727 maketuple : bool 

728 If True, always returns a tuple. 

729 

730 See Also 

731 -------- 

732 index_exp : Predefined instance that always returns a tuple: 

733 `index_exp = IndexExpression(maketuple=True)`. 

734 s_ : Predefined instance without tuple conversion: 

735 `s_ = IndexExpression(maketuple=False)`. 

736 

737 Notes 

738 ----- 

739 You can do all this with `slice()` plus a few special objects, 

740 but there's a lot to remember and this version is simpler because 

741 it uses the standard array indexing syntax. 

742 

743 Examples 

744 -------- 

745 >>> np.s_[2::2] 

746 slice(2, None, 2) 

747 >>> np.index_exp[2::2] 

748 (slice(2, None, 2),) 

749 

750 >>> np.array([0, 1, 2, 3, 4])[np.s_[2::2]] 

751 array([2, 4]) 

752 

753 """ 

754 

755 def __init__(self, maketuple): 

756 self.maketuple = maketuple 

757 

758 def __getitem__(self, item): 

759 if self.maketuple and not isinstance(item, tuple): 

760 return (item,) 

761 else: 

762 return item 

763 

764 

765index_exp = IndexExpression(maketuple=True) 

766s_ = IndexExpression(maketuple=False) 

767 

768# End contribution from Konrad. 

769 

770 

771# The following functions complement those in twodim_base, but are 

772# applicable to N-dimensions. 

773 

774 

775def _fill_diagonal_dispatcher(a, val, wrap=None): 

776 return (a,) 

777 

778 

779@array_function_dispatch(_fill_diagonal_dispatcher) 

780def fill_diagonal(a, val, wrap=False): 

781 """Fill the main diagonal of the given array of any dimensionality. 

782 

783 For an array `a` with ``a.ndim >= 2``, the diagonal is the list of 

784 locations with indices ``a[i, ..., i]`` all identical. This function 

785 modifies the input array in-place, it does not return a value. 

786 

787 Parameters 

788 ---------- 

789 a : array, at least 2-D. 

790 Array whose diagonal is to be filled, it gets modified in-place. 

791 

792 val : scalar or array_like 

793 Value(s) to write on the diagonal. If `val` is scalar, the value is 

794 written along the diagonal. If array-like, the flattened `val` is 

795 written along the diagonal, repeating if necessary to fill all 

796 diagonal entries. 

797 

798 wrap : bool 

799 For tall matrices in NumPy version up to 1.6.2, the 

800 diagonal "wrapped" after N columns. You can have this behavior 

801 with this option. This affects only tall matrices. 

802 

803 See also 

804 -------- 

805 diag_indices, diag_indices_from 

806 

807 Notes 

808 ----- 

809 .. versionadded:: 1.4.0 

810 

811 This functionality can be obtained via `diag_indices`, but internally 

812 this version uses a much faster implementation that never constructs the 

813 indices and uses simple slicing. 

814 

815 Examples 

816 -------- 

817 >>> a = np.zeros((3, 3), int) 

818 >>> np.fill_diagonal(a, 5) 

819 >>> a 

820 array([[5, 0, 0], 

821 [0, 5, 0], 

822 [0, 0, 5]]) 

823 

824 The same function can operate on a 4-D array: 

825 

826 >>> a = np.zeros((3, 3, 3, 3), int) 

827 >>> np.fill_diagonal(a, 4) 

828 

829 We only show a few blocks for clarity: 

830 

831 >>> a[0, 0] 

832 array([[4, 0, 0], 

833 [0, 0, 0], 

834 [0, 0, 0]]) 

835 >>> a[1, 1] 

836 array([[0, 0, 0], 

837 [0, 4, 0], 

838 [0, 0, 0]]) 

839 >>> a[2, 2] 

840 array([[0, 0, 0], 

841 [0, 0, 0], 

842 [0, 0, 4]]) 

843 

844 The wrap option affects only tall matrices: 

845 

846 >>> # tall matrices no wrap 

847 >>> a = np.zeros((5, 3), int) 

848 >>> np.fill_diagonal(a, 4) 

849 >>> a 

850 array([[4, 0, 0], 

851 [0, 4, 0], 

852 [0, 0, 4], 

853 [0, 0, 0], 

854 [0, 0, 0]]) 

855 

856 >>> # tall matrices wrap 

857 >>> a = np.zeros((5, 3), int) 

858 >>> np.fill_diagonal(a, 4, wrap=True) 

859 >>> a 

860 array([[4, 0, 0], 

861 [0, 4, 0], 

862 [0, 0, 4], 

863 [0, 0, 0], 

864 [4, 0, 0]]) 

865 

866 >>> # wide matrices 

867 >>> a = np.zeros((3, 5), int) 

868 >>> np.fill_diagonal(a, 4, wrap=True) 

869 >>> a 

870 array([[4, 0, 0, 0, 0], 

871 [0, 4, 0, 0, 0], 

872 [0, 0, 4, 0, 0]]) 

873 

874 The anti-diagonal can be filled by reversing the order of elements 

875 using either `numpy.flipud` or `numpy.fliplr`. 

876 

877 >>> a = np.zeros((3, 3), int); 

878 >>> np.fill_diagonal(np.fliplr(a), [1,2,3]) # Horizontal flip 

879 >>> a 

880 array([[0, 0, 1], 

881 [0, 2, 0], 

882 [3, 0, 0]]) 

883 >>> np.fill_diagonal(np.flipud(a), [1,2,3]) # Vertical flip 

884 >>> a 

885 array([[0, 0, 3], 

886 [0, 2, 0], 

887 [1, 0, 0]]) 

888 

889 Note that the order in which the diagonal is filled varies depending 

890 on the flip function. 

891 """ 

892 if a.ndim < 2: 

893 raise ValueError("array must be at least 2-d") 

894 end = None 

895 if a.ndim == 2: 

896 # Explicit, fast formula for the common case. For 2-d arrays, we 

897 # accept rectangular ones. 

898 step = a.shape[1] + 1 

899 # This is needed to don't have tall matrix have the diagonal wrap. 

900 if not wrap: 

901 end = a.shape[1] * a.shape[1] 

902 else: 

903 # For more than d=2, the strided formula is only valid for arrays with 

904 # all dimensions equal, so we check first. 

905 if not alltrue(diff(a.shape) == 0): 

906 raise ValueError("All dimensions of input must be of equal length") 

907 step = 1 + (cumprod(a.shape[:-1])).sum() 

908 

909 # Write the value out into the diagonal. 

910 a.flat[:end:step] = val 

911 

912 

913@set_module('numpy') 

914def diag_indices(n, ndim=2): 

915 """ 

916 Return the indices to access the main diagonal of an array. 

917 

918 This returns a tuple of indices that can be used to access the main 

919 diagonal of an array `a` with ``a.ndim >= 2`` dimensions and shape 

920 (n, n, ..., n). For ``a.ndim = 2`` this is the usual diagonal, for 

921 ``a.ndim > 2`` this is the set of indices to access ``a[i, i, ..., i]`` 

922 for ``i = [0..n-1]``. 

923 

924 Parameters 

925 ---------- 

926 n : int 

927 The size, along each dimension, of the arrays for which the returned 

928 indices can be used. 

929 

930 ndim : int, optional 

931 The number of dimensions. 

932 

933 See Also 

934 -------- 

935 diag_indices_from 

936 

937 Notes 

938 ----- 

939 .. versionadded:: 1.4.0 

940 

941 Examples 

942 -------- 

943 Create a set of indices to access the diagonal of a (4, 4) array: 

944 

945 >>> di = np.diag_indices(4) 

946 >>> di 

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

948 >>> a = np.arange(16).reshape(4, 4) 

949 >>> a 

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

951 [ 4, 5, 6, 7], 

952 [ 8, 9, 10, 11], 

953 [12, 13, 14, 15]]) 

954 >>> a[di] = 100 

955 >>> a 

956 array([[100, 1, 2, 3], 

957 [ 4, 100, 6, 7], 

958 [ 8, 9, 100, 11], 

959 [ 12, 13, 14, 100]]) 

960 

961 Now, we create indices to manipulate a 3-D array: 

962 

963 >>> d3 = np.diag_indices(2, 3) 

964 >>> d3 

965 (array([0, 1]), array([0, 1]), array([0, 1])) 

966 

967 And use it to set the diagonal of an array of zeros to 1: 

968 

969 >>> a = np.zeros((2, 2, 2), dtype=int) 

970 >>> a[d3] = 1 

971 >>> a 

972 array([[[1, 0], 

973 [0, 0]], 

974 [[0, 0], 

975 [0, 1]]]) 

976 

977 """ 

978 idx = arange(n) 

979 return (idx,) * ndim 

980 

981 

982def _diag_indices_from(arr): 

983 return (arr,) 

984 

985 

986@array_function_dispatch(_diag_indices_from) 

987def diag_indices_from(arr): 

988 """ 

989 Return the indices to access the main diagonal of an n-dimensional array. 

990 

991 See `diag_indices` for full details. 

992 

993 Parameters 

994 ---------- 

995 arr : array, at least 2-D 

996 

997 See Also 

998 -------- 

999 diag_indices 

1000 

1001 Notes 

1002 ----- 

1003 .. versionadded:: 1.4.0 

1004 

1005 """ 

1006 

1007 if not arr.ndim >= 2: 

1008 raise ValueError("input array must be at least 2-d") 

1009 # For more than d=2, the strided formula is only valid for arrays with 

1010 # all dimensions equal, so we check first. 

1011 if not alltrue(diff(arr.shape) == 0): 

1012 raise ValueError("All dimensions of input must be of equal length") 

1013 

1014 return diag_indices(arr.shape[0], arr.ndim)