Skip to content

Commit

Permalink
make the ak.Array.mask weakly dependent on the array itself
Browse files Browse the repository at this point in the history
  • Loading branch information
pfackeldey committed Dec 16, 2024
1 parent 3725585 commit 0c72f0a
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 30 deletions.
13 changes: 10 additions & 3 deletions src/awkward/highlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import keyword
import pickle
import re
import weakref
from collections.abc import Iterable, Mapping, Sequence, Sized

from awkward_cpp.lib import _ext
Expand Down Expand Up @@ -488,13 +489,19 @@ def named_axis(self) -> AxisMapping:

class Mask:
def __init__(self, array):
self._array = array
self._array = weakref.ref(array)

def __getitem__(self, where):
array = self._array()
if array is None:
msg = "The array to mask was deleted before it could be masked. "
msg += "If you want to construct this mask, you must either keep the array alive "
msg += "or use 'ak.mask' explicitly."
raise ValueError(msg)
with ak._errors.OperationErrorContext(
"ak.Array.mask", args=[self._array, where], kwargs={}
"ak.Array.mask", args=[array, where], kwargs={}
):
return ak.operations.mask(self._array, where, valid_when=True)
return ak.operations.mask(array, where, valid_when=True)

@property
def mask(self):
Expand Down
98 changes: 72 additions & 26 deletions tests/test_2020_reduce_axis_none.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ def test_sum():
assert ak.almost_equal(
ak.sum(array, axis=None, keepdims=True), ak.to_regular([[63.0]])
)

