-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add to_numpy() and as_numpy() methods #5568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 27 commits
17c5755
48ba107
ae6e931
dc24d3f
6ce6b05
04d7b02
ee34649
552b322
1215e69
af8a1ee
e095bf0
eb7d84d
74c05e3
45245d0
27fc4e5
3e8cb24
f9d6370
50fdf4c
1c94a97
2d07c0f
9673cea
0d624cc
2f1ff46
afd35e2
6d33b35
eae95f5
b90b7e3
f39b301
8b346d3
576ab7b
4ed1dd8
976f89a
7bc5d6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,63 @@ | ||
from distutils.version import LooseVersion | ||
from importlib import import_module | ||
|
||
import numpy as np | ||
|
||
from .utils import is_duck_array | ||
|
||
integer_types = (int, np.integer) | ||
|
||
try: | ||
import dask | ||
import dask.array | ||
from dask.base import is_dask_collection | ||
|
||
dask_version = LooseVersion(dask.__version__) | ||
class DuckArrayModule: | ||
""" | ||
Solely for internal isinstance and version checks. | ||
|
||
# solely for isinstance checks | ||
dask_array_type = (dask.array.Array,) | ||
Motivated by having to only import pint when required (as pint currently imports xarray) | ||
https://github.com/pydata/xarray/pull/5561#discussion_r664815718 | ||
""" | ||
|
||
def is_duck_dask_array(x): | ||
return is_duck_array(x) and is_dask_collection(x) | ||
def __init__(self, mod): | ||
try: | ||
duck_array_module = import_module(mod) | ||
duck_array_version = LooseVersion(duck_array_module.__version__) | ||
|
||
if mod == "dask": | ||
duck_array_type = (import_module("dask.array").Array,) | ||
elif mod == "pint": | ||
duck_array_type = (duck_array_module.Quantity,) | ||
elif mod == "cupy": | ||
duck_array_type = (duck_array_module.ndarray,) | ||
elif mod == "sparse": | ||
duck_array_type = (duck_array_module.SparseArray,) | ||
else: | ||
raise NotImplementedError | ||
|
||
except ImportError: # pragma: no cover | ||
duck_array_module = None | ||
duck_array_version = LooseVersion("0.0.0") | ||
duck_array_type = () | ||
|
||
self.module = duck_array_module | ||
self.version = duck_array_version | ||
self.type = duck_array_type | ||
self.available = duck_array_module is not None | ||
|
||
except ImportError: # pragma: no cover | ||
dask_version = LooseVersion("0.0.0") | ||
dask_array_type = () | ||
is_duck_dask_array = lambda _: False | ||
is_dask_collection = lambda _: False | ||
|
||
try: | ||
# solely for isinstance checks | ||
import sparse | ||
def is_duck_dask_array(x): | ||
if DuckArrayModule("dask").available: | ||
from dask.base import is_dask_collection | ||
|
||
return is_duck_array(x) and is_dask_collection(x) | ||
else: | ||
return False | ||
|
||
|
||
sparse_version = LooseVersion(sparse.__version__) | ||
sparse_array_type = (sparse.SparseArray,) | ||
except ImportError: # pragma: no cover | ||
sparse_version = LooseVersion("0.0.0") | ||
sparse_array_type = () | ||
dsk = DuckArrayModule("dask") | ||
TomNicholas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
dask_version = dsk.version | ||
dask_array_type = dsk.type | ||
|
||
try: | ||
# solely for isinstance checks | ||
import cupy | ||
sp = DuckArrayModule("sparse") | ||
sparse_array_type = sp.type | ||
sparse_version = sp.version | ||
|
||
cupy_version = LooseVersion(cupy.__version__) | ||
cupy_array_type = (cupy.ndarray,) | ||
except ImportError: # pragma: no cover | ||
cupy_version = LooseVersion("0.0.0") | ||
cupy_array_type = () | ||
cupy_array_type = DuckArrayModule("cupy").type |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ | |
dask_array_type, | ||
integer_types, | ||
is_duck_dask_array, | ||
sparse_array_type, | ||
) | ||
from .utils import ( | ||
NdimSizeLenMixin, | ||
|
@@ -47,6 +48,8 @@ | |
maybe_coerce_to_str, | ||
) | ||
|
||
|
||
|
||
dcherian marked this conversation as resolved.
Show resolved
Hide resolved
|
||
NON_NUMPY_SUPPORTED_ARRAY_TYPES = ( | ||
( | ||
indexing.ExplicitlyIndexed, | ||
|
@@ -259,7 +262,7 @@ def _as_array_or_item(data): | |
|
||
TODO: remove this (replace with np.asarray) once these issues are fixed | ||
""" | ||
data = data.get() if isinstance(data, cupy_array_type) else np.asarray(data) | ||
data = np.asarray(data) | ||
TomNicholas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if data.ndim == 0: | ||
if data.dtype.kind == "M": | ||
data = np.datetime64(data, "ns") | ||
|
@@ -1069,6 +1072,32 @@ def chunk(self, chunks={}, name=None, lock=False): | |
|
||
return self._replace(data=data) | ||
|
||
def to_numpy(self) -> np.ndarray: | ||
"""Coerces wrapped data to numpy and returns a numpy.ndarray""" | ||
# TODO an entrypoint so array libraries can choose coercion method? | ||
data = self.data | ||
try: | ||
data = data.to_numpy() | ||
except AttributeError: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this always failing? Should we avoid it until such a protocol actually exists? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be my inclination, too. I can also imagine some other library implementing |
||
if isinstance(data, dask_array_type): | ||
data = data.compute() | ||
if isinstance(data, cupy_array_type): | ||
data = data.get() | ||
# pint has to be imported dynamically as pint imports xarray | ||
pint_array_type = DuckArrayModule("pint").type | ||
if isinstance(data, pint_array_type): | ||
data = data.magnitude | ||
if isinstance(data, sparse_array_type): | ||
data = data.todense() | ||
if type(data) != np.ndarray: # noqa : Don't allow subclasses | ||
data = np.asarray(data) | ||
TomNicholas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return data | ||
|
||
def as_numpy(self: VariableType) -> VariableType: | ||
"""Coerces wrapped data into a numpy array, returning a Variable.""" | ||
return self._replace(data=self.to_numpy()) | ||
|
||
def _as_sparse(self, sparse_format=_default, fill_value=dtypes.NA): | ||
""" | ||
use sparse-array as backend. | ||
|
Uh oh!
There was an error while loading. Please reload this page.