From b31a3a3fb05910abc2ee55d63255efdb2a2c383e Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Tue, 16 Nov 2021 12:37:19 -0700 Subject: 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 --- numpy/ma/core.py | 6 ++++++ numpy/ma/tests/test_subclassing.py | 42 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) 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) -- cgit v1.2.1