comparison DEPENDENCIES/mingw32/Python27/Lib/site-packages/numpy/lib/index_tricks.py @ 87:2a2c65a20a8b

Add Python libs and headers
author Chris Cannam
date Wed, 25 Feb 2015 14:05:22 +0000
parents
children
comparison
equal deleted inserted replaced
86:413a9d26189e 87:2a2c65a20a8b
1 from __future__ import division, absolute_import, print_function
2
3 import sys
4 import math
5
6 import numpy.core.numeric as _nx
7 from numpy.core.numeric import (
8 asarray, ScalarType, array, alltrue, cumprod, arange
9 )
10 from numpy.core.numerictypes import find_common_type
11
12 from . import function_base
13 import numpy.matrixlib as matrix
14 from .function_base import diff
15 from numpy.lib._compiled_base import ravel_multi_index, unravel_index
16 from numpy.lib.stride_tricks import as_strided
17
18 makemat = matrix.matrix
19
20
21 __all__ = [
22 'ravel_multi_index', 'unravel_index', 'mgrid', 'ogrid', 'r_', 'c_',
23 's_', 'index_exp', 'ix_', 'ndenumerate', 'ndindex', 'fill_diagonal',
24 'diag_indices', 'diag_indices_from'
25 ]
26
27
28 def ix_(*args):
29 """
30 Construct an open mesh from multiple sequences.
31
32 This function takes N 1-D sequences and returns N outputs with N
33 dimensions each, such that the shape is 1 in all but one dimension
34 and the dimension with the non-unit shape value cycles through all
35 N dimensions.
36
37 Using `ix_` one can quickly construct index arrays that will index
38 the cross product. ``a[np.ix_([1,3],[2,5])]`` returns the array
39 ``[[a[1,2] a[1,5]], [a[3,2] a[3,5]]]``.
40
41 Parameters
42 ----------
43 args : 1-D sequences
44
45 Returns
46 -------
47 out : tuple of ndarrays
48 N arrays with N dimensions each, with N the number of input
49 sequences. Together these arrays form an open mesh.
50
51 See Also
52 --------
53 ogrid, mgrid, meshgrid
54
55 Examples
56 --------
57 >>> a = np.arange(10).reshape(2, 5)
58 >>> a
59 array([[0, 1, 2, 3, 4],
60 [5, 6, 7, 8, 9]])
61 >>> ixgrid = np.ix_([0,1], [2,4])
62 >>> ixgrid
63 (array([[0],
64 [1]]), array([[2, 4]]))
65 >>> ixgrid[0].shape, ixgrid[1].shape
66 ((2, 1), (1, 2))
67 >>> a[ixgrid]
68 array([[2, 4],
69 [7, 9]])
70
71 """
72 out = []
73 nd = len(args)
74 baseshape = [1]*nd
75 for k in range(nd):
76 new = _nx.asarray(args[k])
77 if (new.ndim != 1):
78 raise ValueError("Cross index must be 1 dimensional")
79 if issubclass(new.dtype.type, _nx.bool_):
80 new = new.nonzero()[0]
81 baseshape[k] = len(new)
82 new = new.reshape(tuple(baseshape))
83 out.append(new)
84 baseshape[k] = 1
85 return tuple(out)
86
87 class nd_grid(object):
88 """
89 Construct a multi-dimensional "meshgrid".
90
91 ``grid = nd_grid()`` creates an instance which will return a mesh-grid
92 when indexed. The dimension and number of the output arrays are equal
93 to the number of indexing dimensions. If the step length is not a
94 complex number, then the stop is not inclusive.
95
96 However, if the step length is a **complex number** (e.g. 5j), then the
97 integer part of its magnitude is interpreted as specifying the
98 number of points to create between the start and stop values, where
99 the stop value **is inclusive**.
100
101 If instantiated with an argument of ``sparse=True``, the mesh-grid is
102 open (or not fleshed out) so that only one-dimension of each returned
103 argument is greater than 1.
104
105 Parameters
106 ----------
107 sparse : bool, optional
108 Whether the grid is sparse or not. Default is False.
109
110 Notes
111 -----
112 Two instances of `nd_grid` are made available in the NumPy namespace,
113 `mgrid` and `ogrid`::
114
115 mgrid = nd_grid(sparse=False)
116 ogrid = nd_grid(sparse=True)
117
118 Users should use these pre-defined instances instead of using `nd_grid`
119 directly.
120
121 Examples
122 --------
123 >>> mgrid = np.lib.index_tricks.nd_grid()
124 >>> mgrid[0:5,0:5]
125 array([[[0, 0, 0, 0, 0],
126 [1, 1, 1, 1, 1],
127 [2, 2, 2, 2, 2],
128 [3, 3, 3, 3, 3],
129 [4, 4, 4, 4, 4]],
130 [[0, 1, 2, 3, 4],
131 [0, 1, 2, 3, 4],
132 [0, 1, 2, 3, 4],
133 [0, 1, 2, 3, 4],
134 [0, 1, 2, 3, 4]]])
135 >>> mgrid[-1:1:5j]
136 array([-1. , -0.5, 0. , 0.5, 1. ])
137
138 >>> ogrid = np.lib.index_tricks.nd_grid(sparse=True)
139 >>> ogrid[0:5,0:5]
140 [array([[0],
141 [1],
142 [2],
143 [3],
144 [4]]), array([[0, 1, 2, 3, 4]])]
145
146 """
147
148 def __init__(self, sparse=False):
149 self.sparse = sparse
150
151 def __getitem__(self, key):
152 try:
153 size = []
154 typ = int
155 for k in range(len(key)):
156 step = key[k].step
157 start = key[k].start
158 if start is None:
159 start = 0
160 if step is None:
161 step = 1
162 if isinstance(step, complex):
163 size.append(int(abs(step)))
164 typ = float
165 else:
166 size.append(
167 int(math.ceil((key[k].stop - start)/(step*1.0))))
168 if (isinstance(step, float) or
169 isinstance(start, float) or
170 isinstance(key[k].stop, float)):
171 typ = float
172 if self.sparse:
173 nn = [_nx.arange(_x, dtype=_t)
174 for _x, _t in zip(size, (typ,)*len(size))]
175 else:
176 nn = _nx.indices(size, typ)
177 for k in range(len(size)):
178 step = key[k].step
179 start = key[k].start
180 if start is None:
181 start = 0
182 if step is None:
183 step = 1
184 if isinstance(step, complex):
185 step = int(abs(step))
186 if step != 1:
187 step = (key[k].stop - start)/float(step-1)
188 nn[k] = (nn[k]*step+start)
189 if self.sparse:
190 slobj = [_nx.newaxis]*len(size)
191 for k in range(len(size)):
192 slobj[k] = slice(None, None)
193 nn[k] = nn[k][slobj]
194 slobj[k] = _nx.newaxis
195 return nn
196 except (IndexError, TypeError):
197 step = key.step
198 stop = key.stop
199 start = key.start
200 if start is None:
201 start = 0
202 if isinstance(step, complex):
203 step = abs(step)
204 length = int(step)
205 if step != 1:
206 step = (key.stop-start)/float(step-1)
207 stop = key.stop + step
208 return _nx.arange(0, length, 1, float)*step + start
209 else:
210 return _nx.arange(start, stop, step)
211
212 def __getslice__(self, i, j):
213 return _nx.arange(i, j)
214
215 def __len__(self):
216 return 0
217
218 mgrid = nd_grid(sparse=False)
219 ogrid = nd_grid(sparse=True)
220 mgrid.__doc__ = None # set in numpy.add_newdocs
221 ogrid.__doc__ = None # set in numpy.add_newdocs
222
223 class AxisConcatenator(object):
224 """
225 Translates slice objects to concatenation along an axis.
226
227 For detailed documentation on usage, see `r_`.
228
229 """
230
231 def _retval(self, res):
232 if self.matrix:
233 oldndim = res.ndim
234 res = makemat(res)
235 if oldndim == 1 and self.col:
236 res = res.T
237 self.axis = self._axis
238 self.matrix = self._matrix
239 self.col = 0
240 return res
241
242 def __init__(self, axis=0, matrix=False, ndmin=1, trans1d=-1):
243 self._axis = axis
244 self._matrix = matrix
245 self.axis = axis
246 self.matrix = matrix
247 self.col = 0
248 self.trans1d = trans1d
249 self.ndmin = ndmin
250
251 def __getitem__(self, key):
252 trans1d = self.trans1d
253 ndmin = self.ndmin
254 if isinstance(key, str):
255 frame = sys._getframe().f_back
256 mymat = matrix.bmat(key, frame.f_globals, frame.f_locals)
257 return mymat
258 if not isinstance(key, tuple):
259 key = (key,)
260 objs = []
261 scalars = []
262 arraytypes = []
263 scalartypes = []
264 for k in range(len(key)):
265 scalar = False
266 if isinstance(key[k], slice):
267 step = key[k].step
268 start = key[k].start
269 stop = key[k].stop
270 if start is None:
271 start = 0
272 if step is None:
273 step = 1
274 if isinstance(step, complex):
275 size = int(abs(step))
276 newobj = function_base.linspace(start, stop, num=size)
277 else:
278 newobj = _nx.arange(start, stop, step)
279 if ndmin > 1:
280 newobj = array(newobj, copy=False, ndmin=ndmin)
281 if trans1d != -1:
282 newobj = newobj.swapaxes(-1, trans1d)
283 elif isinstance(key[k], str):
284 if k != 0:
285 raise ValueError("special directives must be the "
286 "first entry.")
287 key0 = key[0]
288 if key0 in 'rc':
289 self.matrix = True
290 self.col = (key0 == 'c')
291 continue
292 if ',' in key0:
293 vec = key0.split(',')
294 try:
295 self.axis, ndmin = \
296 [int(x) for x in vec[:2]]
297 if len(vec) == 3:
298 trans1d = int(vec[2])
299 continue
300 except:
301 raise ValueError("unknown special directive")
302 try:
303 self.axis = int(key[k])
304 continue
305 except (ValueError, TypeError):
306 raise ValueError("unknown special directive")
307 elif type(key[k]) in ScalarType:
308 newobj = array(key[k], ndmin=ndmin)
309 scalars.append(k)
310 scalar = True
311 scalartypes.append(newobj.dtype)
312 else:
313 newobj = key[k]
314 if ndmin > 1:
315 tempobj = array(newobj, copy=False, subok=True)
316 newobj = array(newobj, copy=False, subok=True,
317 ndmin=ndmin)
318 if trans1d != -1 and tempobj.ndim < ndmin:
319 k2 = ndmin-tempobj.ndim
320 if (trans1d < 0):
321 trans1d += k2 + 1
322 defaxes = list(range(ndmin))
323 k1 = trans1d
324 axes = defaxes[:k1] + defaxes[k2:] + \
325 defaxes[k1:k2]
326 newobj = newobj.transpose(axes)
327 del tempobj
328 objs.append(newobj)
329 if not scalar and isinstance(newobj, _nx.ndarray):
330 arraytypes.append(newobj.dtype)
331
332 # Esure that scalars won't up-cast unless warranted
333 final_dtype = find_common_type(arraytypes, scalartypes)
334 if final_dtype is not None:
335 for k in scalars:
336 objs[k] = objs[k].astype(final_dtype)
337
338 res = _nx.concatenate(tuple(objs), axis=self.axis)
339 return self._retval(res)
340
341 def __getslice__(self, i, j):
342 res = _nx.arange(i, j)
343 return self._retval(res)
344
345 def __len__(self):
346 return 0
347
348 # separate classes are used here instead of just making r_ = concatentor(0),
349 # etc. because otherwise we couldn't get the doc string to come out right
350 # in help(r_)
351
352 class RClass(AxisConcatenator):
353 """
354 Translates slice objects to concatenation along the first axis.
355
356 This is a simple way to build up arrays quickly. There are two use cases.
357
358 1. If the index expression contains comma separated arrays, then stack
359 them along their first axis.
360 2. If the index expression contains slice notation or scalars then create
361 a 1-D array with a range indicated by the slice notation.
362
363 If slice notation is used, the syntax ``start:stop:step`` is equivalent
364 to ``np.arange(start, stop, step)`` inside of the brackets. However, if
365 ``step`` is an imaginary number (i.e. 100j) then its integer portion is
366 interpreted as a number-of-points desired and the start and stop are
367 inclusive. In other words ``start:stop:stepj`` is interpreted as
368 ``np.linspace(start, stop, step, endpoint=1)`` inside of the brackets.
369 After expansion of slice notation, all comma separated sequences are
370 concatenated together.
371
372 Optional character strings placed as the first element of the index
373 expression can be used to change the output. The strings 'r' or 'c' result
374 in matrix output. If the result is 1-D and 'r' is specified a 1 x N (row)
375 matrix is produced. If the result is 1-D and 'c' is specified, then a N x 1
376 (column) matrix is produced. If the result is 2-D then both provide the
377 same matrix result.
378
379 A string integer specifies which axis to stack multiple comma separated
380 arrays along. A string of two comma-separated integers allows indication
381 of the minimum number of dimensions to force each entry into as the
382 second integer (the axis to concatenate along is still the first integer).
383
384 A string with three comma-separated integers allows specification of the
385 axis to concatenate along, the minimum number of dimensions to force the
386 entries to, and which axis should contain the start of the arrays which
387 are less than the specified number of dimensions. In other words the third
388 integer allows you to specify where the 1's should be placed in the shape
389 of the arrays that have their shapes upgraded. By default, they are placed
390 in the front of the shape tuple. The third argument allows you to specify
391 where the start of the array should be instead. Thus, a third argument of
392 '0' would place the 1's at the end of the array shape. Negative integers
393 specify where in the new shape tuple the last dimension of upgraded arrays
394 should be placed, so the default is '-1'.
395
396 Parameters
397 ----------
398 Not a function, so takes no parameters
399
400
401 Returns
402 -------
403 A concatenated ndarray or matrix.
404
405 See Also
406 --------
407 concatenate : Join a sequence of arrays together.
408 c_ : Translates slice objects to concatenation along the second axis.
409
410 Examples
411 --------
412 >>> np.r_[np.array([1,2,3]), 0, 0, np.array([4,5,6])]
413 array([1, 2, 3, 0, 0, 4, 5, 6])
414 >>> np.r_[-1:1:6j, [0]*3, 5, 6]
415 array([-1. , -0.6, -0.2, 0.2, 0.6, 1. , 0. , 0. , 0. , 5. , 6. ])
416
417 String integers specify the axis to concatenate along or the minimum
418 number of dimensions to force entries into.
419
420 >>> a = np.array([[0, 1, 2], [3, 4, 5]])
421 >>> np.r_['-1', a, a] # concatenate along last axis
422 array([[0, 1, 2, 0, 1, 2],
423 [3, 4, 5, 3, 4, 5]])
424 >>> np.r_['0,2', [1,2,3], [4,5,6]] # concatenate along first axis, dim>=2
425 array([[1, 2, 3],
426 [4, 5, 6]])
427
428 >>> np.r_['0,2,0', [1,2,3], [4,5,6]]
429 array([[1],
430 [2],
431 [3],
432 [4],
433 [5],
434 [6]])
435 >>> np.r_['1,2,0', [1,2,3], [4,5,6]]
436 array([[1, 4],
437 [2, 5],
438 [3, 6]])
439
440 Using 'r' or 'c' as a first string argument creates a matrix.
441
442 >>> np.r_['r',[1,2,3], [4,5,6]]
443 matrix([[1, 2, 3, 4, 5, 6]])
444
445 """
446
447 def __init__(self):
448 AxisConcatenator.__init__(self, 0)
449
450 r_ = RClass()
451
452 class CClass(AxisConcatenator):
453 """
454 Translates slice objects to concatenation along the second axis.
455
456 This is short-hand for ``np.r_['-1,2,0', index expression]``, which is
457 useful because of its common occurrence. In particular, arrays will be
458 stacked along their last axis after being upgraded to at least 2-D with
459 1's post-pended to the shape (column vectors made out of 1-D arrays).
460
461 For detailed documentation, see `r_`.
462
463 Examples
464 --------
465 >>> np.c_[np.array([[1,2,3]]), 0, 0, np.array([[4,5,6]])]
466 array([[1, 2, 3, 0, 0, 4, 5, 6]])
467
468 """
469
470 def __init__(self):
471 AxisConcatenator.__init__(self, -1, ndmin=2, trans1d=0)
472
473 c_ = CClass()
474
475 class ndenumerate(object):
476 """
477 Multidimensional index iterator.
478
479 Return an iterator yielding pairs of array coordinates and values.
480
481 Parameters
482 ----------
483 a : ndarray
484 Input array.
485
486 See Also
487 --------
488 ndindex, flatiter
489
490 Examples
491 --------
492 >>> a = np.array([[1, 2], [3, 4]])
493 >>> for index, x in np.ndenumerate(a):
494 ... print index, x
495 (0, 0) 1
496 (0, 1) 2
497 (1, 0) 3
498 (1, 1) 4
499
500 """
501
502 def __init__(self, arr):
503 self.iter = asarray(arr).flat
504
505 def __next__(self):
506 """
507 Standard iterator method, returns the index tuple and array value.
508
509 Returns
510 -------
511 coords : tuple of ints
512 The indices of the current iteration.
513 val : scalar
514 The array element of the current iteration.
515
516 """
517 return self.iter.coords, next(self.iter)
518
519 def __iter__(self):
520 return self
521
522 next = __next__
523
524
525 class ndindex(object):
526 """
527 An N-dimensional iterator object to index arrays.
528
529 Given the shape of an array, an `ndindex` instance iterates over
530 the N-dimensional index of the array. At each iteration a tuple
531 of indices is returned, the last dimension is iterated over first.
532
533 Parameters
534 ----------
535 `*args` : ints
536 The size of each dimension of the array.
537
538 See Also
539 --------
540 ndenumerate, flatiter
541
542 Examples
543 --------
544 >>> for index in np.ndindex(3, 2, 1):
545 ... print index
546 (0, 0, 0)
547 (0, 1, 0)
548 (1, 0, 0)
549 (1, 1, 0)
550 (2, 0, 0)
551 (2, 1, 0)
552
553 """
554
555 def __init__(self, *shape):
556 if len(shape) == 1 and isinstance(shape[0], tuple):
557 shape = shape[0]
558 x = as_strided(_nx.zeros(1), shape=shape,
559 strides=_nx.zeros_like(shape))
560 self._it = _nx.nditer(x, flags=['multi_index', 'zerosize_ok'],
561 order='C')
562
563 def __iter__(self):
564 return self
565
566 def ndincr(self):
567 """
568 Increment the multi-dimensional index by one.
569
570 This method is for backward compatibility only: do not use.
571 """
572 next(self)
573
574 def __next__(self):
575 """
576 Standard iterator method, updates the index and returns the index
577 tuple.
578
579 Returns
580 -------
581 val : tuple of ints
582 Returns a tuple containing the indices of the current
583 iteration.
584
585 """
586 next(self._it)
587 return self._it.multi_index
588
589 next = __next__
590
591
592 # You can do all this with slice() plus a few special objects,
593 # but there's a lot to remember. This version is simpler because
594 # it uses the standard array indexing syntax.
595 #
596 # Written by Konrad Hinsen <hinsen@cnrs-orleans.fr>
597 # last revision: 1999-7-23
598 #
599 # Cosmetic changes by T. Oliphant 2001
600 #
601 #
602
603 class IndexExpression(object):
604 """
605 A nicer way to build up index tuples for arrays.
606
607 .. note::
608 Use one of the two predefined instances `index_exp` or `s_`
609 rather than directly using `IndexExpression`.
610
611 For any index combination, including slicing and axis insertion,
612 ``a[indices]`` is the same as ``a[np.index_exp[indices]]`` for any
613 array `a`. However, ``np.index_exp[indices]`` can be used anywhere
614 in Python code and returns a tuple of slice objects that can be
615 used in the construction of complex index expressions.
616
617 Parameters
618 ----------
619 maketuple : bool
620 If True, always returns a tuple.
621
622 See Also
623 --------
624 index_exp : Predefined instance that always returns a tuple:
625 `index_exp = IndexExpression(maketuple=True)`.
626 s_ : Predefined instance without tuple conversion:
627 `s_ = IndexExpression(maketuple=False)`.
628
629 Notes
630 -----
631 You can do all this with `slice()` plus a few special objects,
632 but there's a lot to remember and this version is simpler because
633 it uses the standard array indexing syntax.
634
635 Examples
636 --------
637 >>> np.s_[2::2]
638 slice(2, None, 2)
639 >>> np.index_exp[2::2]
640 (slice(2, None, 2),)
641
642 >>> np.array([0, 1, 2, 3, 4])[np.s_[2::2]]
643 array([2, 4])
644
645 """
646
647 def __init__(self, maketuple):
648 self.maketuple = maketuple
649
650 def __getitem__(self, item):
651 if self.maketuple and not isinstance(item, tuple):
652 return (item,)
653 else:
654 return item
655
656 index_exp = IndexExpression(maketuple=True)
657 s_ = IndexExpression(maketuple=False)
658
659 # End contribution from Konrad.
660
661
662 # The following functions complement those in twodim_base, but are
663 # applicable to N-dimensions.
664
665 def fill_diagonal(a, val, wrap=False):
666 """Fill the main diagonal of the given array of any dimensionality.
667
668 For an array `a` with ``a.ndim > 2``, the diagonal is the list of
669 locations with indices ``a[i, i, ..., i]`` all identical. This function
670 modifies the input array in-place, it does not return a value.
671
672 Parameters
673 ----------
674 a : array, at least 2-D.
675 Array whose diagonal is to be filled, it gets modified in-place.
676
677 val : scalar
678 Value to be written on the diagonal, its type must be compatible with
679 that of the array a.
680
681 wrap : bool
682 For tall matrices in NumPy version up to 1.6.2, the
683 diagonal "wrapped" after N columns. You can have this behavior
684 with this option. This affect only tall matrices.
685
686 See also
687 --------
688 diag_indices, diag_indices_from
689
690 Notes
691 -----
692 .. versionadded:: 1.4.0
693
694 This functionality can be obtained via `diag_indices`, but internally
695 this version uses a much faster implementation that never constructs the
696 indices and uses simple slicing.
697
698 Examples
699 --------
700 >>> a = np.zeros((3, 3), int)
701 >>> np.fill_diagonal(a, 5)
702 >>> a
703 array([[5, 0, 0],
704 [0, 5, 0],
705 [0, 0, 5]])
706
707 The same function can operate on a 4-D array:
708
709 >>> a = np.zeros((3, 3, 3, 3), int)
710 >>> np.fill_diagonal(a, 4)
711
712 We only show a few blocks for clarity:
713
714 >>> a[0, 0]
715 array([[4, 0, 0],
716 [0, 0, 0],
717 [0, 0, 0]])
718 >>> a[1, 1]
719 array([[0, 0, 0],
720 [0, 4, 0],
721 [0, 0, 0]])
722 >>> a[2, 2]
723 array([[0, 0, 0],
724 [0, 0, 0],
725 [0, 0, 4]])
726
727 # tall matrices no wrap
728 >>> a = np.zeros((5, 3),int)
729 >>> fill_diagonal(a, 4)
730 array([[4, 0, 0],
731 [0, 4, 0],
732 [0, 0, 4],
733 [0, 0, 0],
734 [0, 0, 0]])
735
736 # tall matrices wrap
737 >>> a = np.zeros((5, 3),int)
738 >>> fill_diagonal(a, 4)
739 array([[4, 0, 0],
740 [0, 4, 0],
741 [0, 0, 4],
742 [0, 0, 0],
743 [4, 0, 0]])
744
745 # wide matrices
746 >>> a = np.zeros((3, 5),int)
747 >>> fill_diagonal(a, 4)
748 array([[4, 0, 0, 0, 0],
749 [0, 4, 0, 0, 0],
750 [0, 0, 4, 0, 0]])
751
752 """
753 if a.ndim < 2:
754 raise ValueError("array must be at least 2-d")
755 end = None
756 if a.ndim == 2:
757 # Explicit, fast formula for the common case. For 2-d arrays, we
758 # accept rectangular ones.
759 step = a.shape[1] + 1
760 #This is needed to don't have tall matrix have the diagonal wrap.
761 if not wrap:
762 end = a.shape[1] * a.shape[1]
763 else:
764 # For more than d=2, the strided formula is only valid for arrays with
765 # all dimensions equal, so we check first.
766 if not alltrue(diff(a.shape) == 0):
767 raise ValueError("All dimensions of input must be of equal length")
768 step = 1 + (cumprod(a.shape[:-1])).sum()
769
770 # Write the value out into the diagonal.
771 a.flat[:end:step] = val
772
773
774 def diag_indices(n, ndim=2):
775 """
776 Return the indices to access the main diagonal of an array.
777
778 This returns a tuple of indices that can be used to access the main
779 diagonal of an array `a` with ``a.ndim >= 2`` dimensions and shape
780 (n, n, ..., n). For ``a.ndim = 2`` this is the usual diagonal, for
781 ``a.ndim > 2`` this is the set of indices to access ``a[i, i, ..., i]``
782 for ``i = [0..n-1]``.
783
784 Parameters
785 ----------
786 n : int
787 The size, along each dimension, of the arrays for which the returned
788 indices can be used.
789
790 ndim : int, optional
791 The number of dimensions.
792
793 See also
794 --------
795 diag_indices_from
796
797 Notes
798 -----
799 .. versionadded:: 1.4.0
800
801 Examples
802 --------
803 Create a set of indices to access the diagonal of a (4, 4) array:
804
805 >>> di = np.diag_indices(4)
806 >>> di
807 (array([0, 1, 2, 3]), array([0, 1, 2, 3]))
808 >>> a = np.arange(16).reshape(4, 4)
809 >>> a
810 array([[ 0, 1, 2, 3],
811 [ 4, 5, 6, 7],
812 [ 8, 9, 10, 11],
813 [12, 13, 14, 15]])
814 >>> a[di] = 100
815 >>> a
816 array([[100, 1, 2, 3],
817 [ 4, 100, 6, 7],
818 [ 8, 9, 100, 11],
819 [ 12, 13, 14, 100]])
820
821 Now, we create indices to manipulate a 3-D array:
822
823 >>> d3 = np.diag_indices(2, 3)
824 >>> d3
825 (array([0, 1]), array([0, 1]), array([0, 1]))
826
827 And use it to set the diagonal of an array of zeros to 1:
828
829 >>> a = np.zeros((2, 2, 2), dtype=np.int)
830 >>> a[d3] = 1
831 >>> a
832 array([[[1, 0],
833 [0, 0]],
834 [[0, 0],
835 [0, 1]]])
836
837 """
838 idx = arange(n)
839 return (idx,) * ndim
840
841
842 def diag_indices_from(arr):
843 """
844 Return the indices to access the main diagonal of an n-dimensional array.
845
846 See `diag_indices` for full details.
847
848 Parameters
849 ----------
850 arr : array, at least 2-D
851
852 See Also
853 --------
854 diag_indices
855
856 Notes
857 -----
858 .. versionadded:: 1.4.0
859
860 """
861
862 if not arr.ndim >= 2:
863 raise ValueError("input array must be at least 2-d")
864 # For more than d=2, the strided formula is only valid for arrays with
865 # all dimensions equal, so we check first.
866 if not alltrue(diff(arr.shape) == 0):
867 raise ValueError("All dimensions of input must be of equal length")
868
869 return diag_indices(arr.shape[0], arr.ndim)