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
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1import functools
2import sys
3import math
4import warnings
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
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
20array_function_dispatch = functools.partial(
21 overrides.array_function_dispatch, module='numpy')
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]
31def _ix__dispatcher(*args):
32 return args
35@array_function_dispatch(_ix__dispatcher)
36def ix_(*args):
37 """
38 Construct an open mesh from multiple sequences.
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.
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]]]``.
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)``).
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.
63 See Also
64 --------
65 ogrid, mgrid, meshgrid
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]])
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]])
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)
110class nd_grid:
111 """
112 Construct a multi-dimensional "meshgrid".
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.
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**.
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.
128 Parameters
129 ----------
130 sparse : bool, optional
131 Whether the grid is sparse or not. Default is False.
133 Notes
134 -----
135 Two instances of `nd_grid` are made available in the NumPy namespace,
136 `mgrid` and `ogrid`, approximately defined as::
138 mgrid = nd_grid(sparse=False)
139 ogrid = nd_grid(sparse=True)
141 Users should use these pre-defined instances instead of using `nd_grid`
142 directly.
143 """
145 def __init__(self, sparse=False):
146 self.sparse = sparse
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)
209class MGridClass(nd_grid):
210 """
211 `nd_grid` instance which returns a dense multi-dimensional "meshgrid".
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.
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**.
224 Returns
225 -------
226 mesh-grid `ndarrays` all of the same dimensions
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
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. ])
250 """
252 def __init__(self):
253 super().__init__(sparse=False)
256mgrid = MGridClass()
259class OGridClass(nd_grid):
260 """
261 `nd_grid` instance which returns an open multi-dimensional "meshgrid".
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.
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**.
274 Returns
275 -------
276 mesh-grid
277 `ndarrays` with only one dimension not equal to 1
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
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]])]
297 """
299 def __init__(self):
300 super().__init__(sparse=True)
303ogrid = OGridClass()
306class AxisConcatenator:
307 """
308 Translates slice objects to concatenation along an axis.
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)
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
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
329 if not isinstance(key, tuple):
330 key = (key,)
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
338 objs = []
339 scalars = []
340 arraytypes = []
341 scalartypes = []
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)
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)
412 res = self.concatenate(tuple(objs), axis=axis)
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
421 def __len__(self):
422 return 0
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_)
429class RClass(AxisConcatenator):
430 """
431 Translates slice objects to concatenation along the first axis.
433 This is a simple way to build up arrays quickly. There are two use cases.
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.
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.
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.
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).
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'.
473 Parameters
474 ----------
475 Not a function, so takes no parameters
478 Returns
479 -------
480 A concatenated ndarray or matrix.
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.
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. ])
494 String integers specify the axis to concatenate along or the minimum
495 number of dimensions to force entries into.
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]])
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]])
517 Using 'r' or 'c' as a first string argument creates a matrix.
519 >>> np.r_['r',[1,2,3], [4,5,6]]
520 matrix([[1, 2, 3, 4, 5, 6]])
522 """
524 def __init__(self):
525 AxisConcatenator.__init__(self, 0)
528r_ = RClass()
531class CClass(AxisConcatenator):
532 """
533 Translates slice objects to concatenation along the second axis.
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).
540 See Also
541 --------
542 column_stack : Stack 1-D arrays as columns into a 2-D array.
543 r_ : For more detailed documentation.
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]])
554 """
556 def __init__(self):
557 AxisConcatenator.__init__(self, -1, ndmin=2, trans1d=0)
560c_ = CClass()
563@set_module('numpy')
564class ndenumerate:
565 """
566 Multidimensional index iterator.
568 Return an iterator yielding pairs of array coordinates and values.
570 Parameters
571 ----------
572 arr : ndarray
573 Input array.
575 See Also
576 --------
577 ndindex, flatiter
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
589 """
591 def __init__(self, arr):
592 self.iter = asarray(arr).flat
594 def __next__(self):
595 """
596 Standard iterator method, returns the index tuple and array value.
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.
605 """
606 return self.iter.coords, next(self.iter)
608 def __iter__(self):
609 return self
612@set_module('numpy')
613class ndindex:
614 """
615 An N-dimensional iterator object to index arrays.
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.
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.
627 See Also
628 --------
629 ndenumerate, flatiter
631 Examples
632 --------
633 Dimensions as individual arguments
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)
644 Same dimensions - but in a tuple ``(3, 2, 1)``
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)
655 """
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')
665 def __iter__(self):
666 return self
668 def ndincr(self):
669 """
670 Increment the multi-dimensional index by one.
672 This method is for backward compatibility only: do not use.
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)
684 def __next__(self):
685 """
686 Standard iterator method, updates the index and returns the index
687 tuple.
689 Returns
690 -------
691 val : tuple of ints
692 Returns a tuple containing the indices of the current
693 iteration.
695 """
696 next(self._it)
697 return self._it.multi_index
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#
711class IndexExpression:
712 """
713 A nicer way to build up index tuples for arrays.
715 .. note::
716 Use one of the two predefined instances `index_exp` or `s_`
717 rather than directly using `IndexExpression`.
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.
725 Parameters
726 ----------
727 maketuple : bool
728 If True, always returns a tuple.
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)`.
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.
743 Examples
744 --------
745 >>> np.s_[2::2]
746 slice(2, None, 2)
747 >>> np.index_exp[2::2]
748 (slice(2, None, 2),)
750 >>> np.array([0, 1, 2, 3, 4])[np.s_[2::2]]
751 array([2, 4])
753 """
755 def __init__(self, maketuple):
756 self.maketuple = maketuple
758 def __getitem__(self, item):
759 if self.maketuple and not isinstance(item, tuple):
760 return (item,)
761 else:
762 return item
765index_exp = IndexExpression(maketuple=True)
766s_ = IndexExpression(maketuple=False)
768# End contribution from Konrad.
771# The following functions complement those in twodim_base, but are
772# applicable to N-dimensions.
775def _fill_diagonal_dispatcher(a, val, wrap=None):
776 return (a,)
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.
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.
787 Parameters
788 ----------
789 a : array, at least 2-D.
790 Array whose diagonal is to be filled, it gets modified in-place.
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.
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.
803 See also
804 --------
805 diag_indices, diag_indices_from
807 Notes
808 -----
809 .. versionadded:: 1.4.0
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.
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]])
824 The same function can operate on a 4-D array:
826 >>> a = np.zeros((3, 3, 3, 3), int)
827 >>> np.fill_diagonal(a, 4)
829 We only show a few blocks for clarity:
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]])
844 The wrap option affects only tall matrices:
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]])
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]])
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]])
874 The anti-diagonal can be filled by reversing the order of elements
875 using either `numpy.flipud` or `numpy.fliplr`.
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]])
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()
909 # Write the value out into the diagonal.
910 a.flat[:end:step] = val
913@set_module('numpy')
914def diag_indices(n, ndim=2):
915 """
916 Return the indices to access the main diagonal of an array.
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]``.
924 Parameters
925 ----------
926 n : int
927 The size, along each dimension, of the arrays for which the returned
928 indices can be used.
930 ndim : int, optional
931 The number of dimensions.
933 See Also
934 --------
935 diag_indices_from
937 Notes
938 -----
939 .. versionadded:: 1.4.0
941 Examples
942 --------
943 Create a set of indices to access the diagonal of a (4, 4) array:
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]])
961 Now, we create indices to manipulate a 3-D array:
963 >>> d3 = np.diag_indices(2, 3)
964 >>> d3
965 (array([0, 1]), array([0, 1]), array([0, 1]))
967 And use it to set the diagonal of an array of zeros to 1:
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]]])
977 """
978 idx = arange(n)
979 return (idx,) * ndim
982def _diag_indices_from(arr):
983 return (arr,)
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.
991 See `diag_indices` for full details.
993 Parameters
994 ----------
995 arr : array, at least 2-D
997 See Also
998 --------
999 diag_indices
1001 Notes
1002 -----
1003 .. versionadded:: 1.4.0
1005 """
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")
1014 return diag_indices(arr.shape[0], arr.ndim)