Skip to content
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

High-level ak._v2.Array clean-ups. #1392

Merged
merged 4 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/awkward/_v2/_broadcasting.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ def continuation():
elif any(isinstance(x, RecordArray) for x in inputs):
if not options["allow_records"]:
raise ak._v2._util.error(
ValueError(f"cannot broadcast records{in_function(options)}")
ValueError(f"cannot broadcast records {in_function(options)}")
)

fields, length, istuple = None, None, True
Expand Down
12 changes: 6 additions & 6 deletions src/awkward/_v2/_connect/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
raise ImportError("NumPy 1.13.1 or later required")


# def convert_to_array(layout, args, kwargs):
# out = ak._v2.operations.convert.to_numpy(layout, allow_missing=False)
# if args == () and kwargs == {}:
# return out
# else:
# return numpy.array(out, *args, **kwargs)
def convert_to_array(layout, args, kwargs):
out = ak._v2.operations.convert.to_numpy(layout, allow_missing=False)
if args == () and kwargs == {}:
return out
else:
return numpy.array(out, *args, **kwargs)


# implemented = {}
Expand Down
5 changes: 4 additions & 1 deletion src/awkward/_v2/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,10 @@ def error(exception, error_context=None):
valuestr = "???"
if len(valuestr) > 80:
valuestr = valuestr[:77] + "..."
arguments.append(f"\n {name} = {valuestr}")
if isstr(name):
arguments.append(f"\n {name} = {valuestr}")
else:
arguments.append(f"\n {valuestr}")

extra_line = "" if len(arguments) == 0 else "\n "
return type(exception)(
Expand Down
203 changes: 79 additions & 124 deletions src/awkward/_v2/highlevel.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,5 @@
# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE

# TODO in Array:
#
# - [ ] all docstrings are old
# - [ ] 'Mask' nested class and 'mask' property
# - [ ] `__array__`
# - [ ] `__array_ufunc__`
# - [ ] `__array_function__`
# - [X] `numba_type`
# - [x] `__copy__`
# - [x] `__deepcopy__`
# - [X] `__contains__`
#
# TODO in Array:
#
# - [ ] all docstrings are old
# - [ ] `__array_ufunc__`
# - [X] `numba_type`
# - [x] `__copy__`
# - [x] `__deepcopy__`
# - [X] `__contains__`
#
# TODO in ArrayBuilder: everything


import sys
import re
import keyword
Expand All @@ -41,14 +17,6 @@
_dir_pattern = re.compile(r"^[a-zA-Z_]\w*$")


# def _suffix(array):
# out = ak._v2.operations.convert.kernels(array)
# if out is None or out == "cpu":
# return ""
# else:
# return ":" + out


class Array(NDArrayOperatorsMixin, Iterable, Sized):
"""
Args:
Expand Down Expand Up @@ -374,67 +342,32 @@ def behavior(self, behavior):
else:
raise ak._v2._util.error(TypeError("behavior must be None or a dict"))

# class Mask(object):
# def __init__(self, array, valid_when):
# self._array = array
# self._valid_when = valid_when

# def __str__(self):
# return self._str()

# def __repr__(self):
# return self._repr()

# def _str(self, limit_value=85):
# return self._array._str(limit_value=limit_value)

# def _repr(self, limit_value=40, limit_total=85):
# suffix = _suffix(self)
# limit_value -= len(suffix)

# value = ak._v2._util.minimally_touching_string(
# limit_value, self._array.layout, self._array._behavior
# )

# try:
# name = super(Array, self._array).__getattribute__("__name__")
# except AttributeError:
# name = type(self._array).__name__
# limit_type = limit_total - (len(value) + len(name) + len("<.mask type=>"))
# typestr = repr(
# str(
# ak._v2._util.highlevel_type(
# self._array.layout, self._array._behavior, True
# )
# )
# )
# if len(typestr) > limit_type:
# typestr = typestr[: (limit_type - 4)] + "..." + typestr[-1]

# return "<{0}.mask{1} {2} type={3}>".format(name, suffix, value, typestr)

# def __getitem__(self, where):
# return ak._v2.operations.structure.mask(self._array, where, self._valid_when)

# @property
# def mask(self, valid_when=True):
# """
# Whereas
class Mask:
def __init__(self, array):
self._array = array

# array[array_of_booleans]
def __getitem__(self, where):
return ak._v2.operations.structure.mask(self._array, where, True)

# removes elements from `array` in which `array_of_booleans` is False,
@property
def mask(self):
"""
Whereas

# array.mask[array_of_booleans]
array[array_of_booleans]

# returns data with the same length as the original `array` but False
# values in `array_of_booleans` are mapped to None. Such an output
# can be used in mathematical expressions with the original `array`
# because they are still aligned.
removes elements from `array` in which `array_of_booleans` is False,

# See <<filtering>> and #ak.mask.
# """
# return self.Mask(self, valid_when)
array.mask[array_of_booleans]

returns data with the same length as the original `array` but False
values in `array_of_booleans` are mapped to None. Such an output
can be used in mathematical expressions with the original `array`
because they are still aligned.

See <<filtering>> and #ak.mask.
"""
return self.Mask(self)

def tolist(self):
"""
Expand Down Expand Up @@ -1301,32 +1234,37 @@ def show(self, limit_rows=20, limit_cols=80, type=False, stream=sys.stdout):
else:
stream.write(out + "\n")

# def __array__(self, *args, **kwargs):
# """
# Intercepts attempts to convert this Array into a NumPy array and
# either performs a zero-copy conversion or raises an error.

# This function is also called by the
# [np.asarray](https://docs.scipy.org/doc/numpy/reference/generated/numpy.asarray.html)
# family of functions, which have `copy=False` by default.

# >>> np.asarray(ak.Array([[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]]))
# array([[1.1, 2.2, 3.3],
# [4.4, 5.5, 6.6]])

# If the data are numerical and regular (nested lists have equal lengths
# in each dimension, as described by the #type), they can be losslessly
# converted to a NumPy array and this function returns without an error.

# Otherwise, the function raises an error. It does not create a NumPy
# array with dtype `"O"` for `np.object_` (see the
# [note on object_ type](https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html#arrays-scalars-built-in))
# since silent conversions to dtype `"O"` arrays would not only be a
# significant performance hit, but would also break functionality, since
# nested lists in a NumPy `"O"` array are severed from the array and
# cannot be sliced as dimensions.
# """
# return ak._v2._connect.numpy.convert_to_array(self._layout, args, kwargs)
def __array__(self, *args, **kwargs):
"""
Intercepts attempts to convert this Array into a NumPy array and
either performs a zero-copy conversion or raises an error.

This function is also called by the
[np.asarray](https://docs.scipy.org/doc/numpy/reference/generated/numpy.asarray.html)
family of functions, which have `copy=False` by default.

>>> np.asarray(ak.Array([[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]]))
array([[1.1, 2.2, 3.3],
[4.4, 5.5, 6.6]])

If the data are numerical and regular (nested lists have equal lengths
in each dimension, as described by the #type), they can be losslessly
converted to a NumPy array and this function returns without an error.

Otherwise, the function raises an error. It does not create a NumPy
array with dtype `"O"` for `np.object_` (see the
[note on object_ type](https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html#arrays-scalars-built-in))
since silent conversions to dtype `"O"` arrays would not only be a
significant performance hit, but would also break functionality, since
nested lists in a NumPy `"O"` array are severed from the array and
cannot be sliced as dimensions.
"""
arguments = {0: self}
for i, arg in enumerate(args):
arguments[i + 1] = arg
arguments.update(kwargs)
with ak._v2._util.OperationErrorContext("numpy.asarray", arguments):
return ak._v2._connect.numpy.convert_to_array(self._layout, args, kwargs)

def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
"""
Expand Down Expand Up @@ -1385,7 +1323,13 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):

See also #__array_function__.
"""
return ak._v2._connect.numpy.array_ufunc(ufunc, method, inputs, kwargs)
name = f"{type(ufunc).__module__}.{ufunc.__name__}.{str(method)}"
arguments = {}
for i, arg in enumerate(inputs):
arguments[i] = arg
arguments.update(kwargs)
with ak._v2._util.OperationErrorContext(name, arguments):
return ak._v2._connect.numpy.array_ufunc(ufunc, method, inputs, kwargs)

# def __array_function__(self, func, types, args, kwargs):
# """
Expand Down Expand Up @@ -2022,7 +1966,13 @@ def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):

