Skip to content

Commit 486a051

Browse files
committed
Fixes made in parallel to Johan's and that might need to be reverted
2 parents 9367c44 + b5966a8 commit 486a051

4 files changed

Lines changed: 292 additions & 34 deletions

File tree

spm/__wrapper__.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,11 +1695,11 @@ class Cell(_ListMixin, WrappedArray):
16951695
_DelayedType = DelayedCell
16961696

16971697
@classmethod
1698-
def _DEFAULT(cls, n: list = ()) -> np.ndarray:
1699-
if len(n) == 0:
1698+
def _DEFAULT(cls, shape: list = ()) -> np.ndarray:
1699+
if len(shape) == 0:
17001700
return Array.from_any([])
17011701

1702-
data = np.empty(n, dtype=object)
1702+
data = np.empty(shape, dtype=object)
17031703
opt = dict(
17041704
flags=['refs_ok', 'zerosize_ok'],
17051705
op_flags=['writeonly', 'no_broadcast']
@@ -1743,24 +1743,27 @@ def _as_runtime(self) -> dict:
17431743
def _from_runtime(cls, objdict: dict) -> "Cell":
17441744
if objdict['type__'] != 'cell':
17451745
raise TypeError('objdict is not a cell')
1746+
size = np.array(objdict['size__'], dtype=np.uint32).ravel()
1747+
data = np.fromiter(objdict['data__'], dtype=object)
1748+
data = data.reshape(size[::-1]).transpose()
17461749
try:
1747-
size = np.array(objdict['size__'], dtype=np.uint32).ravel()
1748-
data = objdict['data__']
1749-
obj = Cell.from_shape([len(data)])
1750-
opt = dict(flags=['refs_ok', 'zerosize_ok', 'multi_index'],
1751-
op_flags=['writeonly', 'no_broadcast'])
1752-
with np.nditer(obj, **opt) as iter:
1753-
for elem in iter:
1754-
elem[()] = MatlabType.from_any(data[iter.multi_index[0]])
1755-
obj = obj.reshape(size[::-1]).transpose()
1756-
return obj
1750+
obj = data.view(cls)
17571751
except Exception:
17581752
raise RuntimeError(
17591753
f'Failed to construct Cell data:\n'
17601754
f' data={data}\n'
17611755
f' objdict={objdict}'
17621756
)
17631757

1758+
# recurse
1759+
opt = dict(flags=['refs_ok', 'zerosize_ok'],
1760+
op_flags=['readwrite', 'no_broadcast'])
1761+
with np.nditer(data, **opt) as iter:
1762+
for elem in iter:
1763+
elem[()] = MatlabType.from_any(elem.item())
1764+
1765+
return obj
1766+
17641767
@classmethod
17651768
def from_shape(cls, shape=tuple(), **kwargs) -> "Cell":
17661769
"""

tests/test_cell.py

Lines changed: 157 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,72 @@
66

77
class CellTestCase(unittest.TestCase):
88

9+
# def test_instantiate_empty(self):
10+
# c = Cell()
11+
# a = np.asarray([])
12+
# self.assertIsInstance(c, Cell)
13+
# self.assertListEqual(c.tolist(), a.tolist())
14+
915
def test_instantiate_empty(self):
16+
# Construct an empty cell array
1017
c = Cell()
11-
a = np.asarray([])
18+
19+
# Check proper construction
1220
self.assertIsInstance(c, Cell)
13-
self.assertListEqual(c.tolist(), a.tolist())
21+
self.assertTupleEqual(c.shape, (0, 0))
22+
23+
# def test_instantiate_shape_1d(self):
24+
# c = Cell([3])
25+
# self.assertIsInstance(c, Cell)
26+
# self.assertEqual(c.shape, (3,))
27+
# self.assertTrue(all(x.shape == (0,) for x in c))
28+
29+
# def test_instantiate_empty_1d_shape_cell(self):
30+
# # Construct a 3x3 cell array ?
31+
# c = Cell(3)
1432

15-
def test_instantiate_shape_1d(self):
16-
c = Cell([3])
33+
# # Check proper construction
34+
# self.assertIsInstance(c, Cell)
35+
# self.assertTupleEqual(c.shape, (1, 3))
36+
# self.assertTrue(all(isinstance(x, Array) for x in c.flat))
37+
# self.assertTrue(all(x.shape == (0,) for x in c.flat))
38+
39+
def test_instantiate_empty_1d_row_cell(self):
40+
# Construct a 1x3 cell array
41+
c = Cell(1, 3)
42+
43+
# Check proper construction
1744
self.assertIsInstance(c, Cell)
18-
self.assertEqual(c.shape, (3,))
19-
self.assertTrue(all(x.shape == (0,) for x in c))
45+
self.assertTupleEqual(c.shape, (1, 3))
46+
self.assertTrue(all(isinstance(x, Array) for x in c.flat))
47+
self.assertTrue(all(x.shape == (0,) for x in c.flat))
2048

21-
def test_instantiate_shape_2d(self):
22-
c = Cell([3, 2])
49+
def test_instantiate_empty_1d_col_cell(self):
50+
# Construct a 3x1 cell array
51+
c = Cell(3, 1)
52+
53+
# Check proper construction
2354
self.assertIsInstance(c, Cell)
24-
self.assertEqual(c.shape, (3, 2))
55+
self.assertTupleEqual(c.shape, (3, 1))
56+
self.assertTrue(all(isinstance(x, Array) for x in c.flat))
2557
self.assertTrue(all(x.shape == (0,) for x in c.flat))
2658

59+
def test_instantiate_empty_2d_cell(self):
60+
# Construct a 3x2 cell array
61+
c = Cell(3, 2)
62+
63+
# Check proper construction
64+
self.assertIsInstance(c, Cell)
65+
self.assertTupleEqual(c.shape, (3, 2))
66+
self.assertTrue(all(isinstance(x, Array) for x in c.flat))
67+
self.assertTrue(all(x.shape == (0,) for x in c.flat))
68+
69+
# def test_instantiate_shape_2d(self):
70+
# c = Cell([3, 2])
71+
# self.assertIsInstance(c, Cell)
72+
# self.assertEqual(c.shape, (3, 2))
73+
# self.assertTrue(all(x.shape == (0,) for x in c.flat))
74+
2775
def test_instantiate_shape_order(self):
2876
c = Cell([3, 2], order="C")
2977
self.assertIsInstance(c, Cell)
@@ -83,17 +131,106 @@ def test_cell1d_from_matlab(self):
83131
c_python = Cell.from_any([1, 2, 3])
84132
self.assertListEqual(c_matlab.tolist(), c_python.tolist())
85133

86-
def test_cell2d_from_matlab(self):
87-
c_matlab = Runtime.call("eval", "{1, 2, 3; 4, 5, 6}")
88-
c_python = Cell.from_any([[1, 2, 3], [4, 5, 6]], deepcat=True)
89-
self.assertTrue(c_matlab.tolist() == c_python.tolist())
90-
91-
def test_nested_cell_from_matlab(self):
92-
c_matlab = Runtime.call("eval", "{{1, 2, 3}, {4, 5, 6}}")
93-
c_python = Cell.from_any([[1, 2, 3], [4, 5, 6]])
94-
c_matlab = [x.tolist() for x in c_matlab.tolist()]
95-
c_python = [x.tolist() for x in c_python.tolist()]
96-
self.assertListEqual(c_matlab, c_python)
134+
def test_instantiate_1d_row_cell_from_matlab(self):
135+
# Construct a 1x3 cell array in Matlab
136+
try:
137+
c_matlab = Runtime.call("eval", "{1, 2, 3}")
138+
except Exception:
139+
self.fail('1D row cell from Matlab failed.')
140+
141+
# Check Runtime conversion
142+
self.assertIsInstance(c_matlab, Cell)
143+
self.assertTupleEqual(c_matlab.shape, (1, 3))
144+
self.assertListEqual(c_matlab.tolist(), [[1, 2, 3]])
145+
146+
def test_instantiate_1d_col_cell_from_matlab(self):
147+
# Construct a 3x1 cell array in Matlab
148+
try:
149+
c_matlab = Runtime.call("eval", "{1; 2; 3}")
150+
except Exception:
151+
self.fail('1D col cell from Matlab failed.')
152+
153+
# Check Runtime conversion
154+
self.assertIsInstance(c_matlab, Cell)
155+
self.assertTupleEqual(c_matlab.shape, (3, 1))
156+
self.assertListEqual(c_matlab.tolist(), [[1], [2], [3]])
157+
158+
def test_instantiate_2d_cell_from_matlab(self):
159+
# Construct a 2x3 cell array in Matlab
160+
try:
161+
c_matlab = Runtime.call("eval", "{1, 2, 3; 4, 5, 6}")
162+
except Exception:
163+
self.fail('2D cell from Matlab failed.')
164+
165+
# Check Runtime conversion
166+
self.assertIsInstance(c_matlab, Cell)
167+
self.assertTupleEqual(c_matlab.shape, (2, 3))
168+
self.assertListEqual(c_matlab.tolist(), [[1, 2, 3], [4, 5, 6]])
169+
170+
def test_instantiate_nested_cell_from_matlab(self):
171+
# Construct a nested cell array
172+
try:
173+
c_matlab = Runtime.call("eval", "{{1, 2, 3}, {4, 5, 6}}")
174+
except Exception:
175+
self.fail('Nested cell from Matlab failed.')
176+
177+
# Check Runtime conversion
178+
self.assertIsInstance(c_matlab, Cell)
179+
self.assertTupleEqual(c_matlab.shape, (2,))
180+
self.assertTrue(all(isinstance(x, Cell) for x in c_matlab))
181+
self.assertTrue(all(len(x.shape) == 1 for x in c_matlab))
182+
self.assertListEqual(c_matlab[0].tolist(), [[1, 2, 3]])
183+
self.assertListEqual(c_matlab[1].tolist(), [[4, 5, 6]])
184+
185+
def test_instantiate_empty_cell_from_matlab(self):
186+
# Construct an empty cell array in Matlab
187+
try:
188+
c_matlab = Runtime.call("eval", "{}")
189+
except Exception:
190+
self.fail('Empty cell from Matlab failed.')
191+
192+
# Check Runtime conversion
193+
self.assertIsInstance(c_matlab, Cell)
194+
self.assertTupleEqual(c_matlab.shape, (0,))
195+
196+
def test_instantiate_empty_1d_row_cell_from_matlab(self):
197+
# Construct a 1x3 cell array in Matlab
198+
try:
199+
c_matlab = Runtime.call('cell', 3, 1)
200+
except Exception:
201+
self.fail('1D empty row cell from Matlab failed.')
202+
203+
# Check Runtime conversion
204+
self.assertIsInstance(c_matlab, Cell)
205+
self.assertTupleEqual(c_matlab.shape, (3, 1))
206+
self.assertTrue(all(isinstance(x, Array) for x in c_matlab))
207+
self.assertTrue(all(len(x.shape) == 0 for x in c_matlab))
208+
209+
def test_instantiate_empty_1d_col_cell_from_matlab(self):
210+
# Construct a 1x3 cell array in Matlab
211+
try:
212+
c_matlab = Runtime.call('cell', 1, 3)
213+
except Exception:
214+
self.fail('1D empty col cell from Matlab failed.')
215+
216+
# Check Runtime conversion
217+
self.assertIsInstance(c_matlab, Cell)
218+
self.assertTupleEqual(c_matlab.shape, (1, 3))
219+
self.assertTrue(all(isinstance(x, Array) for x in c_matlab.flat))
220+
self.assertTrue(all(len(x.shape) == 0 for x in c_matlab.flat))
221+
222+
def test_instantiate_empty_2d_cell_from_matlab(self):
223+
# Construct a 3x2 cell array in Matlab
224+
try:
225+
c_matlab = Runtime.call('cell', 3, 2)
226+
except Exception:
227+
self.fail('2D empty cell from Matlab failed.')
228+
229+
# Check Runtime conversion
230+
self.assertIsInstance(c_matlab, Cell)
231+
self.assertTupleEqual(c_matlab.shape, (3, 2))
232+
self.assertTrue(all(isinstance(x, Array) for x in c_matlab.flat))
233+
self.assertTrue(all(len(x.shape) == 0 for x in c_matlab.flat))
97234

98235
def test_append_1d(self):
99236
c = Cell.from_any([1, 2, 3], owndata=True)

tests/test_struct.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22
import numpy as np
33

4-
from spm import Struct
4+
from spm import Struct, Array
55

66

77
class TestStruct(unittest.TestCase):
@@ -42,6 +42,34 @@ def test_as_array(self):
4242
a = np.asarray(self.struct, dtype=object)
4343
self.assertEqual(a.item(), dict(self.struct))
4444

45+
def test_struct_as_array_after_initialization(self):
46+
self.struct.foo = "bar"
47+
self.struct.bar = "baz"
48+
self.struct[1].baz = 42
49+
50+
keys = set(('foo', 'bar', 'baz'))
51+
52+
# All fields exist in struct array
53+
self.assertSetEqual(keys, set(self.struct.keys()))
54+
55+
# All fields exist in first slice
56+
self.assertSetEqual(keys, set(self.struct[0].keys()))
57+
58+
# All fields exist in second slice
59+
self.assertSetEqual(keys, set(self.struct[1].keys()))
60+
61+
# Specified elements are correct
62+
self.assertEqual(self.struct[0].foo, "bar")
63+
self.assertEqual(self.struct[0].bar, "baz")
64+
self.assertEqual(self.struct[1].baz, 42)
65+
66+
# Unspecified elements are empty arrays
67+
self.assertIsInstance(self.struct[0].baz, Array)
68+
self.assertTupleEqual(self.struct[0].baz.shape, tuple())
69+
self.assertIsInstance(self.struct[1].foo, Array)
70+
self.assertTupleEqual(self.struct[1].foo.shape, tuple())
71+
self.assertIsInstance(self.struct[1].bar, Array)
72+
self.assertTupleEqual(self.struct[1].bar.shape, tuple())
4573

4674
if __name__ == "__main__":
4775
unittest.main()

tests/tests_runtime.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,96 @@ def test_call_matlab_noargout(self):
4242

4343
self.assertTrue(result is None)
4444

45+
def test_0d_empty_cell_to_matlab(self):
46+
try:
47+
from spm import Runtime, Cell
48+
idt = Runtime.call('eval', '@(x) x')
49+
c = Cell()
50+
c2 = idt(c)
51+
except Exception:
52+
self.fail('OD empty cell to Matlab failed.')
53+
54+
self.assertIsInstance(c2, Cell)
55+
self.assertEqual(c2.shape, c.shape)
56+
57+
def test_1d_empty_cell_to_matlab(self):
58+
try:
59+
from spm import Runtime, Cell
60+
idt = Runtime.call('eval', '@(x) x')
61+
c = Cell(3)
62+
c2 = idt(c)
63+
except Exception:
64+
self.fail('1D empty cell to Matlab failed.')
65+
66+
self.assertIsInstance(c2, Cell)
67+
self.assertEqual(c2.shape, c.shape)
68+
69+
def test_2d_empty_cell_to_matlab(self):
70+
try:
71+
from spm import Runtime, Cell
72+
idt = Runtime.call('eval', '@(x) x')
73+
c = Cell(3, 2)
74+
c2 = idt(c)
75+
except Exception:
76+
self.fail('2D empty cell to Matlab failed.')
77+
78+
self.assertIsInstance(c2, Cell)
79+
self.assertEqual(c2.shape, c.shape)
80+
81+
def test_1d_cell_to_matlab(self):
82+
try:
83+
from spm import Runtime, Cell
84+
idt = Runtime.call('eval', '@(x) x')
85+
c = Cell.from_any([1, 2, 3])
86+
c2 = idt(c)
87+
except Exception:
88+
self.fail('1D cell to Matlab failed.')
89+
90+
self.assertIsInstance(c2, Cell)
91+
self.assertEqual(c2.shape, c.shape)
92+
self.assertTrue(c2.tolist() == c.tolist())
93+
94+
def test_2d_cell_to_matlab(self):
95+
try:
96+
from spm import Runtime, Cell
97+
import numpy as np
98+
idt = Runtime.call('eval', '@(x) x')
99+
c = Cell.from_array(np.random.randn(2, 3))
100+
c2 = idt(c)
101+
except Exception:
102+
self.fail('1D cell to Matlab failed.')
103+
104+
self.assertIsInstance(c2, Cell)
105+
self.assertEqual(c2.shape, c.shape)
106+
self.assertTrue(c2.tolist() == c.tolist())
107+
108+
def test_empty_struct_to_matlab(self):
109+
try:
110+
from spm import Runtime, Struct
111+
idt = Runtime.call('eval', '@(x) x')
112+
s = Struct()
113+
s2 = idt(s)
114+
except Exception:
115+
self.fail('Empty struct to Matlab failed.')
116+
117+
self.assertIsInstance(s2, Struct)
118+
self.assertEqual(s2.shape, s.shape)
119+
120+
def test_empty_array_to_matlab(self):
121+
try:
122+
from spm import Runtime, Array
123+
idt = Runtime.call('eval', '@(x) x')
124+
a = Array()
125+
a2 = idt(a)
126+
except Exception:
127+
self.fail('Empty array to Matlab failed.')
128+
129+
self.assertIsInstance(a2, Array)
130+
self.assertEqual(a2.shape, a.shape)
131+
132+
133+
134+
45135

46136
if __name__ == '__main__':
47137
unittest.main()

0 commit comments

Comments
 (0)