dask-array 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dask_array/__init__.py +228 -0
- dask_array/_backends.py +76 -0
- dask_array/_backends_array.py +99 -0
- dask_array/_blockwise.py +1410 -0
- dask_array/_broadcast.py +272 -0
- dask_array/_chunk.py +445 -0
- dask_array/_chunk_types.py +54 -0
- dask_array/_collection.py +1644 -0
- dask_array/_concatenate.py +331 -0
- dask_array/_core_utils.py +1365 -0
- dask_array/_dispatch.py +141 -0
- dask_array/_einsum.py +277 -0
- dask_array/_expr.py +544 -0
- dask_array/_expr_flow.py +586 -0
- dask_array/_gufunc.py +805 -0
- dask_array/_histogram.py +617 -0
- dask_array/_map_blocks.py +652 -0
- dask_array/_new_collection.py +10 -0
- dask_array/_numpy_compat.py +135 -0
- dask_array/_overlap.py +1159 -0
- dask_array/_rechunk.py +1050 -0
- dask_array/_reshape.py +710 -0
- dask_array/_routines.py +102 -0
- dask_array/_shuffle.py +448 -0
- dask_array/_stack.py +264 -0
- dask_array/_svg.py +291 -0
- dask_array/_templates.py +29 -0
- dask_array/_test_utils.py +257 -0
- dask_array/_ufunc.py +385 -0
- dask_array/_utils.py +349 -0
- dask_array/_visualize.py +223 -0
- dask_array/_xarray.py +337 -0
- dask_array/core/__init__.py +34 -0
- dask_array/core/_blockwise_funcs.py +312 -0
- dask_array/core/_conversion.py +422 -0
- dask_array/core/_from_graph.py +97 -0
- dask_array/creation/__init__.py +71 -0
- dask_array/creation/_arange.py +121 -0
- dask_array/creation/_diag.py +116 -0
- dask_array/creation/_diagonal.py +241 -0
- dask_array/creation/_eye.py +103 -0
- dask_array/creation/_linspace.py +102 -0
- dask_array/creation/_mesh.py +134 -0
- dask_array/creation/_ones_zeros.py +454 -0
- dask_array/creation/_pad.py +270 -0
- dask_array/creation/_repeat.py +55 -0
- dask_array/creation/_tile.py +36 -0
- dask_array/creation/_tri.py +28 -0
- dask_array/creation/_utils.py +296 -0
- dask_array/fft.py +320 -0
- dask_array/io/__init__.py +39 -0
- dask_array/io/_base.py +10 -0
- dask_array/io/_from_array.py +257 -0
- dask_array/io/_from_delayed.py +95 -0
- dask_array/io/_from_graph.py +54 -0
- dask_array/io/_from_npy_stack.py +67 -0
- dask_array/io/_store.py +336 -0
- dask_array/io/_tiledb.py +159 -0
- dask_array/io/_to_npy_stack.py +65 -0
- dask_array/io/_zarr.py +449 -0
- dask_array/linalg/__init__.py +39 -0
- dask_array/linalg/_cholesky.py +234 -0
- dask_array/linalg/_lu.py +300 -0
- dask_array/linalg/_norm.py +94 -0
- dask_array/linalg/_qr.py +601 -0
- dask_array/linalg/_solve.py +349 -0
- dask_array/linalg/_svd.py +394 -0
- dask_array/linalg/_tensordot.py +334 -0
- dask_array/linalg/_utils.py +74 -0
- dask_array/manipulation/__init__.py +45 -0
- dask_array/manipulation/_expand.py +321 -0
- dask_array/manipulation/_flip.py +92 -0
- dask_array/manipulation/_roll.py +78 -0
- dask_array/manipulation/_transpose.py +309 -0
- dask_array/random/__init__.py +125 -0
- dask_array/random/_choice.py +181 -0
- dask_array/random/_expr.py +256 -0
- dask_array/random/_generator.py +441 -0
- dask_array/random/_random_state.py +259 -0
- dask_array/random/_utils.py +84 -0
- dask_array/reductions/__init__.py +84 -0
- dask_array/reductions/_arg_reduction.py +130 -0
- dask_array/reductions/_common.py +1082 -0
- dask_array/reductions/_cumulative.py +522 -0
- dask_array/reductions/_percentile.py +261 -0
- dask_array/reductions/_reduction.py +725 -0
- dask_array/reductions/_trace.py +56 -0
- dask_array/routines/__init__.py +133 -0
- dask_array/routines/_apply.py +84 -0
- dask_array/routines/_bincount.py +112 -0
- dask_array/routines/_broadcast.py +111 -0
- dask_array/routines/_coarsen.py +115 -0
- dask_array/routines/_diff.py +79 -0
- dask_array/routines/_gradient.py +158 -0
- dask_array/routines/_indexing.py +65 -0
- dask_array/routines/_insert_delete.py +132 -0
- dask_array/routines/_misc.py +122 -0
- dask_array/routines/_nonzero.py +72 -0
- dask_array/routines/_search.py +123 -0
- dask_array/routines/_select.py +113 -0
- dask_array/routines/_statistics.py +171 -0
- dask_array/routines/_topk.py +82 -0
- dask_array/routines/_triangular.py +74 -0
- dask_array/routines/_unique.py +232 -0
- dask_array/routines/_where.py +62 -0
- dask_array/slicing/__init__.py +67 -0
- dask_array/slicing/_basic.py +550 -0
- dask_array/slicing/_blocks.py +138 -0
- dask_array/slicing/_bool_index.py +145 -0
- dask_array/slicing/_setitem.py +329 -0
- dask_array/slicing/_squeeze.py +101 -0
- dask_array/slicing/_utils.py +1133 -0
- dask_array/slicing/_vindex.py +282 -0
- dask_array/stacking/__init__.py +15 -0
- dask_array/stacking/_block.py +83 -0
- dask_array/stacking/_simple.py +58 -0
- dask_array/templates/array.html.j2 +48 -0
- dask_array/tests/__init__.py +0 -0
- dask_array/tests/conftest.py +22 -0
- dask_array/tests/test_api.py +40 -0
- dask_array/tests/test_binary_op_chunks.py +107 -0
- dask_array/tests/test_coarse_slice_through_blockwise.py +362 -0
- dask_array/tests/test_collection.py +799 -0
- dask_array/tests/test_creation.py +1102 -0
- dask_array/tests/test_expr_flow.py +143 -0
- dask_array/tests/test_linalg.py +1130 -0
- dask_array/tests/test_map_blocks_multi_output.py +104 -0
- dask_array/tests/test_rechunk_pushdown.py +214 -0
- dask_array/tests/test_reductions.py +1091 -0
- dask_array/tests/test_routines.py +2853 -0
- dask_array/tests/test_shuffle_chunks.py +67 -0
- dask_array/tests/test_slice_pushdown.py +968 -0
- dask_array/tests/test_slice_through_blockwise.py +678 -0
- dask_array/tests/test_slice_through_overlap.py +366 -0
- dask_array/tests/test_slice_through_reshape.py +272 -0
- dask_array/tests/test_slicing.py +839 -0
- dask_array/tests/test_transpose_slice_pushdown.py +208 -0
- dask_array/tests/test_visualize.py +94 -0
- dask_array/tests/test_xarray.py +193 -0
- dask_array-0.1.0.dist-info/METADATA +48 -0
- dask_array-0.1.0.dist-info/RECORD +144 -0
- dask_array-0.1.0.dist-info/WHEEL +4 -0
- dask_array-0.1.0.dist-info/entry_points.txt +2 -0
- dask_array-0.1.0.dist-info/licenses/LICENSE +29 -0
|
@@ -0,0 +1,1644 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import operator
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from dask import config
|
|
10
|
+
from dask_array import _chunk as chunk
|
|
11
|
+
from dask_array._new_collection import new_collection
|
|
12
|
+
from dask_array._expr import ArrayExpr
|
|
13
|
+
from dask_array.manipulation._transpose import Transpose
|
|
14
|
+
from dask_array._chunk_types import is_valid_chunk_type
|
|
15
|
+
from dask.base import DaskMethodsMixin, is_dask_collection, named_schedulers
|
|
16
|
+
from dask.core import flatten
|
|
17
|
+
from dask.utils import format_bytes, has_keyword, key_split, typename
|
|
18
|
+
|
|
19
|
+
from dask_array._templates import get_template
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
ARRAY_TEMPLATE = get_template("array.html.j2")
|
|
23
|
+
except ImportError:
|
|
24
|
+
ARRAY_TEMPLATE = None
|
|
25
|
+
|
|
26
|
+
# Import blockwise functions from their module
|
|
27
|
+
# Import broadcast
|
|
28
|
+
from dask_array._broadcast import broadcast_to
|
|
29
|
+
|
|
30
|
+
# Import concatenate and stacking
|
|
31
|
+
from dask_array._concatenate import concatenate
|
|
32
|
+
from dask_array._stack import stack
|
|
33
|
+
from dask_array.core._blockwise_funcs import blockwise, elemwise
|
|
34
|
+
|
|
35
|
+
# Import core conversion functions from their module
|
|
36
|
+
from dask_array.core._conversion import (
|
|
37
|
+
array,
|
|
38
|
+
asanyarray,
|
|
39
|
+
asarray,
|
|
40
|
+
from_array,
|
|
41
|
+
)
|
|
42
|
+
from dask_array.core._from_graph import from_graph
|
|
43
|
+
|
|
44
|
+
# Import manipulation functions
|
|
45
|
+
from dask_array.manipulation._expand import (
|
|
46
|
+
atleast_1d,
|
|
47
|
+
atleast_2d,
|
|
48
|
+
atleast_3d,
|
|
49
|
+
expand_dims,
|
|
50
|
+
)
|
|
51
|
+
from dask_array.manipulation._flip import flip, fliplr, flipud, rot90
|
|
52
|
+
from dask_array.manipulation._roll import roll
|
|
53
|
+
from dask_array.manipulation._transpose import (
|
|
54
|
+
moveaxis,
|
|
55
|
+
rollaxis,
|
|
56
|
+
transpose,
|
|
57
|
+
)
|
|
58
|
+
from dask_array.stacking._block import block
|
|
59
|
+
from dask_array.stacking._simple import dstack, hstack, vstack
|
|
60
|
+
|
|
61
|
+
# Type imports
|
|
62
|
+
from dask_array._core_utils import (
|
|
63
|
+
_HANDLED_FUNCTIONS,
|
|
64
|
+
T_IntOrNaN,
|
|
65
|
+
_get_chunk_shape,
|
|
66
|
+
_should_delegate,
|
|
67
|
+
cached_max,
|
|
68
|
+
check_if_handled_given_other,
|
|
69
|
+
finalize,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
__all__ = [
|
|
73
|
+
"Array",
|
|
74
|
+
"array",
|
|
75
|
+
"asanyarray",
|
|
76
|
+
"asarray",
|
|
77
|
+
"atleast_1d",
|
|
78
|
+
"atleast_2d",
|
|
79
|
+
"atleast_3d",
|
|
80
|
+
"block",
|
|
81
|
+
"blockwise",
|
|
82
|
+
"broadcast_to",
|
|
83
|
+
"concatenate",
|
|
84
|
+
"dstack",
|
|
85
|
+
"elemwise",
|
|
86
|
+
"expand_dims",
|
|
87
|
+
"flip",
|
|
88
|
+
"fliplr",
|
|
89
|
+
"flipud",
|
|
90
|
+
"from_array",
|
|
91
|
+
"from_graph",
|
|
92
|
+
"hstack",
|
|
93
|
+
"moveaxis",
|
|
94
|
+
"ravel",
|
|
95
|
+
"rechunk",
|
|
96
|
+
"reshape",
|
|
97
|
+
"reshape_blockwise",
|
|
98
|
+
"roll",
|
|
99
|
+
"rollaxis",
|
|
100
|
+
"rot90",
|
|
101
|
+
"squeeze",
|
|
102
|
+
"stack",
|
|
103
|
+
"swapaxes",
|
|
104
|
+
"transpose",
|
|
105
|
+
"vstack",
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class Array(DaskMethodsMixin):
|
|
110
|
+
__dask_scheduler__ = staticmethod(named_schedulers.get("threads", named_schedulers["sync"]))
|
|
111
|
+
__dask_optimize__ = staticmethod(lambda dsk, keys, **kwargs: dsk)
|
|
112
|
+
__array_priority__ = 11 # higher than numpy.ndarray and numpy.matrix
|
|
113
|
+
|
|
114
|
+
def __init__(self, expr):
|
|
115
|
+
self._expr = expr
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def expr(self) -> ArrayExpr:
|
|
119
|
+
return self._expr
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def _name(self):
|
|
123
|
+
return self.expr._name
|
|
124
|
+
|
|
125
|
+
def __dask_postcompute__(self):
|
|
126
|
+
return finalize, ()
|
|
127
|
+
|
|
128
|
+
def __dask_postpersist__(self):
|
|
129
|
+
state = self.expr.lower_completely()
|
|
130
|
+
# Use original array's meta like legacy implementation
|
|
131
|
+
meta = self._meta
|
|
132
|
+
if meta is None:
|
|
133
|
+
# Fallback to synthetic meta if original is also None
|
|
134
|
+
meta = np.empty((0,) * state.ndim, dtype=state.dtype)
|
|
135
|
+
# Use self.chunks to preserve nan chunks for unknown-sized operations
|
|
136
|
+
return from_graph, (
|
|
137
|
+
meta,
|
|
138
|
+
self.chunks,
|
|
139
|
+
# FIXME: This is using keys of the unoptimized graph
|
|
140
|
+
list(flatten(state.__dask_keys__())),
|
|
141
|
+
key_split(state._name),
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def dask(self):
|
|
146
|
+
return self.__dask_graph__()
|
|
147
|
+
|
|
148
|
+
def __dask_graph__(self):
|
|
149
|
+
out = self.expr.lower_completely()
|
|
150
|
+
return out.__dask_graph__()
|
|
151
|
+
|
|
152
|
+
def __dask_keys__(self):
|
|
153
|
+
out = self.expr.lower_completely()
|
|
154
|
+
return out.__dask_keys__()
|
|
155
|
+
|
|
156
|
+
def __dask_tokenize__(self):
|
|
157
|
+
return "Array", self.expr._name
|
|
158
|
+
|
|
159
|
+
def compute(self, **kwargs):
|
|
160
|
+
return DaskMethodsMixin.compute(self.optimize(), **kwargs)
|
|
161
|
+
|
|
162
|
+
def persist(self, **kwargs):
|
|
163
|
+
return DaskMethodsMixin.persist(self.optimize(), **kwargs)
|
|
164
|
+
|
|
165
|
+
def optimize(self):
|
|
166
|
+
return new_collection(self.expr.optimize())
|
|
167
|
+
|
|
168
|
+
def simplify(self):
|
|
169
|
+
return new_collection(self.expr.simplify())
|
|
170
|
+
|
|
171
|
+
def pprint(self):
|
|
172
|
+
"""Pretty print the expression tree.
|
|
173
|
+
|
|
174
|
+
Uses rich table format if rich is installed, otherwise falls back
|
|
175
|
+
to the basic tree representation.
|
|
176
|
+
"""
|
|
177
|
+
self.expr.pprint()
|
|
178
|
+
|
|
179
|
+
def visualize(self, tasks: bool = False, **kwargs): # type: ignore[override]
|
|
180
|
+
"""Visualize the expression or task graph.
|
|
181
|
+
|
|
182
|
+
Parameters
|
|
183
|
+
----------
|
|
184
|
+
tasks : bool
|
|
185
|
+
Whether to visualize the task graph. By default
|
|
186
|
+
the expression graph will be visualized instead.
|
|
187
|
+
**kwargs
|
|
188
|
+
Additional arguments passed to the visualizer.
|
|
189
|
+
"""
|
|
190
|
+
# color= options require task graph visualization
|
|
191
|
+
if tasks or kwargs.get("color"):
|
|
192
|
+
return super().visualize(**kwargs)
|
|
193
|
+
return self.expr.visualize(**kwargs)
|
|
194
|
+
|
|
195
|
+
@property
|
|
196
|
+
def _meta(self):
|
|
197
|
+
return self.expr._meta
|
|
198
|
+
|
|
199
|
+
@property
|
|
200
|
+
def dtype(self):
|
|
201
|
+
return self.expr.dtype
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def shape(self):
|
|
205
|
+
return self.expr.shape
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def chunks(self):
|
|
209
|
+
return self.expr.chunks
|
|
210
|
+
|
|
211
|
+
@chunks.setter
|
|
212
|
+
def chunks(self, chunks):
|
|
213
|
+
raise TypeError(
|
|
214
|
+
"Can not set chunks directly\n\n"
|
|
215
|
+
"Please use the rechunk method instead:\n"
|
|
216
|
+
f" x.rechunk({chunks})\n\n"
|
|
217
|
+
"Documentation\n"
|
|
218
|
+
"-------------\n"
|
|
219
|
+
"https://docs.dask.org/en/latest/generated/dask.array.rechunk.html"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def _chunks(self):
|
|
224
|
+
"""Internal access to chunks (for compatibility with tests)."""
|
|
225
|
+
return self.expr.chunks
|
|
226
|
+
|
|
227
|
+
@_chunks.setter
|
|
228
|
+
def _chunks(self, chunks):
|
|
229
|
+
"""Set chunks by wrapping the expression with ChunksOverride.
|
|
230
|
+
|
|
231
|
+
This is primarily for internal use and testing when simulating
|
|
232
|
+
arrays with unknown chunk sizes.
|
|
233
|
+
"""
|
|
234
|
+
from dask_array._expr import ChunksOverride
|
|
235
|
+
|
|
236
|
+
self._expr = ChunksOverride(self._expr, chunks)
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def chunksize(self) -> tuple:
|
|
240
|
+
return tuple(cached_max(c) for c in self.chunks)
|
|
241
|
+
|
|
242
|
+
@property
|
|
243
|
+
def ndim(self):
|
|
244
|
+
return self.expr.ndim
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def numblocks(self):
|
|
248
|
+
return self.expr.numblocks
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def npartitions(self):
|
|
252
|
+
from math import prod
|
|
253
|
+
|
|
254
|
+
return prod(self.numblocks)
|
|
255
|
+
|
|
256
|
+
def compute_chunk_sizes(self):
|
|
257
|
+
"""
|
|
258
|
+
Compute the chunk sizes for a Dask array. This is especially useful
|
|
259
|
+
when the chunk sizes are unknown (e.g., when indexing one Dask array
|
|
260
|
+
with another).
|
|
261
|
+
|
|
262
|
+
Notes
|
|
263
|
+
-----
|
|
264
|
+
This function modifies the Dask array in-place.
|
|
265
|
+
|
|
266
|
+
Examples
|
|
267
|
+
--------
|
|
268
|
+
>>> import dask_array as da
|
|
269
|
+
>>> import numpy as np
|
|
270
|
+
>>> x = da.from_array([-2, -1, 0, 1, 2], chunks=2)
|
|
271
|
+
>>> x.chunks
|
|
272
|
+
((2, 2, 1),)
|
|
273
|
+
>>> y = x[x <= 0]
|
|
274
|
+
>>> y.chunks
|
|
275
|
+
((nan, nan, nan),)
|
|
276
|
+
>>> y.compute_chunk_sizes() # in-place computation
|
|
277
|
+
dask.array<getitem, shape=(3,), dtype=int64, chunksize=(2,), chunktype=numpy.ndarray>
|
|
278
|
+
>>> y.chunks
|
|
279
|
+
((2, 1, 0),)
|
|
280
|
+
"""
|
|
281
|
+
from dask.base import compute
|
|
282
|
+
|
|
283
|
+
chunk_shapes = self.map_blocks(
|
|
284
|
+
_get_chunk_shape,
|
|
285
|
+
dtype=int,
|
|
286
|
+
chunks=tuple(len(c) * (1,) for c in self.chunks) + ((self.ndim,),),
|
|
287
|
+
new_axis=self.ndim,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
c = []
|
|
291
|
+
for i in range(self.ndim):
|
|
292
|
+
s = self.ndim * [0] + [i]
|
|
293
|
+
s[i] = slice(None)
|
|
294
|
+
s = tuple(s)
|
|
295
|
+
|
|
296
|
+
c.append(tuple(chunk_shapes[s]))
|
|
297
|
+
|
|
298
|
+
# `map_blocks` assigns numpy dtypes
|
|
299
|
+
# cast chunk dimensions back to python int before returning
|
|
300
|
+
new_chunks = tuple(tuple(int(chunk) for chunk in chunks) for chunks in compute(tuple(c))[0])
|
|
301
|
+
|
|
302
|
+
# In the expression system, wrap with ChunksOverride to set the new chunks
|
|
303
|
+
from dask_array._expr import ChunksOverride
|
|
304
|
+
|
|
305
|
+
self._expr = ChunksOverride(self._expr, new_chunks)
|
|
306
|
+
|
|
307
|
+
return self
|
|
308
|
+
|
|
309
|
+
@property
|
|
310
|
+
def _key_array(self):
|
|
311
|
+
return np.array(self.__dask_keys__(), dtype=object)
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def blocks(self):
|
|
315
|
+
from dask_array.slicing._blocks import BlockView
|
|
316
|
+
|
|
317
|
+
return BlockView(self)
|
|
318
|
+
|
|
319
|
+
@property
|
|
320
|
+
def partitions(self):
|
|
321
|
+
"""Slice an array by partitions. Alias of dask array .blocks attribute."""
|
|
322
|
+
return self.blocks
|
|
323
|
+
|
|
324
|
+
@property
|
|
325
|
+
def size(self) -> T_IntOrNaN:
|
|
326
|
+
return self.expr.size
|
|
327
|
+
|
|
328
|
+
@property
|
|
329
|
+
def nbytes(self) -> T_IntOrNaN:
|
|
330
|
+
"""Number of bytes in array"""
|
|
331
|
+
return self.size * self.dtype.itemsize
|
|
332
|
+
|
|
333
|
+
@property
|
|
334
|
+
def itemsize(self) -> int:
|
|
335
|
+
"""Length of one array element in bytes"""
|
|
336
|
+
return self.dtype.itemsize
|
|
337
|
+
|
|
338
|
+
@property
|
|
339
|
+
def name(self):
|
|
340
|
+
return self.expr.name
|
|
341
|
+
|
|
342
|
+
def __len__(self):
|
|
343
|
+
return self.expr.__len__()
|
|
344
|
+
|
|
345
|
+
def __repr__(self):
|
|
346
|
+
name = self.name.rsplit("-", 1)[0]
|
|
347
|
+
return "dask.array<{}, shape={}, dtype={}, chunksize={}, chunktype={}.{}>".format(
|
|
348
|
+
name,
|
|
349
|
+
self.shape,
|
|
350
|
+
self.dtype,
|
|
351
|
+
self.chunksize,
|
|
352
|
+
type(self._meta).__module__.split(".")[0],
|
|
353
|
+
type(self._meta).__name__,
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
def _repr_html_(self):
|
|
357
|
+
if ARRAY_TEMPLATE is None:
|
|
358
|
+
return repr(self)
|
|
359
|
+
|
|
360
|
+
try:
|
|
361
|
+
grid = self.to_svg(size=config.get("array.svg.size", 120))
|
|
362
|
+
except NotImplementedError:
|
|
363
|
+
grid = ""
|
|
364
|
+
|
|
365
|
+
if "sparse" in typename(type(self._meta)):
|
|
366
|
+
nbytes = None
|
|
367
|
+
cbytes = None
|
|
368
|
+
elif not math.isnan(self.nbytes):
|
|
369
|
+
nbytes = format_bytes(self.nbytes)
|
|
370
|
+
cbytes = format_bytes(math.prod(self.chunksize) * self.dtype.itemsize)
|
|
371
|
+
else:
|
|
372
|
+
nbytes = "unknown"
|
|
373
|
+
cbytes = "unknown"
|
|
374
|
+
|
|
375
|
+
# Expression flow summary and diagram
|
|
376
|
+
from dask_array._expr_flow import build_flow_graph, render_flow_svg, count_operations
|
|
377
|
+
|
|
378
|
+
try:
|
|
379
|
+
nodes, edges = build_flow_graph(self._expr)
|
|
380
|
+
n_expr = count_operations(self._expr)
|
|
381
|
+
expr_flow = render_flow_svg(self._expr) if nodes else ""
|
|
382
|
+
except Exception:
|
|
383
|
+
n_expr = 1
|
|
384
|
+
expr_flow = ""
|
|
385
|
+
|
|
386
|
+
return ARRAY_TEMPLATE.render(
|
|
387
|
+
array=self,
|
|
388
|
+
grid=grid,
|
|
389
|
+
nbytes=nbytes,
|
|
390
|
+
cbytes=cbytes,
|
|
391
|
+
n_expr=n_expr,
|
|
392
|
+
expr_flow=expr_flow,
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
def __bool__(self):
|
|
396
|
+
if self.size > 1:
|
|
397
|
+
raise ValueError(f"The truth value of a {self.__class__.__name__} is ambiguous. Use a.any() or a.all().")
|
|
398
|
+
return bool(self.compute())
|
|
399
|
+
|
|
400
|
+
def _scalarfunc(self, cast_type):
|
|
401
|
+
if self.size > 1:
|
|
402
|
+
raise TypeError("Only length-1 arrays can be converted to Python scalars")
|
|
403
|
+
else:
|
|
404
|
+
return cast_type(self.compute().item())
|
|
405
|
+
|
|
406
|
+
def __int__(self):
|
|
407
|
+
return self._scalarfunc(int)
|
|
408
|
+
|
|
409
|
+
def __float__(self):
|
|
410
|
+
return self._scalarfunc(float)
|
|
411
|
+
|
|
412
|
+
def __complex__(self):
|
|
413
|
+
return self._scalarfunc(complex)
|
|
414
|
+
|
|
415
|
+
def __index__(self):
|
|
416
|
+
return self._scalarfunc(operator.index)
|
|
417
|
+
|
|
418
|
+
def __array__(self, dtype=None, copy=None, **kwargs):
|
|
419
|
+
import warnings
|
|
420
|
+
|
|
421
|
+
if kwargs:
|
|
422
|
+
warnings.warn(
|
|
423
|
+
f"Extra keyword arguments {kwargs} are ignored and won't be accepted in the future",
|
|
424
|
+
FutureWarning,
|
|
425
|
+
)
|
|
426
|
+
if copy is False:
|
|
427
|
+
warnings.warn(
|
|
428
|
+
"Can't acquire a memory view of a Dask array. This will raise in the future.",
|
|
429
|
+
FutureWarning,
|
|
430
|
+
)
|
|
431
|
+
x = self.compute()
|
|
432
|
+
return np.asarray(x, dtype=dtype)
|
|
433
|
+
|
|
434
|
+
def __iter__(self):
|
|
435
|
+
for i in range(len(self)):
|
|
436
|
+
yield self[i]
|
|
437
|
+
|
|
438
|
+
def __getitem__(self, index):
|
|
439
|
+
# Field access, e.g. x['a'] or x[['a', 'b']]
|
|
440
|
+
if isinstance(index, str) or (isinstance(index, list) and index and all(isinstance(i, str) for i in index)):
|
|
441
|
+
from dask_array._chunk import getitem
|
|
442
|
+
|
|
443
|
+
if isinstance(index, str):
|
|
444
|
+
dt = self.dtype[index]
|
|
445
|
+
else:
|
|
446
|
+
dt = np.dtype(
|
|
447
|
+
{
|
|
448
|
+
"names": index,
|
|
449
|
+
"formats": [self.dtype.fields[name][0] for name in index],
|
|
450
|
+
"offsets": [self.dtype.fields[name][1] for name in index],
|
|
451
|
+
"itemsize": self.dtype.itemsize,
|
|
452
|
+
}
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
if dt.shape:
|
|
456
|
+
new_axis = list(range(self.ndim, self.ndim + len(dt.shape)))
|
|
457
|
+
chunks = self.chunks + tuple((i,) for i in dt.shape)
|
|
458
|
+
return self.map_blocks(getitem, index, dtype=dt.base, chunks=chunks, new_axis=new_axis)
|
|
459
|
+
else:
|
|
460
|
+
return self.map_blocks(getitem, index, dtype=dt)
|
|
461
|
+
|
|
462
|
+
if not isinstance(index, tuple):
|
|
463
|
+
index = (index,)
|
|
464
|
+
|
|
465
|
+
from dask_array.slicing import (
|
|
466
|
+
normalize_index,
|
|
467
|
+
slice_array,
|
|
468
|
+
slice_with_int_dask_array,
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
index2 = normalize_index(index, self.shape)
|
|
472
|
+
|
|
473
|
+
dependencies = {self.name}
|
|
474
|
+
for i in index2:
|
|
475
|
+
if isinstance(i, Array):
|
|
476
|
+
dependencies.add(i.name)
|
|
477
|
+
|
|
478
|
+
if any(isinstance(i, Array) and i.dtype.kind in "iu" for i in index2):
|
|
479
|
+
self, index2 = slice_with_int_dask_array(self, index2)
|
|
480
|
+
if any(isinstance(i, Array) and i.dtype == bool for i in index2):
|
|
481
|
+
from dask_array.slicing import slice_with_bool_dask_array
|
|
482
|
+
|
|
483
|
+
self, index2 = slice_with_bool_dask_array(self, index2)
|
|
484
|
+
|
|
485
|
+
if all(isinstance(i, slice) and i == slice(None) for i in index2):
|
|
486
|
+
return self
|
|
487
|
+
|
|
488
|
+
result = slice_array(self.expr, index2)
|
|
489
|
+
return new_collection(result)
|
|
490
|
+
|
|
491
|
+
def __setitem__(self, key, value):
|
|
492
|
+
from dask_array._core_utils import unknown_chunk_message
|
|
493
|
+
|
|
494
|
+
# Handle np.ma.masked assignment
|
|
495
|
+
if value is np.ma.masked:
|
|
496
|
+
value = np.ma.masked_all((), dtype=self.dtype)
|
|
497
|
+
|
|
498
|
+
# Check for NaN/inf in integer arrays
|
|
499
|
+
if not is_dask_collection(value) and self.dtype.kind in "iu":
|
|
500
|
+
if np.isnan(value).any():
|
|
501
|
+
raise ValueError("cannot convert float NaN to integer")
|
|
502
|
+
if np.isinf(value).any():
|
|
503
|
+
raise ValueError("cannot convert float infinity to integer")
|
|
504
|
+
|
|
505
|
+
# Suppress dtype broadcasting; __setitem__ can't change the dtype.
|
|
506
|
+
value = asanyarray(value, dtype=self.dtype)
|
|
507
|
+
|
|
508
|
+
# Handle 1D integer array index case
|
|
509
|
+
if isinstance(key, Array) and (
|
|
510
|
+
key.dtype.kind in "iu" or (key.dtype == bool and key.ndim == 1 and self.ndim > 1)
|
|
511
|
+
):
|
|
512
|
+
key = (key,)
|
|
513
|
+
|
|
514
|
+
# Use "where" method for any dask Array key (matches legacy behavior)
|
|
515
|
+
if isinstance(key, Array):
|
|
516
|
+
from dask_array._broadcast import broadcast_to
|
|
517
|
+
|
|
518
|
+
left_shape = np.array(key.shape)
|
|
519
|
+
right_shape = np.array(self.shape)
|
|
520
|
+
|
|
521
|
+
# Treat unknown shapes as matching
|
|
522
|
+
match = left_shape == right_shape
|
|
523
|
+
match |= np.isnan(left_shape) | np.isnan(right_shape)
|
|
524
|
+
|
|
525
|
+
if not match.all():
|
|
526
|
+
raise IndexError(f"boolean index shape {key.shape} must match indexed array's {self.shape}.")
|
|
527
|
+
|
|
528
|
+
# If value has ndim > 0, they must be broadcastable to self.shape[idx].
|
|
529
|
+
if value.ndim:
|
|
530
|
+
value = broadcast_to(value, self[key].shape)
|
|
531
|
+
|
|
532
|
+
from dask_array.routines._where import where
|
|
533
|
+
|
|
534
|
+
y = where(key, value, self)
|
|
535
|
+
self._expr = y.expr
|
|
536
|
+
return
|
|
537
|
+
|
|
538
|
+
# Check for unknown chunks
|
|
539
|
+
if np.isnan(self.shape).any():
|
|
540
|
+
raise ValueError(f"Arrays chunk sizes are unknown. {unknown_chunk_message}")
|
|
541
|
+
|
|
542
|
+
# Validate indices and value shape eagerly (before creating lazy expression)
|
|
543
|
+
import math
|
|
544
|
+
|
|
545
|
+
from dask_array.slicing._utils import parse_assignment_indices
|
|
546
|
+
|
|
547
|
+
indices, implied_shape, _, implied_shape_positions = parse_assignment_indices(key, self.shape)
|
|
548
|
+
value_shape = value.shape
|
|
549
|
+
|
|
550
|
+
# Validate value shape vs implied shape (from setitem_array validation)
|
|
551
|
+
if 0 in implied_shape and value_shape and max(value_shape) > 1:
|
|
552
|
+
raise ValueError(
|
|
553
|
+
f"shape mismatch: value array of shape {value_shape} "
|
|
554
|
+
"could not be broadcast to indexing result "
|
|
555
|
+
f"of shape {tuple(implied_shape)}"
|
|
556
|
+
)
|
|
557
|
+
|
|
558
|
+
value_ndim = len(value_shape)
|
|
559
|
+
offset = len(implied_shape) - value_ndim
|
|
560
|
+
if offset >= 0:
|
|
561
|
+
array_common_shape = implied_shape[offset:]
|
|
562
|
+
value_common_shape = value_shape
|
|
563
|
+
implied_positions = implied_shape_positions[offset:]
|
|
564
|
+
else:
|
|
565
|
+
value_offset = -offset
|
|
566
|
+
array_common_shape = implied_shape
|
|
567
|
+
value_common_shape = value_shape[value_offset:]
|
|
568
|
+
implied_positions = implied_shape_positions
|
|
569
|
+
# All extra leading dimensions must have size 1
|
|
570
|
+
if value_shape[:value_offset] != (1,) * value_offset:
|
|
571
|
+
raise ValueError(
|
|
572
|
+
f"could not broadcast input array from shape{value_shape} into shape {tuple(implied_shape)}"
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
# Check shape compatibility for each dimension
|
|
576
|
+
for _, (a, b, j) in enumerate(zip(array_common_shape, value_common_shape, implied_positions)):
|
|
577
|
+
index = indices[j]
|
|
578
|
+
if is_dask_collection(index) and getattr(index, "dtype", None) == bool:
|
|
579
|
+
# For dask boolean index, value size must not exceed index size
|
|
580
|
+
if not math.isnan(b) and b > index.size:
|
|
581
|
+
raise ValueError(
|
|
582
|
+
f"shape mismatch: value array dimension size of {b} is "
|
|
583
|
+
"greater then corresponding boolean index size of "
|
|
584
|
+
f"{index.size}"
|
|
585
|
+
)
|
|
586
|
+
elif b != 1 and a != b and not math.isnan(a):
|
|
587
|
+
raise ValueError(
|
|
588
|
+
f"shape mismatch: value array of shape {value_shape} "
|
|
589
|
+
"could not be broadcast to indexing result of shape "
|
|
590
|
+
f"{tuple(implied_shape)}"
|
|
591
|
+
)
|
|
592
|
+
|
|
593
|
+
# Use SetItem expression for other index types
|
|
594
|
+
from dask_array.slicing import SetItem
|
|
595
|
+
|
|
596
|
+
value_expr = value.expr if isinstance(value, Array) else value
|
|
597
|
+
y = new_collection(SetItem(self.expr, key, value_expr))
|
|
598
|
+
self._expr = y.expr
|
|
599
|
+
|
|
600
|
+
@check_if_handled_given_other
|
|
601
|
+
def __add__(self, other):
|
|
602
|
+
return elemwise(operator.add, self, other)
|
|
603
|
+
|
|
604
|
+
@check_if_handled_given_other
|
|
605
|
+
def __radd__(self, other):
|
|
606
|
+
return elemwise(operator.add, other, self)
|
|
607
|
+
|
|
608
|
+
@check_if_handled_given_other
|
|
609
|
+
def __mul__(self, other):
|
|
610
|
+
return elemwise(operator.mul, self, other)
|
|
611
|
+
|
|
612
|
+
@check_if_handled_given_other
|
|
613
|
+
def __rmul__(self, other):
|
|
614
|
+
return elemwise(operator.mul, other, self)
|
|
615
|
+
|
|
616
|
+
@check_if_handled_given_other
|
|
617
|
+
def __sub__(self, other):
|
|
618
|
+
return elemwise(operator.sub, self, other)
|
|
619
|
+
|
|
620
|
+
@check_if_handled_given_other
|
|
621
|
+
def __rsub__(self, other):
|
|
622
|
+
return elemwise(operator.sub, other, self)
|
|
623
|
+
|
|
624
|
+
@check_if_handled_given_other
|
|
625
|
+
def __pow__(self, other):
|
|
626
|
+
return elemwise(operator.pow, self, other)
|
|
627
|
+
|
|
628
|
+
@check_if_handled_given_other
|
|
629
|
+
def __rpow__(self, other):
|
|
630
|
+
return elemwise(operator.pow, other, self)
|
|
631
|
+
|
|
632
|
+
@check_if_handled_given_other
|
|
633
|
+
def __truediv__(self, other):
|
|
634
|
+
return elemwise(operator.truediv, self, other)
|
|
635
|
+
|
|
636
|
+
@check_if_handled_given_other
|
|
637
|
+
def __rtruediv__(self, other):
|
|
638
|
+
return elemwise(operator.truediv, other, self)
|
|
639
|
+
|
|
640
|
+
@check_if_handled_given_other
|
|
641
|
+
def __floordiv__(self, other):
|
|
642
|
+
return elemwise(operator.floordiv, self, other)
|
|
643
|
+
|
|
644
|
+
@check_if_handled_given_other
|
|
645
|
+
def __rfloordiv__(self, other):
|
|
646
|
+
return elemwise(operator.floordiv, other, self)
|
|
647
|
+
|
|
648
|
+
def __abs__(self):
|
|
649
|
+
return elemwise(operator.abs, self)
|
|
650
|
+
|
|
651
|
+
@check_if_handled_given_other
|
|
652
|
+
def __and__(self, other):
|
|
653
|
+
return elemwise(operator.and_, self, other)
|
|
654
|
+
|
|
655
|
+
@check_if_handled_given_other
|
|
656
|
+
def __rand__(self, other):
|
|
657
|
+
return elemwise(operator.and_, other, self)
|
|
658
|
+
|
|
659
|
+
@check_if_handled_given_other
|
|
660
|
+
def __div__(self, other):
|
|
661
|
+
return elemwise(operator.div, self, other)
|
|
662
|
+
|
|
663
|
+
@check_if_handled_given_other
|
|
664
|
+
def __rdiv__(self, other):
|
|
665
|
+
return elemwise(operator.div, other, self)
|
|
666
|
+
|
|
667
|
+
@check_if_handled_given_other
|
|
668
|
+
def __eq__(self, other):
|
|
669
|
+
return elemwise(operator.eq, self, other)
|
|
670
|
+
|
|
671
|
+
@check_if_handled_given_other
|
|
672
|
+
def __gt__(self, other):
|
|
673
|
+
return elemwise(operator.gt, self, other)
|
|
674
|
+
|
|
675
|
+
@check_if_handled_given_other
|
|
676
|
+
def __ge__(self, other):
|
|
677
|
+
return elemwise(operator.ge, self, other)
|
|
678
|
+
|
|
679
|
+
def __invert__(self):
|
|
680
|
+
return elemwise(operator.invert, self)
|
|
681
|
+
|
|
682
|
+
@check_if_handled_given_other
|
|
683
|
+
def __lshift__(self, other):
|
|
684
|
+
return elemwise(operator.lshift, self, other)
|
|
685
|
+
|
|
686
|
+
@check_if_handled_given_other
|
|
687
|
+
def __rlshift__(self, other):
|
|
688
|
+
return elemwise(operator.lshift, other, self)
|
|
689
|
+
|
|
690
|
+
@check_if_handled_given_other
|
|
691
|
+
def __lt__(self, other):
|
|
692
|
+
return elemwise(operator.lt, self, other)
|
|
693
|
+
|
|
694
|
+
@check_if_handled_given_other
|
|
695
|
+
def __le__(self, other):
|
|
696
|
+
return elemwise(operator.le, self, other)
|
|
697
|
+
|
|
698
|
+
@check_if_handled_given_other
|
|
699
|
+
def __mod__(self, other):
|
|
700
|
+
return elemwise(operator.mod, self, other)
|
|
701
|
+
|
|
702
|
+
@check_if_handled_given_other
|
|
703
|
+
def __rmod__(self, other):
|
|
704
|
+
return elemwise(operator.mod, other, self)
|
|
705
|
+
|
|
706
|
+
@check_if_handled_given_other
|
|
707
|
+
def __ne__(self, other):
|
|
708
|
+
return elemwise(operator.ne, self, other)
|
|
709
|
+
|
|
710
|
+
def __neg__(self):
|
|
711
|
+
return elemwise(operator.neg, self)
|
|
712
|
+
|
|
713
|
+
@check_if_handled_given_other
|
|
714
|
+
def __or__(self, other):
|
|
715
|
+
return elemwise(operator.or_, self, other)
|
|
716
|
+
|
|
717
|
+
def __pos__(self):
|
|
718
|
+
return self
|
|
719
|
+
|
|
720
|
+
@check_if_handled_given_other
|
|
721
|
+
def __ror__(self, other):
|
|
722
|
+
return elemwise(operator.or_, other, self)
|
|
723
|
+
|
|
724
|
+
@check_if_handled_given_other
|
|
725
|
+
def __rshift__(self, other):
|
|
726
|
+
return elemwise(operator.rshift, self, other)
|
|
727
|
+
|
|
728
|
+
@check_if_handled_given_other
|
|
729
|
+
def __rrshift__(self, other):
|
|
730
|
+
return elemwise(operator.rshift, other, self)
|
|
731
|
+
|
|
732
|
+
@check_if_handled_given_other
|
|
733
|
+
def __xor__(self, other):
|
|
734
|
+
return elemwise(operator.xor, self, other)
|
|
735
|
+
|
|
736
|
+
@check_if_handled_given_other
|
|
737
|
+
def __rxor__(self, other):
|
|
738
|
+
return elemwise(operator.xor, other, self)
|
|
739
|
+
|
|
740
|
+
@check_if_handled_given_other
|
|
741
|
+
def __matmul__(self, other):
|
|
742
|
+
from dask_array.linalg import matmul
|
|
743
|
+
|
|
744
|
+
return matmul(self, other)
|
|
745
|
+
|
|
746
|
+
@check_if_handled_given_other
|
|
747
|
+
def __rmatmul__(self, other):
|
|
748
|
+
from dask_array.linalg import matmul
|
|
749
|
+
|
|
750
|
+
return matmul(other, self)
|
|
751
|
+
|
|
752
|
+
@check_if_handled_given_other
|
|
753
|
+
def __divmod__(self, other):
|
|
754
|
+
from dask_array._ufunc import divmod
|
|
755
|
+
|
|
756
|
+
return divmod(self, other)
|
|
757
|
+
|
|
758
|
+
@check_if_handled_given_other
|
|
759
|
+
def __rdivmod__(self, other):
|
|
760
|
+
from dask_array._ufunc import divmod
|
|
761
|
+
|
|
762
|
+
return divmod(other, self)
|
|
763
|
+
|
|
764
|
+
def __array_function__(self, func, types, args, kwargs):
|
|
765
|
+
import dask_array as module
|
|
766
|
+
from dask.base import compute
|
|
767
|
+
|
|
768
|
+
def handle_nonmatching_names(func, args, kwargs):
|
|
769
|
+
if func not in _HANDLED_FUNCTIONS:
|
|
770
|
+
warnings.warn(
|
|
771
|
+
f"The `{func.__module__}.{func.__name__}` function "
|
|
772
|
+
"is not implemented by Dask array. "
|
|
773
|
+
"You may want to use the da.map_blocks function "
|
|
774
|
+
"or something similar to silence this warning. "
|
|
775
|
+
"Your code may stop working in a future release.",
|
|
776
|
+
FutureWarning,
|
|
777
|
+
)
|
|
778
|
+
# Need to convert to array object (e.g. numpy.ndarray or
|
|
779
|
+
# cupy.ndarray) as needed, so we can call the NumPy function
|
|
780
|
+
# again and it gets the chance to dispatch to the right
|
|
781
|
+
# implementation.
|
|
782
|
+
args, kwargs = compute(args, kwargs)
|
|
783
|
+
return func(*args, **kwargs)
|
|
784
|
+
|
|
785
|
+
return _HANDLED_FUNCTIONS[func](*args, **kwargs)
|
|
786
|
+
|
|
787
|
+
# First, verify that all types are handled by Dask. Otherwise, return NotImplemented.
|
|
788
|
+
if not all(
|
|
789
|
+
# Accept our own superclasses as recommended by NEP-13
|
|
790
|
+
# (https://numpy.org/neps/nep-0013-ufunc-overrides.html#subclass-hierarchies)
|
|
791
|
+
issubclass(type(self), type_) or is_valid_chunk_type(type_)
|
|
792
|
+
for type_ in types
|
|
793
|
+
):
|
|
794
|
+
return NotImplemented
|
|
795
|
+
|
|
796
|
+
# Now try to find a matching function name. If that doesn't work, we may
|
|
797
|
+
# be dealing with an alias or a function that's simply not in the Dask API.
|
|
798
|
+
# Handle aliases via the _HANDLED_FUNCTIONS dict mapping, and warn otherwise.
|
|
799
|
+
for submodule in func.__module__.split(".")[1:]:
|
|
800
|
+
try:
|
|
801
|
+
module = getattr(module, submodule)
|
|
802
|
+
except AttributeError:
|
|
803
|
+
return handle_nonmatching_names(func, args, kwargs)
|
|
804
|
+
|
|
805
|
+
if not hasattr(module, func.__name__):
|
|
806
|
+
return handle_nonmatching_names(func, args, kwargs)
|
|
807
|
+
|
|
808
|
+
da_func = getattr(module, func.__name__)
|
|
809
|
+
if da_func is func:
|
|
810
|
+
return handle_nonmatching_names(func, args, kwargs)
|
|
811
|
+
|
|
812
|
+
# If ``like`` is contained in ``da_func``'s signature, add ``like=self``
|
|
813
|
+
# to the kwargs dictionary.
|
|
814
|
+
if has_keyword(da_func, "like"):
|
|
815
|
+
kwargs["like"] = self
|
|
816
|
+
|
|
817
|
+
return da_func(*args, **kwargs)
|
|
818
|
+
|
|
819
|
+
def transpose(self, *axes):
|
|
820
|
+
from collections.abc import Iterable
|
|
821
|
+
|
|
822
|
+
if not axes:
|
|
823
|
+
axes = None
|
|
824
|
+
elif len(axes) == 1 and isinstance(axes[0], Iterable):
|
|
825
|
+
axes = axes[0]
|
|
826
|
+
|
|
827
|
+
if axes:
|
|
828
|
+
if len(axes) != self.ndim:
|
|
829
|
+
raise ValueError("axes don't match array")
|
|
830
|
+
axes = tuple(d + self.ndim if d < 0 else d for d in axes)
|
|
831
|
+
else:
|
|
832
|
+
axes = tuple(range(self.ndim))[::-1]
|
|
833
|
+
|
|
834
|
+
# Identity transpose - return self
|
|
835
|
+
if axes == tuple(range(self.ndim)):
|
|
836
|
+
return self
|
|
837
|
+
|
|
838
|
+
return new_collection(Transpose(self, axes))
|
|
839
|
+
|
|
840
|
+
@property
|
|
841
|
+
def T(self):
|
|
842
|
+
return self.transpose()
|
|
843
|
+
|
|
844
|
+
@property
|
|
845
|
+
def A(self):
|
|
846
|
+
return self
|
|
847
|
+
|
|
848
|
+
def swapaxes(self, axis1, axis2):
|
|
849
|
+
"""Interchange two axes of an array.
|
|
850
|
+
|
|
851
|
+
Refer to :func:`dask.array.swapaxes` for full documentation.
|
|
852
|
+
"""
|
|
853
|
+
return swapaxes(self, axis1, axis2)
|
|
854
|
+
|
|
855
|
+
def squeeze(self, axis=None):
|
|
856
|
+
"""Remove axes of length one from array.
|
|
857
|
+
|
|
858
|
+
Refer to :func:`dask.array.squeeze` for full documentation.
|
|
859
|
+
"""
|
|
860
|
+
return squeeze(self, axis=axis)
|
|
861
|
+
|
|
862
|
+
def reshape(self, *shape, merge_chunks=True, limit=None):
|
|
863
|
+
"""Reshape the array to a new shape.
|
|
864
|
+
|
|
865
|
+
Refer to :func:`dask.array.reshape` for full documentation.
|
|
866
|
+
"""
|
|
867
|
+
if len(shape) == 1 and isinstance(shape[0], (tuple, list)):
|
|
868
|
+
shape = shape[0]
|
|
869
|
+
return reshape(self, shape, merge_chunks=merge_chunks, limit=limit)
|
|
870
|
+
|
|
871
|
+
def flatten(self):
|
|
872
|
+
"""Return a copy of the array collapsed into one dimension.
|
|
873
|
+
|
|
874
|
+
Returns
|
|
875
|
+
-------
|
|
876
|
+
dask Array
|
|
877
|
+
A 1-D array with the same data as self.
|
|
878
|
+
"""
|
|
879
|
+
return reshape(self, (-1,))
|
|
880
|
+
|
|
881
|
+
def ravel(self):
|
|
882
|
+
"""Return a flattened array.
|
|
883
|
+
|
|
884
|
+
Returns
|
|
885
|
+
-------
|
|
886
|
+
dask Array
|
|
887
|
+
A 1-D array with the same data as self.
|
|
888
|
+
"""
|
|
889
|
+
return reshape(self, (-1,))
|
|
890
|
+
|
|
891
|
+
def repeat(self, repeats, axis=None):
|
|
892
|
+
"""Repeat elements of an array.
|
|
893
|
+
|
|
894
|
+
Refer to :func:`dask.array.repeat` for full documentation.
|
|
895
|
+
"""
|
|
896
|
+
from dask_array.creation import repeat
|
|
897
|
+
|
|
898
|
+
return repeat(self, repeats, axis)
|
|
899
|
+
|
|
900
|
+
def choose(self, choices):
|
|
901
|
+
"""Use an index array to construct a new array from a set of choices.
|
|
902
|
+
|
|
903
|
+
Refer to :func:`dask.array.choose` for full documentation.
|
|
904
|
+
|
|
905
|
+
See Also
|
|
906
|
+
--------
|
|
907
|
+
dask.array.choose : equivalent function
|
|
908
|
+
"""
|
|
909
|
+
from dask_array._routines import choose
|
|
910
|
+
|
|
911
|
+
return choose(self, choices)
|
|
912
|
+
|
|
913
|
+
def nonzero(self):
|
|
914
|
+
"""Return the indices of the elements that are non-zero.
|
|
915
|
+
|
|
916
|
+
Refer to :func:`dask.array.nonzero` for full documentation.
|
|
917
|
+
|
|
918
|
+
See Also
|
|
919
|
+
--------
|
|
920
|
+
dask.array.nonzero : equivalent function
|
|
921
|
+
"""
|
|
922
|
+
from dask_array._routines import nonzero
|
|
923
|
+
|
|
924
|
+
return nonzero(self)
|
|
925
|
+
|
|
926
|
+
def round(self, decimals=0):
|
|
927
|
+
"""Return array with each element rounded to the given number of decimals.
|
|
928
|
+
|
|
929
|
+
Refer to :func:`dask.array.round` for full documentation.
|
|
930
|
+
|
|
931
|
+
See Also
|
|
932
|
+
--------
|
|
933
|
+
dask.array.round : equivalent function
|
|
934
|
+
"""
|
|
935
|
+
from dask_array._routines import round
|
|
936
|
+
|
|
937
|
+
return round(self, decimals=decimals)
|
|
938
|
+
|
|
939
|
+
def rechunk(
|
|
940
|
+
self,
|
|
941
|
+
chunks="auto",
|
|
942
|
+
threshold=None,
|
|
943
|
+
block_size_limit=None,
|
|
944
|
+
balance=False,
|
|
945
|
+
method=None,
|
|
946
|
+
):
|
|
947
|
+
return rechunk(self, chunks, threshold, block_size_limit, balance, method)
|
|
948
|
+
|
|
949
|
+
def shuffle(self, indexer, axis, chunks="auto"):
|
|
950
|
+
from dask_array._shuffle import shuffle
|
|
951
|
+
|
|
952
|
+
return shuffle(self, indexer, axis, chunks)
|
|
953
|
+
|
|
954
|
+
def _vindex(self, key):
|
|
955
|
+
from dask_array.slicing import _numpy_vindex, _vindex
|
|
956
|
+
from dask.base import is_dask_collection
|
|
957
|
+
|
|
958
|
+
if not isinstance(key, tuple):
|
|
959
|
+
key = (key,)
|
|
960
|
+
if any(k is None for k in key):
|
|
961
|
+
raise IndexError(f"vindex does not support indexing with None (np.newaxis), got {key}")
|
|
962
|
+
if all(isinstance(k, slice) for k in key):
|
|
963
|
+
if all(k.indices(d) == slice(0, d).indices(d) for k, d in zip(key, self.shape)):
|
|
964
|
+
return self
|
|
965
|
+
raise IndexError(
|
|
966
|
+
"vindex requires at least one non-slice to vectorize over "
|
|
967
|
+
"when the slices are not over the entire array (i.e, x[:]). "
|
|
968
|
+
f"Use normal slicing instead when only using slices. Got: {key}"
|
|
969
|
+
)
|
|
970
|
+
elif any(is_dask_collection(k) for k in key):
|
|
971
|
+
if math.prod(self.numblocks) == 1 and len(key) == 1 and self.ndim == 1:
|
|
972
|
+
idxr = key[0]
|
|
973
|
+
# we can broadcast in this case
|
|
974
|
+
return idxr.map_blocks(_numpy_vindex, self, dtype=self.dtype, chunks=idxr.chunks)
|
|
975
|
+
else:
|
|
976
|
+
raise IndexError(
|
|
977
|
+
"vindex does not support indexing with dask objects. Call compute "
|
|
978
|
+
f"on the indexer first to get an evalurated array. Got: {key}"
|
|
979
|
+
)
|
|
980
|
+
return _vindex(self, *key)
|
|
981
|
+
|
|
982
|
+
@property
|
|
983
|
+
def vindex(self):
|
|
984
|
+
"""Vectorized indexing with broadcasting.
|
|
985
|
+
|
|
986
|
+
This is equivalent to numpy's advanced indexing, using arrays that are
|
|
987
|
+
broadcast against each other. This allows for pointwise indexing:
|
|
988
|
+
|
|
989
|
+
>>> import dask_array as da
|
|
990
|
+
>>> x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
|
|
991
|
+
>>> x = da.from_array(x, chunks=2)
|
|
992
|
+
>>> x.vindex[[0, 1, 2], [0, 1, 2]].compute()
|
|
993
|
+
array([1, 5, 9])
|
|
994
|
+
|
|
995
|
+
Mixed basic/advanced indexing with slices/arrays is also supported. The
|
|
996
|
+
order of dimensions in the result follows those proposed for
|
|
997
|
+
`ndarray.vindex <https://github.com/numpy/numpy/pull/6256>`_:
|
|
998
|
+
the subspace spanned by arrays is followed by all slices.
|
|
999
|
+
|
|
1000
|
+
Note: ``vindex`` provides more general functionality than standard
|
|
1001
|
+
indexing, but it also has fewer optimizations and can be significantly
|
|
1002
|
+
slower.
|
|
1003
|
+
"""
|
|
1004
|
+
from dask.utils import IndexCallable
|
|
1005
|
+
|
|
1006
|
+
return IndexCallable(self._vindex)
|
|
1007
|
+
|
|
1008
|
+
def store(self, target, **kwargs):
|
|
1009
|
+
"""Store array in array-like object.
|
|
1010
|
+
|
|
1011
|
+
Refer to :func:`dask.array.store` for full documentation.
|
|
1012
|
+
"""
|
|
1013
|
+
from dask_array.io import store
|
|
1014
|
+
|
|
1015
|
+
return store([self], [target], **kwargs)
|
|
1016
|
+
|
|
1017
|
+
def to_zarr(self, *args, **kwargs):
|
|
1018
|
+
"""Save array to the zarr storage format
|
|
1019
|
+
|
|
1020
|
+
See https://zarr.readthedocs.io for details about the format.
|
|
1021
|
+
|
|
1022
|
+
Refer to :func:`dask.array.to_zarr` for full documentation.
|
|
1023
|
+
|
|
1024
|
+
See also
|
|
1025
|
+
--------
|
|
1026
|
+
dask.array.to_zarr : equivalent function
|
|
1027
|
+
"""
|
|
1028
|
+
from dask_array.io import to_zarr
|
|
1029
|
+
|
|
1030
|
+
return to_zarr(self, *args, **kwargs)
|
|
1031
|
+
|
|
1032
|
+
def to_tiledb(self, uri, *args, **kwargs):
|
|
1033
|
+
"""Save array to the TileDB storage manager
|
|
1034
|
+
|
|
1035
|
+
See https://docs.tiledb.io for details about the format and engine.
|
|
1036
|
+
|
|
1037
|
+
Refer to :func:`dask.array.to_tiledb` for full documentation.
|
|
1038
|
+
|
|
1039
|
+
See also
|
|
1040
|
+
--------
|
|
1041
|
+
dask.array.to_tiledb : equivalent function
|
|
1042
|
+
"""
|
|
1043
|
+
from dask_array.io._tiledb import to_tiledb
|
|
1044
|
+
|
|
1045
|
+
return to_tiledb(self, uri, *args, **kwargs)
|
|
1046
|
+
|
|
1047
|
+
def to_hdf5(self, filename, datapath, **kwargs):
|
|
1048
|
+
"""Store array in HDF5 file
|
|
1049
|
+
|
|
1050
|
+
>>> x.to_hdf5('myfile.hdf5', '/x') # doctest: +SKIP
|
|
1051
|
+
|
|
1052
|
+
Optionally provide arguments as though to ``h5py.File.create_dataset``
|
|
1053
|
+
|
|
1054
|
+
>>> x.to_hdf5('myfile.hdf5', '/x', compression='lzf', shuffle=True) # doctest: +SKIP
|
|
1055
|
+
|
|
1056
|
+
See Also
|
|
1057
|
+
--------
|
|
1058
|
+
dask_array.to_hdf5
|
|
1059
|
+
h5py.File.create_dataset
|
|
1060
|
+
"""
|
|
1061
|
+
from dask_array.io._store import to_hdf5
|
|
1062
|
+
|
|
1063
|
+
return to_hdf5(filename, datapath, self, **kwargs)
|
|
1064
|
+
|
|
1065
|
+
def to_backend(self, backend: str | None = None, **kwargs):
|
|
1066
|
+
"""Move to a new Array backend
|
|
1067
|
+
|
|
1068
|
+
Parameters
|
|
1069
|
+
----------
|
|
1070
|
+
backend : str, Optional
|
|
1071
|
+
The name of the new backend to move to. The default
|
|
1072
|
+
is the current "array.backend" configuration.
|
|
1073
|
+
|
|
1074
|
+
Returns
|
|
1075
|
+
-------
|
|
1076
|
+
Array
|
|
1077
|
+
"""
|
|
1078
|
+
from dask_array.creation._utils import to_backend
|
|
1079
|
+
|
|
1080
|
+
return to_backend(self, backend=backend, **kwargs) # type: ignore[arg-type]
|
|
1081
|
+
|
|
1082
|
+
def to_svg(self, size=500):
|
|
1083
|
+
"""Convert chunks from Dask Array into an SVG Image
|
|
1084
|
+
|
|
1085
|
+
Parameters
|
|
1086
|
+
----------
|
|
1087
|
+
size : int
|
|
1088
|
+
Rough size of the image
|
|
1089
|
+
|
|
1090
|
+
Returns
|
|
1091
|
+
-------
|
|
1092
|
+
str
|
|
1093
|
+
An svg string depicting the array as a grid of chunks
|
|
1094
|
+
"""
|
|
1095
|
+
from dask_array._svg import svg
|
|
1096
|
+
|
|
1097
|
+
return svg(self.chunks, size=size)
|
|
1098
|
+
|
|
1099
|
+
def copy(self):
|
|
1100
|
+
"""Copy array. This is a no-op for dask arrays, which are immutable."""
|
|
1101
|
+
return Array(self._expr)
|
|
1102
|
+
|
|
1103
|
+
def __deepcopy__(self, memo):
|
|
1104
|
+
c = self.copy()
|
|
1105
|
+
memo[id(self)] = c
|
|
1106
|
+
return c
|
|
1107
|
+
|
|
1108
|
+
def to_delayed(self, optimize_graph=True):
|
|
1109
|
+
"""Convert into an array of :class:`dask.delayed.Delayed` objects, one per chunk.
|
|
1110
|
+
|
|
1111
|
+
Parameters
|
|
1112
|
+
----------
|
|
1113
|
+
optimize_graph : bool, optional
|
|
1114
|
+
If True [default], the graph is optimized before converting into
|
|
1115
|
+
:class:`dask.delayed.Delayed` objects.
|
|
1116
|
+
|
|
1117
|
+
See Also
|
|
1118
|
+
--------
|
|
1119
|
+
dask.array.from_delayed
|
|
1120
|
+
"""
|
|
1121
|
+
from dask.delayed import Delayed
|
|
1122
|
+
from dask.utils import ndeepmap
|
|
1123
|
+
|
|
1124
|
+
keys = self.__dask_keys__()
|
|
1125
|
+
graph = self.__dask_graph__()
|
|
1126
|
+
if optimize_graph:
|
|
1127
|
+
graph = self.__dask_optimize__(graph, keys)
|
|
1128
|
+
L = ndeepmap(self.ndim, lambda k: Delayed(k, graph), keys)
|
|
1129
|
+
return np.array(L, dtype=object)
|
|
1130
|
+
|
|
1131
|
+
def to_dask_dataframe(self, columns=None, index=None, meta=None):
|
|
1132
|
+
"""Convert dask Array to dask Dataframe
|
|
1133
|
+
|
|
1134
|
+
Parameters
|
|
1135
|
+
----------
|
|
1136
|
+
columns: list or string
|
|
1137
|
+
list of column names if DataFrame, single string if Series
|
|
1138
|
+
index : dask.dataframe.Index, optional
|
|
1139
|
+
An optional *dask* Index to use for the output Series or DataFrame.
|
|
1140
|
+
|
|
1141
|
+
The default output index depends on whether the array has any unknown
|
|
1142
|
+
chunks. If there are any unknown chunks, the output has ``None``
|
|
1143
|
+
for all the divisions (one per chunk). If all the chunks are known,
|
|
1144
|
+
a default index with known divisions is created.
|
|
1145
|
+
|
|
1146
|
+
Specifying ``index`` can be useful if you're conforming a Dask Array
|
|
1147
|
+
to an existing dask Series or DataFrame, and you would like the
|
|
1148
|
+
indices to match.
|
|
1149
|
+
meta : object, optional
|
|
1150
|
+
An optional `meta` parameter can be passed for dask
|
|
1151
|
+
to specify the concrete dataframe type to use for partitions of
|
|
1152
|
+
the Dask dataframe. By default, pandas DataFrame is used.
|
|
1153
|
+
|
|
1154
|
+
See Also
|
|
1155
|
+
--------
|
|
1156
|
+
dask.dataframe.from_dask_array
|
|
1157
|
+
"""
|
|
1158
|
+
from dask.dataframe.dask_expr._array import from_dask_array_expr
|
|
1159
|
+
|
|
1160
|
+
return from_dask_array_expr(self, columns=columns, index=index, meta=meta)
|
|
1161
|
+
|
|
1162
|
+
def sum(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None):
|
|
1163
|
+
"""
|
|
1164
|
+
Return the sum of the array elements over the given axis.
|
|
1165
|
+
|
|
1166
|
+
Refer to :func:`dask.array.sum` for full documentation.
|
|
1167
|
+
|
|
1168
|
+
See Also
|
|
1169
|
+
--------
|
|
1170
|
+
dask.array.sum : equivalent function
|
|
1171
|
+
"""
|
|
1172
|
+
from dask_array.reductions import sum
|
|
1173
|
+
|
|
1174
|
+
return sum(
|
|
1175
|
+
self,
|
|
1176
|
+
axis=axis,
|
|
1177
|
+
dtype=dtype,
|
|
1178
|
+
keepdims=keepdims,
|
|
1179
|
+
split_every=split_every,
|
|
1180
|
+
out=out,
|
|
1181
|
+
)
|
|
1182
|
+
|
|
1183
|
+
def mean(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None):
|
|
1184
|
+
"""Returns the average of the array elements along given axis.
|
|
1185
|
+
|
|
1186
|
+
Refer to :func:`dask.array.mean` for full documentation.
|
|
1187
|
+
|
|
1188
|
+
See Also
|
|
1189
|
+
--------
|
|
1190
|
+
dask.array.mean : equivalent function
|
|
1191
|
+
"""
|
|
1192
|
+
from dask_array.reductions import mean
|
|
1193
|
+
|
|
1194
|
+
return mean(
|
|
1195
|
+
self,
|
|
1196
|
+
axis=axis,
|
|
1197
|
+
dtype=dtype,
|
|
1198
|
+
keepdims=keepdims,
|
|
1199
|
+
split_every=split_every,
|
|
1200
|
+
out=out,
|
|
1201
|
+
)
|
|
1202
|
+
|
|
1203
|
+
def std(self, axis=None, dtype=None, keepdims=False, ddof=0, split_every=None, out=None):
|
|
1204
|
+
"""Returns the standard deviation of the array elements along given axis.
|
|
1205
|
+
|
|
1206
|
+
Refer to :func:`dask.array.std` for full documentation.
|
|
1207
|
+
|
|
1208
|
+
See Also
|
|
1209
|
+
--------
|
|
1210
|
+
dask.array.std : equivalent function
|
|
1211
|
+
"""
|
|
1212
|
+
from dask_array.reductions import std
|
|
1213
|
+
|
|
1214
|
+
return std(
|
|
1215
|
+
self,
|
|
1216
|
+
axis=axis,
|
|
1217
|
+
dtype=dtype,
|
|
1218
|
+
keepdims=keepdims,
|
|
1219
|
+
ddof=ddof,
|
|
1220
|
+
split_every=split_every,
|
|
1221
|
+
out=out,
|
|
1222
|
+
)
|
|
1223
|
+
|
|
1224
|
+
def var(self, axis=None, dtype=None, keepdims=False, ddof=0, split_every=None, out=None):
|
|
1225
|
+
"""Returns the variance of the array elements, along given axis.
|
|
1226
|
+
|
|
1227
|
+
Refer to :func:`dask.array.var` for full documentation.
|
|
1228
|
+
|
|
1229
|
+
See Also
|
|
1230
|
+
--------
|
|
1231
|
+
dask.array.var : equivalent function
|
|
1232
|
+
"""
|
|
1233
|
+
from dask_array.reductions import var
|
|
1234
|
+
|
|
1235
|
+
return var(
|
|
1236
|
+
self,
|
|
1237
|
+
axis=axis,
|
|
1238
|
+
dtype=dtype,
|
|
1239
|
+
keepdims=keepdims,
|
|
1240
|
+
ddof=ddof,
|
|
1241
|
+
split_every=split_every,
|
|
1242
|
+
out=out,
|
|
1243
|
+
)
|
|
1244
|
+
|
|
1245
|
+
def moment(
|
|
1246
|
+
self,
|
|
1247
|
+
order,
|
|
1248
|
+
axis=None,
|
|
1249
|
+
dtype=None,
|
|
1250
|
+
keepdims=False,
|
|
1251
|
+
ddof=0,
|
|
1252
|
+
split_every=None,
|
|
1253
|
+
out=None,
|
|
1254
|
+
):
|
|
1255
|
+
"""Calculate the nth centralized moment.
|
|
1256
|
+
|
|
1257
|
+
Refer to :func:`dask.array.moment` for the full documentation.
|
|
1258
|
+
|
|
1259
|
+
See Also
|
|
1260
|
+
--------
|
|
1261
|
+
dask.array.moment : equivalent function
|
|
1262
|
+
"""
|
|
1263
|
+
from dask_array.reductions import moment
|
|
1264
|
+
|
|
1265
|
+
return moment(
|
|
1266
|
+
self,
|
|
1267
|
+
order,
|
|
1268
|
+
axis=axis,
|
|
1269
|
+
dtype=dtype,
|
|
1270
|
+
keepdims=keepdims,
|
|
1271
|
+
ddof=ddof,
|
|
1272
|
+
split_every=split_every,
|
|
1273
|
+
out=out,
|
|
1274
|
+
)
|
|
1275
|
+
|
|
1276
|
+
def prod(self, axis=None, dtype=None, keepdims=False, split_every=None, out=None):
|
|
1277
|
+
"""Return the product of the array elements over the given axis
|
|
1278
|
+
|
|
1279
|
+
Refer to :func:`dask.array.prod` for full documentation.
|
|
1280
|
+
|
|
1281
|
+
See Also
|
|
1282
|
+
--------
|
|
1283
|
+
dask.array.prod : equivalent function
|
|
1284
|
+
"""
|
|
1285
|
+
from dask_array.reductions import prod
|
|
1286
|
+
|
|
1287
|
+
return prod(
|
|
1288
|
+
self,
|
|
1289
|
+
axis=axis,
|
|
1290
|
+
dtype=dtype,
|
|
1291
|
+
keepdims=keepdims,
|
|
1292
|
+
split_every=split_every,
|
|
1293
|
+
out=out,
|
|
1294
|
+
)
|
|
1295
|
+
|
|
1296
|
+
def any(self, axis=None, keepdims=False, split_every=None, out=None):
|
|
1297
|
+
"""Returns True if any of the elements evaluate to True.
|
|
1298
|
+
|
|
1299
|
+
Refer to :func:`dask.array.any` for full documentation.
|
|
1300
|
+
|
|
1301
|
+
See Also
|
|
1302
|
+
--------
|
|
1303
|
+
dask.array.any : equivalent function
|
|
1304
|
+
"""
|
|
1305
|
+
from dask_array.reductions import any
|
|
1306
|
+
|
|
1307
|
+
return any(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
|
|
1308
|
+
|
|
1309
|
+
def all(self, axis=None, keepdims=False, split_every=None, out=None):
|
|
1310
|
+
"""Returns True if all elements evaluate to True.
|
|
1311
|
+
|
|
1312
|
+
Refer to :func:`dask.array.all` for full documentation.
|
|
1313
|
+
|
|
1314
|
+
See Also
|
|
1315
|
+
--------
|
|
1316
|
+
dask.array.all : equivalent function
|
|
1317
|
+
"""
|
|
1318
|
+
from dask_array.reductions import all
|
|
1319
|
+
|
|
1320
|
+
return all(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
|
|
1321
|
+
|
|
1322
|
+
def min(self, axis=None, keepdims=False, split_every=None, out=None):
|
|
1323
|
+
"""Return the minimum along a given axis.
|
|
1324
|
+
|
|
1325
|
+
Refer to :func:`dask.array.min` for full documentation.
|
|
1326
|
+
|
|
1327
|
+
See Also
|
|
1328
|
+
--------
|
|
1329
|
+
dask.array.min : equivalent function
|
|
1330
|
+
"""
|
|
1331
|
+
from dask_array.reductions import min
|
|
1332
|
+
|
|
1333
|
+
return min(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
|
|
1334
|
+
|
|
1335
|
+
def max(self, axis=None, keepdims=False, split_every=None, out=None):
|
|
1336
|
+
"""Return the maximum along a given axis.
|
|
1337
|
+
|
|
1338
|
+
Refer to :func:`dask.array.max` for full documentation.
|
|
1339
|
+
|
|
1340
|
+
See Also
|
|
1341
|
+
--------
|
|
1342
|
+
dask.array.max : equivalent function
|
|
1343
|
+
"""
|
|
1344
|
+
from dask_array.reductions import max
|
|
1345
|
+
|
|
1346
|
+
return max(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
|
|
1347
|
+
|
|
1348
|
+
def argmin(self, axis=None, *, keepdims=False, split_every=None, out=None):
|
|
1349
|
+
"""Return indices of the minimum values along the given axis.
|
|
1350
|
+
|
|
1351
|
+
Refer to :func:`dask.array.argmin` for full documentation.
|
|
1352
|
+
|
|
1353
|
+
See Also
|
|
1354
|
+
--------
|
|
1355
|
+
dask.array.argmin : equivalent function
|
|
1356
|
+
"""
|
|
1357
|
+
from dask_array.reductions import argmin
|
|
1358
|
+
|
|
1359
|
+
return argmin(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
|
|
1360
|
+
|
|
1361
|
+
def argmax(self, axis=None, *, keepdims=False, split_every=None, out=None):
|
|
1362
|
+
"""Return indices of the maximum values along the given axis.
|
|
1363
|
+
|
|
1364
|
+
Refer to :func:`dask.array.argmax` for full documentation.
|
|
1365
|
+
|
|
1366
|
+
See Also
|
|
1367
|
+
--------
|
|
1368
|
+
dask.array.argmax : equivalent function
|
|
1369
|
+
"""
|
|
1370
|
+
from dask_array.reductions import argmax
|
|
1371
|
+
|
|
1372
|
+
return argmax(self, axis=axis, keepdims=keepdims, split_every=split_every, out=out)
|
|
1373
|
+
|
|
1374
|
+
def topk(self, k, axis=-1, split_every=None):
|
|
1375
|
+
"""The top k elements of an array.
|
|
1376
|
+
|
|
1377
|
+
Refer to :func:`dask.array.topk` for full documentation.
|
|
1378
|
+
|
|
1379
|
+
See Also
|
|
1380
|
+
--------
|
|
1381
|
+
dask.array.topk : equivalent function
|
|
1382
|
+
"""
|
|
1383
|
+
from dask_array._routines import topk
|
|
1384
|
+
|
|
1385
|
+
return topk(self, k, axis=axis, split_every=split_every)
|
|
1386
|
+
|
|
1387
|
+
def argtopk(self, k, axis=-1, split_every=None):
|
|
1388
|
+
"""The indices of the top k elements of an array.
|
|
1389
|
+
|
|
1390
|
+
Refer to :func:`dask.array.argtopk` for full documentation.
|
|
1391
|
+
|
|
1392
|
+
See Also
|
|
1393
|
+
--------
|
|
1394
|
+
dask.array.argtopk : equivalent function
|
|
1395
|
+
"""
|
|
1396
|
+
from dask_array._routines import argtopk
|
|
1397
|
+
|
|
1398
|
+
return argtopk(self, k, axis=axis, split_every=split_every)
|
|
1399
|
+
|
|
1400
|
+
def cumsum(self, axis, dtype=None, out=None, *, method="sequential"):
|
|
1401
|
+
"""Return the cumulative sum of the elements along the given axis.
|
|
1402
|
+
|
|
1403
|
+
Refer to :func:`dask.array.cumsum` for full documentation.
|
|
1404
|
+
|
|
1405
|
+
See Also
|
|
1406
|
+
--------
|
|
1407
|
+
dask.array.cumsum : equivalent function
|
|
1408
|
+
"""
|
|
1409
|
+
from dask_array.reductions import cumsum
|
|
1410
|
+
|
|
1411
|
+
return cumsum(self, axis=axis, dtype=dtype, out=out, method=method)
|
|
1412
|
+
|
|
1413
|
+
def cumprod(self, axis, dtype=None, out=None, *, method="sequential"):
|
|
1414
|
+
"""Return the cumulative product of the elements along the given axis.
|
|
1415
|
+
|
|
1416
|
+
Refer to :func:`dask.array.cumprod` for full documentation.
|
|
1417
|
+
|
|
1418
|
+
See Also
|
|
1419
|
+
--------
|
|
1420
|
+
dask.array.cumprod : equivalent function
|
|
1421
|
+
"""
|
|
1422
|
+
from dask_array.reductions import cumprod
|
|
1423
|
+
|
|
1424
|
+
return cumprod(self, axis=axis, dtype=dtype, out=out, method=method)
|
|
1425
|
+
|
|
1426
|
+
def trace(self, offset=0, axis1=0, axis2=1, dtype=None):
|
|
1427
|
+
"""Return the sum along diagonals of the array.
|
|
1428
|
+
|
|
1429
|
+
Refer to :func:`dask.array.trace` for full documentation.
|
|
1430
|
+
|
|
1431
|
+
See Also
|
|
1432
|
+
--------
|
|
1433
|
+
dask.array.trace : equivalent function
|
|
1434
|
+
"""
|
|
1435
|
+
from dask_array.reductions import trace
|
|
1436
|
+
|
|
1437
|
+
return trace(self, offset=offset, axis1=axis1, axis2=axis2, dtype=dtype)
|
|
1438
|
+
|
|
1439
|
+
def dot(self, other):
|
|
1440
|
+
"""Dot product of self and other.
|
|
1441
|
+
|
|
1442
|
+
Refer to :func:`dask.array.tensordot` for full documentation.
|
|
1443
|
+
|
|
1444
|
+
See Also
|
|
1445
|
+
--------
|
|
1446
|
+
dask.array.dot : equivalent function
|
|
1447
|
+
"""
|
|
1448
|
+
from dask_array.linalg import tensordot
|
|
1449
|
+
|
|
1450
|
+
return tensordot(self, other, axes=((self.ndim - 1,), (other.ndim - 2,)))
|
|
1451
|
+
|
|
1452
|
+
def astype(self, dtype, **kwargs):
|
|
1453
|
+
"""Copy of the array, cast to a specified type.
|
|
1454
|
+
|
|
1455
|
+
Parameters
|
|
1456
|
+
----------
|
|
1457
|
+
dtype : str or dtype
|
|
1458
|
+
Typecode or data-type to which the array is cast.
|
|
1459
|
+
casting : {'no', 'equiv', 'safe', 'same_kind', 'unsafe'}, optional
|
|
1460
|
+
Controls what kind of data casting may occur. Defaults to 'unsafe'
|
|
1461
|
+
for backwards compatibility.
|
|
1462
|
+
|
|
1463
|
+
* 'no' means the data types should not be cast at all.
|
|
1464
|
+
* 'equiv' means only byte-order changes are allowed.
|
|
1465
|
+
* 'safe' means only casts which can preserve values are allowed.
|
|
1466
|
+
* 'same_kind' means only safe casts or casts within a kind,
|
|
1467
|
+
like float64 to float32, are allowed.
|
|
1468
|
+
* 'unsafe' means any data conversions may be done.
|
|
1469
|
+
copy : bool, optional
|
|
1470
|
+
By default, astype always returns a newly allocated array. If this
|
|
1471
|
+
is set to False and the `dtype` requirement is satisfied, the input
|
|
1472
|
+
array is returned instead of a copy.
|
|
1473
|
+
|
|
1474
|
+
.. note::
|
|
1475
|
+
|
|
1476
|
+
Dask does not respect the contiguous memory layout of the array,
|
|
1477
|
+
and will ignore the ``order`` keyword argument.
|
|
1478
|
+
The default order is 'C' contiguous.
|
|
1479
|
+
"""
|
|
1480
|
+
kwargs.pop("order", None) # `order` is not respected, so we remove this kwarg
|
|
1481
|
+
# Scalars don't take `casting` or `copy` kwargs - as such we only pass
|
|
1482
|
+
# them to `map_blocks` if specified by user (different than defaults).
|
|
1483
|
+
extra = set(kwargs) - {"casting", "copy"}
|
|
1484
|
+
if extra:
|
|
1485
|
+
raise TypeError(f"astype does not take the following keyword arguments: {list(extra)}")
|
|
1486
|
+
casting = kwargs.get("casting", "unsafe")
|
|
1487
|
+
dtype = np.dtype(dtype)
|
|
1488
|
+
if self.dtype == dtype:
|
|
1489
|
+
return self
|
|
1490
|
+
elif not np.can_cast(self.dtype, dtype, casting=casting):
|
|
1491
|
+
raise TypeError(f"Cannot cast array from {self.dtype!r} to {dtype!r} according to the rule {casting!r}")
|
|
1492
|
+
return elemwise(chunk.astype, self, dtype=dtype, astype_dtype=dtype, **kwargs)
|
|
1493
|
+
|
|
1494
|
+
def map_blocks(self, func, *args, **kwargs):
|
|
1495
|
+
from dask_array._map_blocks import map_blocks
|
|
1496
|
+
|
|
1497
|
+
return map_blocks(func, self, *args, **kwargs)
|
|
1498
|
+
|
|
1499
|
+
@property
|
|
1500
|
+
def _elemwise(self):
|
|
1501
|
+
return elemwise
|
|
1502
|
+
|
|
1503
|
+
@property
|
|
1504
|
+
def real(self):
|
|
1505
|
+
from dask_array._ufunc import real
|
|
1506
|
+
|
|
1507
|
+
return real(self)
|
|
1508
|
+
|
|
1509
|
+
@property
|
|
1510
|
+
def imag(self):
|
|
1511
|
+
from dask_array._ufunc import imag
|
|
1512
|
+
|
|
1513
|
+
return imag(self)
|
|
1514
|
+
|
|
1515
|
+
def conj(self):
|
|
1516
|
+
"""Complex-conjugate all elements.
|
|
1517
|
+
|
|
1518
|
+
Refer to :func:`dask.array.conj` for full documentation.
|
|
1519
|
+
|
|
1520
|
+
See Also
|
|
1521
|
+
--------
|
|
1522
|
+
dask.array.conj : equivalent function
|
|
1523
|
+
"""
|
|
1524
|
+
from dask_array._ufunc import conj
|
|
1525
|
+
|
|
1526
|
+
return conj(self)
|
|
1527
|
+
|
|
1528
|
+
def clip(self, min=None, max=None):
|
|
1529
|
+
"""Return an array whose values are limited to ``[min, max]``.
|
|
1530
|
+
One of max or min must be given.
|
|
1531
|
+
|
|
1532
|
+
Refer to :func:`dask.array.clip` for full documentation.
|
|
1533
|
+
|
|
1534
|
+
See Also
|
|
1535
|
+
--------
|
|
1536
|
+
dask.array.clip : equivalent function
|
|
1537
|
+
"""
|
|
1538
|
+
from dask_array._ufunc import clip
|
|
1539
|
+
|
|
1540
|
+
return clip(self, min, max)
|
|
1541
|
+
|
|
1542
|
+
def view(self, dtype=None, order="C"):
|
|
1543
|
+
"""Get a view of the array as a new data type
|
|
1544
|
+
|
|
1545
|
+
Parameters
|
|
1546
|
+
----------
|
|
1547
|
+
dtype:
|
|
1548
|
+
The dtype by which to view the array.
|
|
1549
|
+
The default, None, results in the view having the same data-type
|
|
1550
|
+
as the original array.
|
|
1551
|
+
order: string
|
|
1552
|
+
'C' or 'F' (Fortran) ordering
|
|
1553
|
+
|
|
1554
|
+
This reinterprets the bytes of the array under a new dtype. If that
|
|
1555
|
+
dtype does not have the same size as the original array then the shape
|
|
1556
|
+
will change.
|
|
1557
|
+
|
|
1558
|
+
Beware that both numpy and dask.array can behave oddly when taking
|
|
1559
|
+
shape-changing views of arrays under Fortran ordering. Under some
|
|
1560
|
+
versions of NumPy this function will fail when taking shape-changing
|
|
1561
|
+
views of Fortran ordered arrays if the first dimension has chunks of
|
|
1562
|
+
size one.
|
|
1563
|
+
"""
|
|
1564
|
+
if dtype is None:
|
|
1565
|
+
dtype = self.dtype
|
|
1566
|
+
else:
|
|
1567
|
+
dtype = np.dtype(dtype)
|
|
1568
|
+
mult = self.dtype.itemsize / dtype.itemsize
|
|
1569
|
+
|
|
1570
|
+
def _ensure_int(f):
|
|
1571
|
+
i = int(f)
|
|
1572
|
+
if i != f:
|
|
1573
|
+
raise ValueError(f"Could not coerce {f:f} to integer")
|
|
1574
|
+
return i
|
|
1575
|
+
|
|
1576
|
+
if order == "C":
|
|
1577
|
+
chunks = self.chunks[:-1] + (tuple(_ensure_int(c * mult) for c in self.chunks[-1]),)
|
|
1578
|
+
elif order == "F":
|
|
1579
|
+
chunks = (tuple(_ensure_int(c * mult) for c in self.chunks[0]),) + self.chunks[1:]
|
|
1580
|
+
else:
|
|
1581
|
+
raise ValueError("Order must be one of 'C' or 'F'")
|
|
1582
|
+
|
|
1583
|
+
return self.map_blocks(chunk.view, dtype, order=order, dtype=dtype, chunks=chunks)
|
|
1584
|
+
|
|
1585
|
+
def __array_ufunc__(self, numpy_ufunc, method, *inputs, **kwargs):
|
|
1586
|
+
out = kwargs.get("out", ())
|
|
1587
|
+
for x in inputs + out:
|
|
1588
|
+
if _should_delegate(self, x):
|
|
1589
|
+
return NotImplemented
|
|
1590
|
+
|
|
1591
|
+
if method == "__call__":
|
|
1592
|
+
if numpy_ufunc is np.matmul:
|
|
1593
|
+
from dask_array.linalg import matmul
|
|
1594
|
+
|
|
1595
|
+
# special case until apply_gufunc handles optional dimensions
|
|
1596
|
+
return matmul(*inputs, **kwargs)
|
|
1597
|
+
if numpy_ufunc.signature is not None:
|
|
1598
|
+
from dask_array._gufunc import apply_gufunc
|
|
1599
|
+
|
|
1600
|
+
return apply_gufunc(numpy_ufunc, numpy_ufunc.signature, *inputs, **kwargs)
|
|
1601
|
+
if numpy_ufunc.nout > 1:
|
|
1602
|
+
from dask_array import _ufunc as ufunc
|
|
1603
|
+
|
|
1604
|
+
try:
|
|
1605
|
+
da_ufunc = getattr(ufunc, numpy_ufunc.__name__)
|
|
1606
|
+
except AttributeError:
|
|
1607
|
+
return NotImplemented
|
|
1608
|
+
return da_ufunc(*inputs, **kwargs)
|
|
1609
|
+
else:
|
|
1610
|
+
return elemwise(numpy_ufunc, *inputs, **kwargs)
|
|
1611
|
+
elif method == "outer":
|
|
1612
|
+
from dask_array import _ufunc as ufunc
|
|
1613
|
+
|
|
1614
|
+
try:
|
|
1615
|
+
da_ufunc = getattr(ufunc, numpy_ufunc.__name__)
|
|
1616
|
+
except AttributeError:
|
|
1617
|
+
return NotImplemented
|
|
1618
|
+
return da_ufunc.outer(*inputs, **kwargs)
|
|
1619
|
+
else:
|
|
1620
|
+
return NotImplemented
|
|
1621
|
+
|
|
1622
|
+
def map_overlap(self, func, depth, boundary=None, trim=True, **kwargs):
|
|
1623
|
+
"""Map a function over blocks of the array with some overlap
|
|
1624
|
+
|
|
1625
|
+
Refer to :func:`dask.array.map_overlap` for full documentation.
|
|
1626
|
+
|
|
1627
|
+
See Also
|
|
1628
|
+
--------
|
|
1629
|
+
dask.array.map_overlap : equivalent function
|
|
1630
|
+
"""
|
|
1631
|
+
from dask_array._overlap import map_overlap
|
|
1632
|
+
|
|
1633
|
+
return map_overlap(func, self, depth=depth, boundary=boundary, trim=trim, **kwargs)
|
|
1634
|
+
|
|
1635
|
+
|
|
1636
|
+
# Import rechunk, reshape, ravel from their modules
|
|
1637
|
+
from dask_array._rechunk import rechunk
|
|
1638
|
+
from dask_array._reshape import ravel, reshape, reshape_blockwise
|
|
1639
|
+
|
|
1640
|
+
# Import swapaxes
|
|
1641
|
+
from dask_array.manipulation._transpose import swapaxes
|
|
1642
|
+
|
|
1643
|
+
# Import squeeze from its module
|
|
1644
|
+
from dask_array.slicing import squeeze
|