See #ak.Array.__array_ufunc__ for a more complete description.
"""
return ak._v2._connect.numpy.array_ufunc(ufunc, method, inputs, kwargs)
name = f"{type(ufunc).__module__}.{ufunc.__name__}.{str(method)}"
arguments = {}
for i, arg in enumerate(inputs):
arguments[i] = arg
arguments.update(kwargs)
with ak._v2._util.OperationErrorContext(name, arguments):
return ak._v2._connect.numpy.array_ufunc(ufunc, method, inputs, kwargs)

@property
def numba_type(self):
Expand Down Expand Up @@ -2371,15 +2321,20 @@ def show(self, limit_rows=20, limit_cols=80, type=False, stream=sys.stdout):
limit_rows=limit_rows, limit_cols=limit_cols, type=type, stream=stream
)

# def __array__(self, *args, **kwargs):
# """
# Intercepts attempts to convert a #snapshot of this array into a
# NumPy array and either performs a zero-copy conversion or raises
# an error.
def __array__(self, *args, **kwargs):
"""
Intercepts attempts to convert a #snapshot of this array into a
NumPy array and either performs a zero-copy conversion or raises
an error.

# See #ak.Array.__array__ for a more complete description.
# """
# return ak._v2._connect.numpy.convert_to_array(self.snapshot(), args, kwargs)
See #ak.Array.__array__ for a more complete description.
"""
arguments = {0: self}
for i, arg in enumerate(args):
arguments[i + 1] = arg
arguments.update(kwargs)
with ak._v2._util.OperationErrorContext("numpy.asarray", arguments):
return ak._v2._connect.numpy.convert_to_array(self.snapshot(), args, kwargs)

@property
def numba_type(self):
Expand Down