Skip to content

Commit 7f7bb03

Browse files
committed
fix(base): accept a list of rows in getmatrix and a range in getvector
getmatrix() raised TypeError for a nested list or tuple, such as a 2xN path written as [[0, 1, 2], [0, 1, 0]], and getvector() raised TypeError for a range. Convert a nested sequence to an array and check its shape like any 2D array, and treat a range like a list. A flat list is still reshaped as before. Refs #255
1 parent 824a459 commit 7f7bb03

2 files changed

Lines changed: 52 additions & 2 deletions

File tree

‎spatialmath/base/argcheck.py‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ def getmatrix(
186186
:raises ValueError: if value is not of the specified shape
187187
188188
``getmatrix(m, shape)`` is a 2D matrix with shape ``shape`` formed from
189-
``m`` which can be a 2D array, 1D array-like or a scalar.
189+
``m`` which can be a 2D array, a list or tuple of rows, a 1D array-like
190+
(including a ``range``) or a scalar.
190191
191192
.. runblock:: pycon
192193
@@ -197,6 +198,7 @@ def getmatrix(
197198
>>> getmatrix([3,4], (2, 1))
198199
>>> getmatrix([3,4,5,6], (2,2))
199200
>>> getmatrix(np.r_[3,4,5,6], (2,2))
201+
>>> getmatrix([[0,1,2], [0,1,0]], (2,None)) # list of rows
200202
201203
.. note::
202204
@@ -213,6 +215,13 @@ def getmatrix(
213215
:seealso: :func:`ismatrix`, :func:`verifymatrix`
214216
:SymPy: supported
215217
"""
218+
if isinstance(m, range):
219+
m = list(m)
220+
if isinstance(m, (list, tuple)) and not isvector(m):
221+
# passed a nested sequence, such as a list of rows: convert it and
222+
# check its shape below
223+
m = np.array(m)
224+
216225
if isinstance(m, np.ndarray) and len(m.shape) == 2:
217226
# passed a 2D array
218227
mshape = m.shape
@@ -341,7 +350,7 @@ def getvector(
341350
where ``vec`` is any of:
342351
343352
- a Python native int or float, a 1-vector
344-
- Python native list or tuple
353+
- Python native list, tuple or range
345354
- numPy real 1D array, ie. shape=(N,)
346355
- numPy real 2D array with a singleton dimension, ie. shape=(1,N)
347356
or (N,1)
@@ -386,6 +395,8 @@ def getvector(
386395
"""
387396
dt = dtype
388397

398+
if isinstance(v, range): # a range is a sequence of numbers
399+
v = list(v)
389400
if isinstance(v, _scalartypes): # handle scalar case
390401
v = [v] # type: ignore
391402
if isinstance(v, (list, tuple)):

‎tests/base/test_argcheck.py‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,31 @@ def test_getmatrix(self):
110110
with self.assertRaises(ValueError):
111111
m = getmatrix(a, (2, None))
112112

113+
def test_getmatrix_nested_sequence(self):
114+
# a list of rows, as for a 2xN path of points (issue #255)
115+
m = getmatrix([[0, 1, 2], [0, 1, 0]], (2, None))
116+
self.assertIsInstance(m, np.ndarray)
117+
nt.assert_array_equal(m, np.array([[0, 1, 2], [0, 1, 0]]))
118+
self.assertEqual(m.dtype, np.float64)
119+
120+
# a list of tuples, Nx2
121+
m = getmatrix([(0, 0), (1, 1), (2, 0)], (None, 2))
122+
nt.assert_array_equal(m, np.array([[0, 0], [1, 1], [2, 0]]))
123+
124+
# a tuple of lists, fully specified shape
125+
m = getmatrix(([1, 2], [3, 4]), (2, 2))
126+
nt.assert_array_equal(m, np.array([[1, 2], [3, 4]]))
127+
128+
# the shape is checked, not reshaped
129+
with self.assertRaises(ValueError):
130+
getmatrix([[0, 1, 2], [0, 1, 0]], (3, None))
131+
with self.assertRaises(ValueError):
132+
getmatrix([[0, 0], [1, 1], [2, 0]], (2, None))
133+
134+
# a range is a 1D sequence of numbers
135+
m = getmatrix(range(4), (2, 2))
136+
nt.assert_array_equal(m, np.array([[0, 1], [2, 3]]))
137+
113138
def test_verifymatrix(self):
114139
with self.assertRaises(TypeError):
115140
assertmatrix(3)
@@ -237,6 +262,20 @@ def test_homogeneous_conversion_unsupported_array_shapes(self):
237262
with self.assertRaises(ValueError):
238263
convert(np.ones(shape))
239264

265+
def test_getvector_range(self):
266+
# a range is a sequence of numbers (issue #255)
267+
v = getvector(range(1, 7))
268+
self.assertIsInstance(v, np.ndarray)
269+
nt.assert_array_equal(v, np.r_[1, 2, 3, 4, 5, 6])
270+
271+
v = getvector(range(3), 3, out="list")
272+
self.assertEqual(v, [0, 1, 2])
273+
274+
v = getvector(range(3), out="col")
275+
nt.assert_equal(v.shape, (3, 1))
276+
277+
nt.assert_raises(ValueError, getvector, range(3), 4)
278+
240279
def test_getvector(self):
241280
l = [1, 2, 3]
242281
t = (1, 2, 3)

0 commit comments

Comments
 (0)