Chris@87
|
1 # pylint: disable-msg=W0611, W0612, W0511,R0201
|
Chris@87
|
2 """Tests suite for MaskedArray & subclassing.
|
Chris@87
|
3
|
Chris@87
|
4 :author: Pierre Gerard-Marchant
|
Chris@87
|
5 :contact: pierregm_at_uga_dot_edu
|
Chris@87
|
6 :version: $Id: test_subclassing.py 3473 2007-10-29 15:18:13Z jarrod.millman $
|
Chris@87
|
7
|
Chris@87
|
8 """
|
Chris@87
|
9 from __future__ import division, absolute_import, print_function
|
Chris@87
|
10
|
Chris@87
|
11 __author__ = "Pierre GF Gerard-Marchant ($Author: jarrod.millman $)"
|
Chris@87
|
12 __version__ = '1.0'
|
Chris@87
|
13 __revision__ = "$Revision: 3473 $"
|
Chris@87
|
14 __date__ = '$Date: 2007-10-29 17:18:13 +0200 (Mon, 29 Oct 2007) $'
|
Chris@87
|
15
|
Chris@87
|
16 import numpy as np
|
Chris@87
|
17 from numpy.testing import *
|
Chris@87
|
18 from numpy.ma.testutils import *
|
Chris@87
|
19 from numpy.ma.core import *
|
Chris@87
|
20
|
Chris@87
|
21
|
Chris@87
|
22 class SubArray(np.ndarray):
|
Chris@87
|
23 # Defines a generic np.ndarray subclass, that stores some metadata
|
Chris@87
|
24 # in the dictionary `info`.
|
Chris@87
|
25 def __new__(cls,arr,info={}):
|
Chris@87
|
26 x = np.asanyarray(arr).view(cls)
|
Chris@87
|
27 x.info = info
|
Chris@87
|
28 return x
|
Chris@87
|
29
|
Chris@87
|
30 def __array_finalize__(self, obj):
|
Chris@87
|
31 self.info = getattr(obj, 'info', {})
|
Chris@87
|
32 return
|
Chris@87
|
33
|
Chris@87
|
34 def __add__(self, other):
|
Chris@87
|
35 result = np.ndarray.__add__(self, other)
|
Chris@87
|
36 result.info.update({'added':result.info.pop('added', 0)+1})
|
Chris@87
|
37 return result
|
Chris@87
|
38
|
Chris@87
|
39 subarray = SubArray
|
Chris@87
|
40
|
Chris@87
|
41
|
Chris@87
|
42 class MSubArray(SubArray, MaskedArray):
|
Chris@87
|
43
|
Chris@87
|
44 def __new__(cls, data, info={}, mask=nomask):
|
Chris@87
|
45 subarr = SubArray(data, info)
|
Chris@87
|
46 _data = MaskedArray.__new__(cls, data=subarr, mask=mask)
|
Chris@87
|
47 _data.info = subarr.info
|
Chris@87
|
48 return _data
|
Chris@87
|
49
|
Chris@87
|
50 def __array_finalize__(self, obj):
|
Chris@87
|
51 MaskedArray.__array_finalize__(self, obj)
|
Chris@87
|
52 SubArray.__array_finalize__(self, obj)
|
Chris@87
|
53 return
|
Chris@87
|
54
|
Chris@87
|
55 def _get_series(self):
|
Chris@87
|
56 _view = self.view(MaskedArray)
|
Chris@87
|
57 _view._sharedmask = False
|
Chris@87
|
58 return _view
|
Chris@87
|
59 _series = property(fget=_get_series)
|
Chris@87
|
60
|
Chris@87
|
61 msubarray = MSubArray
|
Chris@87
|
62
|
Chris@87
|
63
|
Chris@87
|
64 class MMatrix(MaskedArray, np.matrix,):
|
Chris@87
|
65
|
Chris@87
|
66 def __new__(cls, data, mask=nomask):
|
Chris@87
|
67 mat = np.matrix(data)
|
Chris@87
|
68 _data = MaskedArray.__new__(cls, data=mat, mask=mask)
|
Chris@87
|
69 return _data
|
Chris@87
|
70
|
Chris@87
|
71 def __array_finalize__(self, obj):
|
Chris@87
|
72 np.matrix.__array_finalize__(self, obj)
|
Chris@87
|
73 MaskedArray.__array_finalize__(self, obj)
|
Chris@87
|
74 return
|
Chris@87
|
75
|
Chris@87
|
76 def _get_series(self):
|
Chris@87
|
77 _view = self.view(MaskedArray)
|
Chris@87
|
78 _view._sharedmask = False
|
Chris@87
|
79 return _view
|
Chris@87
|
80 _series = property(fget=_get_series)
|
Chris@87
|
81
|
Chris@87
|
82 mmatrix = MMatrix
|
Chris@87
|
83
|
Chris@87
|
84
|
Chris@87
|
85 # also a subclass that overrides __str__, __repr__ and __setitem__, disallowing
|
Chris@87
|
86 # setting to non-class values (and thus np.ma.core.masked_print_option)
|
Chris@87
|
87 class ComplicatedSubArray(SubArray):
|
Chris@87
|
88 def __str__(self):
|
Chris@87
|
89 return 'myprefix {0} mypostfix'.format(
|
Chris@87
|
90 super(ComplicatedSubArray, self).__str__())
|
Chris@87
|
91
|
Chris@87
|
92 def __repr__(self):
|
Chris@87
|
93 # Return a repr that does not start with 'name('
|
Chris@87
|
94 return '<{0} {1}>'.format(self.__class__.__name__, self)
|
Chris@87
|
95
|
Chris@87
|
96 def __setitem__(self, item, value):
|
Chris@87
|
97 # this ensures direct assignment to masked_print_option will fail
|
Chris@87
|
98 if not isinstance(value, ComplicatedSubArray):
|
Chris@87
|
99 raise ValueError("Can only set to MySubArray values")
|
Chris@87
|
100 super(ComplicatedSubArray, self).__setitem__(item, value)
|
Chris@87
|
101
|
Chris@87
|
102
|
Chris@87
|
103 class TestSubclassing(TestCase):
|
Chris@87
|
104 # Test suite for masked subclasses of ndarray.
|
Chris@87
|
105
|
Chris@87
|
106 def setUp(self):
|
Chris@87
|
107 x = np.arange(5)
|
Chris@87
|
108 mx = mmatrix(x, mask=[0, 1, 0, 0, 0])
|
Chris@87
|
109 self.data = (x, mx)
|
Chris@87
|
110
|
Chris@87
|
111 def test_data_subclassing(self):
|
Chris@87
|
112 # Tests whether the subclass is kept.
|
Chris@87
|
113 x = np.arange(5)
|
Chris@87
|
114 m = [0, 0, 1, 0, 0]
|
Chris@87
|
115 xsub = SubArray(x)
|
Chris@87
|
116 xmsub = masked_array(xsub, mask=m)
|
Chris@87
|
117 self.assertTrue(isinstance(xmsub, MaskedArray))
|
Chris@87
|
118 assert_equal(xmsub._data, xsub)
|
Chris@87
|
119 self.assertTrue(isinstance(xmsub._data, SubArray))
|
Chris@87
|
120
|
Chris@87
|
121 def test_maskedarray_subclassing(self):
|
Chris@87
|
122 # Tests subclassing MaskedArray
|
Chris@87
|
123 (x, mx) = self.data
|
Chris@87
|
124 self.assertTrue(isinstance(mx._data, np.matrix))
|
Chris@87
|
125
|
Chris@87
|
126 def test_masked_unary_operations(self):
|
Chris@87
|
127 # Tests masked_unary_operation
|
Chris@87
|
128 (x, mx) = self.data
|
Chris@87
|
129 with np.errstate(divide='ignore'):
|
Chris@87
|
130 self.assertTrue(isinstance(log(mx), mmatrix))
|
Chris@87
|
131 assert_equal(log(x), np.log(x))
|
Chris@87
|
132
|
Chris@87
|
133 def test_masked_binary_operations(self):
|
Chris@87
|
134 # Tests masked_binary_operation
|
Chris@87
|
135 (x, mx) = self.data
|
Chris@87
|
136 # Result should be a mmatrix
|
Chris@87
|
137 self.assertTrue(isinstance(add(mx, mx), mmatrix))
|
Chris@87
|
138 self.assertTrue(isinstance(add(mx, x), mmatrix))
|
Chris@87
|
139 # Result should work
|
Chris@87
|
140 assert_equal(add(mx, x), mx+x)
|
Chris@87
|
141 self.assertTrue(isinstance(add(mx, mx)._data, np.matrix))
|
Chris@87
|
142 self.assertTrue(isinstance(add.outer(mx, mx), mmatrix))
|
Chris@87
|
143 self.assertTrue(isinstance(hypot(mx, mx), mmatrix))
|
Chris@87
|
144 self.assertTrue(isinstance(hypot(mx, x), mmatrix))
|
Chris@87
|
145
|
Chris@87
|
146 def test_masked_binary_operations2(self):
|
Chris@87
|
147 # Tests domained_masked_binary_operation
|
Chris@87
|
148 (x, mx) = self.data
|
Chris@87
|
149 xmx = masked_array(mx.data.__array__(), mask=mx.mask)
|
Chris@87
|
150 self.assertTrue(isinstance(divide(mx, mx), mmatrix))
|
Chris@87
|
151 self.assertTrue(isinstance(divide(mx, x), mmatrix))
|
Chris@87
|
152 assert_equal(divide(mx, mx), divide(xmx, xmx))
|
Chris@87
|
153
|
Chris@87
|
154 def test_attributepropagation(self):
|
Chris@87
|
155 x = array(arange(5), mask=[0]+[1]*4)
|
Chris@87
|
156 my = masked_array(subarray(x))
|
Chris@87
|
157 ym = msubarray(x)
|
Chris@87
|
158 #
|
Chris@87
|
159 z = (my+1)
|
Chris@87
|
160 self.assertTrue(isinstance(z, MaskedArray))
|
Chris@87
|
161 self.assertTrue(not isinstance(z, MSubArray))
|
Chris@87
|
162 self.assertTrue(isinstance(z._data, SubArray))
|
Chris@87
|
163 assert_equal(z._data.info, {})
|
Chris@87
|
164 #
|
Chris@87
|
165 z = (ym+1)
|
Chris@87
|
166 self.assertTrue(isinstance(z, MaskedArray))
|
Chris@87
|
167 self.assertTrue(isinstance(z, MSubArray))
|
Chris@87
|
168 self.assertTrue(isinstance(z._data, SubArray))
|
Chris@87
|
169 self.assertTrue(z._data.info['added'] > 0)
|
Chris@87
|
170 #
|
Chris@87
|
171 ym._set_mask([1, 0, 0, 0, 1])
|
Chris@87
|
172 assert_equal(ym._mask, [1, 0, 0, 0, 1])
|
Chris@87
|
173 ym._series._set_mask([0, 0, 0, 0, 1])
|
Chris@87
|
174 assert_equal(ym._mask, [0, 0, 0, 0, 1])
|
Chris@87
|
175 #
|
Chris@87
|
176 xsub = subarray(x, info={'name':'x'})
|
Chris@87
|
177 mxsub = masked_array(xsub)
|
Chris@87
|
178 self.assertTrue(hasattr(mxsub, 'info'))
|
Chris@87
|
179 assert_equal(mxsub.info, xsub.info)
|
Chris@87
|
180
|
Chris@87
|
181 def test_subclasspreservation(self):
|
Chris@87
|
182 # Checks that masked_array(...,subok=True) preserves the class.
|
Chris@87
|
183 x = np.arange(5)
|
Chris@87
|
184 m = [0, 0, 1, 0, 0]
|
Chris@87
|
185 xinfo = [(i, j) for (i, j) in zip(x, m)]
|
Chris@87
|
186 xsub = MSubArray(x, mask=m, info={'xsub':xinfo})
|
Chris@87
|
187 #
|
Chris@87
|
188 mxsub = masked_array(xsub, subok=False)
|
Chris@87
|
189 self.assertTrue(not isinstance(mxsub, MSubArray))
|
Chris@87
|
190 self.assertTrue(isinstance(mxsub, MaskedArray))
|
Chris@87
|
191 assert_equal(mxsub._mask, m)
|
Chris@87
|
192 #
|
Chris@87
|
193 mxsub = asarray(xsub)
|
Chris@87
|
194 self.assertTrue(not isinstance(mxsub, MSubArray))
|
Chris@87
|
195 self.assertTrue(isinstance(mxsub, MaskedArray))
|
Chris@87
|
196 assert_equal(mxsub._mask, m)
|
Chris@87
|
197 #
|
Chris@87
|
198 mxsub = masked_array(xsub, subok=True)
|
Chris@87
|
199 self.assertTrue(isinstance(mxsub, MSubArray))
|
Chris@87
|
200 assert_equal(mxsub.info, xsub.info)
|
Chris@87
|
201 assert_equal(mxsub._mask, xsub._mask)
|
Chris@87
|
202 #
|
Chris@87
|
203 mxsub = asanyarray(xsub)
|
Chris@87
|
204 self.assertTrue(isinstance(mxsub, MSubArray))
|
Chris@87
|
205 assert_equal(mxsub.info, xsub.info)
|
Chris@87
|
206 assert_equal(mxsub._mask, m)
|
Chris@87
|
207
|
Chris@87
|
208 def test_subclass_repr(self):
|
Chris@87
|
209 """test that repr uses the name of the subclass
|
Chris@87
|
210 and 'array' for np.ndarray"""
|
Chris@87
|
211 x = np.arange(5)
|
Chris@87
|
212 mx = masked_array(x, mask=[True, False, True, False, False])
|
Chris@87
|
213 self.assertTrue(repr(mx).startswith('masked_array'))
|
Chris@87
|
214 xsub = SubArray(x)
|
Chris@87
|
215 mxsub = masked_array(xsub, mask=[True, False, True, False, False])
|
Chris@87
|
216 self.assertTrue(repr(mxsub).startswith(
|
Chris@87
|
217 'masked_{0}(data = [-- 1 -- 3 4]'.format(SubArray.__name__)))
|
Chris@87
|
218
|
Chris@87
|
219 def test_subclass_str(self):
|
Chris@87
|
220 """test str with subclass that has overridden str, setitem"""
|
Chris@87
|
221 # first without override
|
Chris@87
|
222 x = np.arange(5)
|
Chris@87
|
223 xsub = SubArray(x)
|
Chris@87
|
224 mxsub = masked_array(xsub, mask=[True, False, True, False, False])
|
Chris@87
|
225 self.assertTrue(str(mxsub) == '[-- 1 -- 3 4]')
|
Chris@87
|
226
|
Chris@87
|
227 xcsub = ComplicatedSubArray(x)
|
Chris@87
|
228 assert_raises(ValueError, xcsub.__setitem__, 0,
|
Chris@87
|
229 np.ma.core.masked_print_option)
|
Chris@87
|
230 mxcsub = masked_array(xcsub, mask=[True, False, True, False, False])
|
Chris@87
|
231 self.assertTrue(str(mxcsub) == 'myprefix [-- 1 -- 3 4] mypostfix')
|
Chris@87
|
232
|
Chris@87
|
233
|
Chris@87
|
234 ###############################################################################
|
Chris@87
|
235 if __name__ == '__main__':
|
Chris@87
|
236 run_module_suite()
|