Mercurial > hg > vamp-build-and-test
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) |