summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Lucas <greg.m.lucas@gmail.com>2021-11-16 12:37:19 -0700
committerGitHub <noreply@github.com>2021-11-16 11:37:19 -0800
commitb31a3a3fb05910abc2ee55d63255efdb2a2c383e (patch)
tree6a4bf7369908610274510f5b9ce7f999a026a205
parent38558de9ecb8b0ec7982a956106713f921e2d3d5 (diff)
downloadnumpy-b31a3a3fb05910abc2ee55d63255efdb2a2c383e.tar.gz
REV: Add MaskedArray creation from non nd-array back in (#20386)
* REV: Add MaskedArray creation from non nd-array back in This code path was removed in beacb39. This adds back in the MaskedArray portion of that commit. A test with a Quantity-like (non inherited, but still acts like a MaskedArray) class for this case. * Update numpy/ma/core.py Co-authored-by: Sebastian Berg <sebastian@sipsolutions.net>
-rw-r--r--numpy/ma/core.py6
-rw-r--r--numpy/ma/tests/test_subclassing.py42
2 files changed, 48 insertions, 0 deletions
diff --git a/numpy/ma/core.py b/numpy/ma/core.py
index 036d6312c..491c2c605 100644
--- a/numpy/ma/core.py
+++ b/numpy/ma/core.py
@@ -2837,6 +2837,12 @@ class MaskedArray(ndarray):
_data = ndarray.view(_data, type(data))
else:
_data = ndarray.view(_data, cls)
+
+ # Handle the case where data is not a subclass of ndarray, but
+ # still has the _mask attribute like MaskedArrays
+ if hasattr(data, '_mask') and not isinstance(data, ndarray):
+ _data._mask = data._mask
+ # FIXME: should we set `_data._sharedmask = True`?
# Process mask.
# Type of the mask
mdtype = make_mask_descr(_data.dtype)
diff --git a/numpy/ma/tests/test_subclassing.py b/numpy/ma/tests/test_subclassing.py
index 1af539625..83a9b2f51 100644
--- a/numpy/ma/tests/test_subclassing.py
+++ b/numpy/ma/tests/test_subclassing.py
@@ -343,3 +343,45 @@ class TestSubclassing:
diff2 = arr1 - arr2
assert_('info' in diff2._optinfo)
assert_(diff2._optinfo['info'] == 'test')
+
+
+class ArrayNoInheritance:
+ """Quantity-like class that does not inherit from ndarray"""
+ def __init__(self, data, units):
+ self.magnitude = data
+ self.units = units
+
+ def __getattr__(self, attr):
+ return getattr(self.magnitude, attr)
+
+
+def test_array_no_inheritance():
+ data_masked = np.ma.array([1, 2, 3], mask=[True, False, True])
+ data_masked_units = ArrayNoInheritance(data_masked, 'meters')
+
+ # Get the masked representation of the Quantity-like class
+ new_array = np.ma.array(data_masked_units)
+ assert_equal(data_masked.data, new_array.data)
+ assert_equal(data_masked.mask, new_array.mask)
+ # Test sharing the mask
+ data_masked.mask = [True, False, False]
+ assert_equal(data_masked.mask, new_array.mask)
+ assert_(new_array.sharedmask)
+
+ # Get the masked representation of the Quantity-like class
+ new_array = np.ma.array(data_masked_units, copy=True)
+ assert_equal(data_masked.data, new_array.data)
+ assert_equal(data_masked.mask, new_array.mask)
+ # Test that the mask is not shared when copy=True
+ data_masked.mask = [True, False, True]
+ assert_equal([True, False, False], new_array.mask)
+ assert_(not new_array.sharedmask)
+
+ # Get the masked representation of the Quantity-like class
+ new_array = np.ma.array(data_masked_units, keep_mask=False)
+ assert_equal(data_masked.data, new_array.data)
+ # The change did not affect the original mask
+ assert_equal(data_masked.mask, [True, False, True])
+ # Test that the mask is False and not shared when keep_mask=False
+ assert_(not new_array.mask)
+ assert_(not new_array.sharedmask)