arr = ak.Array([[63.0]])
assert ak.almost_equal(
ak.sum(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[63.0]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)
assert ak.sum(array[2], axis=None, mask_identity=True) is None

Expand All @@ -31,9 +33,10 @@ def test_prod():
assert ak.almost_equal(
ak.prod(array[1:], axis=None, keepdims=True), ak.to_regular([[4838400.0]])
)
arr = ak.Array([[4838400.0]])
assert ak.almost_equal(
ak.prod(array[1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[4838400.0]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)
assert ak.prod(array[2], axis=None, mask_identity=True) is None

Expand All @@ -49,13 +52,16 @@ def test_min():
ak.to_regular([[-100.0]]),
)

arr = ak.Array([[0.0]])
assert ak.almost_equal(
ak.min(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0.0]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[np.inf]])
assert ak.almost_equal(
ak.min(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[np.inf]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.min(array[2], axis=None, mask_identity=True) is None

Expand All @@ -70,13 +76,17 @@ def test_max():
ak.max(array, axis=None, keepdims=True, initial=100, mask_identity=False),
ak.to_regular([[100.0]]),
)

arr = ak.Array([[10.0]])
assert ak.almost_equal(
ak.max(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[10.0]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[-np.inf]])
assert ak.almost_equal(
ak.max(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[np.inf]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.max(array[2], axis=None, mask_identity=True) is None

Expand All @@ -87,13 +97,17 @@ def test_count():
ak.count(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[12]]),
)

arr = ak.Array([[12]])
assert ak.almost_equal(
ak.count(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[12]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[0]])
assert ak.almost_equal(
ak.count(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.count(array[2], axis=None, mask_identity=True) is None
assert ak.count(array[2], axis=None, mask_identity=False) == 0
Expand All @@ -105,13 +119,17 @@ def test_count_nonzero():
ak.count_nonzero(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[11]]),
)

arr = ak.Array([[11]])
assert ak.almost_equal(
ak.count_nonzero(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[11]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[0]])
assert ak.almost_equal(
ak.count_nonzero(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.count_nonzero(array[2], axis=None, mask_identity=True) is None
assert ak.count_nonzero(array[2], axis=None, mask_identity=False) == 0
Expand All @@ -123,17 +141,20 @@ def test_std():
ak.std(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[3.139134700306227]]),
)

arr = ak.Array([[3.139134700306227]])
assert ak.almost_equal(
ak.std(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[3.139134700306227]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)
assert np.isnan(ak.std(array[2], axis=None, mask_identity=False))


def test_std_no_mask_axis_none():
arr = ak.Array([[0.0]])
assert ak.almost_equal(
ak.std(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0.0]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.std(array[2], axis=None, mask_identity=True) is None

Expand All @@ -144,17 +165,20 @@ def test_var():
ak.var(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[9.854166666666666]]),
)

arr = ak.Array([[9.854166666666666]])
assert ak.almost_equal(
ak.var(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[9.854166666666666]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)
assert np.isnan(ak.var(array[2], axis=None, mask_identity=False))


def test_var_no_mask_axis_none():
arr = ak.Array([[0.0]])
assert ak.almost_equal(
ak.var(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0.0]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.var(array[2], axis=None, mask_identity=True) is None

Expand All @@ -165,17 +189,20 @@ def test_mean():
ak.mean(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[5.25]]),
)

arr = ak.Array([[5.25]])
assert ak.almost_equal(
ak.mean(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[5.25]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)
assert np.isnan(ak.mean(array[2], axis=None, mask_identity=False))


def test_mean_no_mask_axis_none():
arr = ak.Array([[0.0]])
assert ak.almost_equal(
ak.mean(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0.0]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.mean(array[2], axis=None, mask_identity=True) is None

Expand All @@ -186,17 +213,20 @@ def test_ptp():
ak.ptp(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[10.0]]),
)

arr = ak.Array([[10.0]])
assert ak.almost_equal(
ak.ptp(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[10.0]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)
assert ak.ptp(array[2], axis=None, mask_identity=False) == pytest.approx(0.0)


def test_ptp_no_mask_axis_none():
arr = ak.Array([[0.0]])
assert ak.almost_equal(
ak.ptp(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0.0]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.ptp(array[2], axis=None, mask_identity=True) is None

Expand All @@ -207,13 +237,17 @@ def test_argmax():
ak.argmax(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[11]]),
)

arr = ak.Array([[11]])
assert ak.almost_equal(
ak.argmax(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[11]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[0]])
assert ak.almost_equal(
ak.argmax(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.argmax(array[2], axis=None, mask_identity=True) is None
assert ak.argmax(array[2], axis=None, mask_identity=False) == -1
Expand All @@ -225,13 +259,17 @@ def test_argmin():
ak.argmin(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[0]]),
)

arr = ak.Array([[0]])
assert ak.almost_equal(
ak.argmin(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[0]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[999]])
assert ak.almost_equal(
ak.argmin(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[999]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.argmin(array[2], axis=None, mask_identity=True) is None
assert ak.argmin(array[2], axis=None, mask_identity=False) == -1
Expand All @@ -243,13 +281,17 @@ def test_any():
ak.any(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[True]]),
)

arr = ak.Array([[True]])
assert ak.almost_equal(
ak.any(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[True]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[True]])
assert ak.almost_equal(
ak.any(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[True]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.any(array[2], axis=None, mask_identity=True) is None
assert not ak.any(array[2], axis=None, mask_identity=False)
Expand All @@ -261,13 +303,17 @@ def test_all():
ak.all(array, axis=None, keepdims=True, mask_identity=False),
ak.to_regular([[False]]),
)

arr = ak.Array([[False]])
assert ak.almost_equal(
ak.all(array, axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[False]]).mask[[[True]]]),
ak.to_regular(arr.mask[[[True]]]),
)

arr = ak.Array([[False]])
assert ak.almost_equal(
ak.all(array[-1:], axis=None, keepdims=True, mask_identity=True),
ak.to_regular(ak.Array([[False]]).mask[[[False]]]),
ak.to_regular(arr.mask[[[False]]]),
)
assert ak.all(array[2], axis=None, mask_identity=True) is None
assert ak.all(array[2], axis=None, mask_identity=False)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_2064_fill_none_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ def test_axis_last():


def test_option_outside_record():
record = ak.zip({"x": [1, 4], "y": [2, 3]}).mask[[True, False]]
record = ak.zip({"x": [1, 4], "y": [2, 3]})
record = record.mask[[True, False]]
assert ak.fill_none(record, 0, axis=-1).to_list() == [{"x": 1, "y": 2}, 0]

0 comments on commit 0c72f0a

Please sign in to comment.