[Scipy-svn] r3319 - in trunk/scipy/sparse: . tests
scipy-svn at scipy.org
scipy-svn at scipy.org
Tue Sep 18 11:04:56 EDT 2007
Author: rc
Date: 2007-09-18 10:04:50 -0500 (Tue, 18 Sep 2007)
New Revision: 3319
Modified:
trunk/scipy/sparse/sparse.py
trunk/scipy/sparse/tests/test_sparse.py
Log:
get_submatrix() for csc_matrix
csr_matrix, csc_matrix.__getitem__() now uses appropriate get_submatrix()
- indexing by row and column slices is possible, though it returns a new matrix,
not a view
Modified: trunk/scipy/sparse/sparse.py
===================================================================
--- trunk/scipy/sparse/sparse.py 2007-09-18 03:18:35 UTC (rev 3318)
+++ trunk/scipy/sparse/sparse.py 2007-09-18 15:04:50 UTC (rev 3319)
@@ -762,8 +762,51 @@
else:
return self._toother()._toother()
+ def _get_submatrix( self, shape0, shape1, slice0, slice1 ):
+ """Return a submatrix of this matrix (new matrix is created)."""
+ def _process_slice( sl, num ):
+ if isinstance( sl, slice ):
+ i0, i1 = sl.start, sl.stop
+ if i0 is None:
+ i0 = 0
+ elif i0 < 0:
+ i0 = num + i0
+ if i1 is None:
+ i1 = num
+ elif i1 < 0:
+ i1 = num + i1
+ return i0, i1
+
+ elif isscalar( sl ):
+ if sl < 0:
+ sl += num
+
+ return sl, sl + 1
+
+ else:
+ return sl[0], sl[1]
+
+ def _in_bounds( i0, i1, num ):
+ if not (0<=i0<num) or not (0<i1<=num) or not (i0<i1):
+ raise IndexError,\
+ "index out of bounds: 0<=%d<%d, 0<=%d<%d, %d<%d" %\
+ (i0, num, i1, num, i0, i1)
+
+ i0, i1 = _process_slice( slice0, shape0 )
+ j0, j1 = _process_slice( slice1, shape1 )
+ _in_bounds( i0, i1, shape0 )
+ _in_bounds( j0, j1, shape1 )
+
+ aux = sparsetools.get_csr_submatrix( shape0, shape1,
+ self.indptr, self.indices,
+ self.data,
+ i0, i1, j0, j1 )
+ data, indices, indptr = aux[2], aux[1], aux[0]
+ return data, indices, indptr, i1 - i0, j1 - j0
+
+
class csc_matrix(_cs_matrix):
""" Compressed sparse column matrix
This can be instantiated in several ways:
@@ -922,9 +965,12 @@
if (self.indptr[0] != 0):
raise ValueError,"index pointer should start with 0"
if (len(self.indptr) != N+1):
- raise ValueError, "index pointer should be of of size N+1"
+ raise ValueError, \
+ "index pointer size (%d) should be N+1 (%d)" %\
+ (len(self.indptr), N+1)
if (nzmax < nnz):
- raise ValueError, "nzmax must not be less than nnz"
+ raise ValueError, "nzmax (%d) must not be less than nnz (%d)" %\
+ (nzmax, nnz)
if full_check:
#check format validity (more expensive)
@@ -994,8 +1040,8 @@
row = key[0]
col = key[1]
if isinstance(col, slice):
- raise IndexError, "csc_matrix supports slices only of a single"\
- " column"
+ # Returns a new matrix!
+ return self.get_submatrix( row, col )
elif isinstance(row, slice):
return self._getslice(row, col)
M, N = self.shape
@@ -1123,6 +1169,14 @@
"""
return _cs_matrix._ensure_sorted_indices(self, self.shape[1], self.shape[0], inplace)
+ def get_submatrix( self, slice0, slice1 ):
+ """Return a submatrix of this matrix (new matrix is created).
+ Rows and columns can be selected using slice instances, tuples,
+ or scalars."""
+ aux = _cs_matrix._get_submatrix( self, self.shape[1], self.shape[0],
+ slice1, slice0 )
+ nr, nc = aux[3:]
+ return self.__class__( aux[:3], dims = (nc, nr) )
class csr_matrix(_cs_matrix):
""" Compressed sparse row matrix
@@ -1337,8 +1391,8 @@
row = key[0]
col = key[1]
if isinstance(row, slice):
- raise IndexError, "csr_matrix supports slices only of a single"\
- " row"
+ # Returns a new matrix!
+ return self.get_submatrix( row, col )
elif isinstance(col, slice):
return self._getslice(row, col)
M, N = self.shape
@@ -1466,16 +1520,13 @@
return _cs_matrix._ensure_sorted_indices(self, self.shape[0], self.shape[1], inplace)
def get_submatrix( self, slice0, slice1 ):
- """Return a submatrix of this matrix (new matrix is created)."""
- aux = sparsetools.get_csr_submatrix( self.shape[0], self.shape[1],
- self.indptr, self.indices,
- self.data,
- slice0.start, slice0.stop,
- slice1.start, slice1.stop )
- data, indices, indptr = aux[2], aux[1], aux[0]
- return self.__class__( (data, indices, indptr),
- dims = (slice0.stop - slice0.start,
- slice1.stop - slice1.start) )
+ """Return a submatrix of this matrix (new matrix is created)..
+ Rows and columns can be selected using slice instances, tuples,
+ or scalars."""
+ aux = _cs_matrix._get_submatrix( self, self.shape[0], self.shape[1],
+ slice0, slice1 )
+ nr, nc = aux[3:]
+ return self.__class__( aux[:3], dims = (nr, nc) )
# This function was for sorting dictionary keys by the second tuple element.
# (We now use the Schwartzian transform instead for efficiency.)
Modified: trunk/scipy/sparse/tests/test_sparse.py
===================================================================
--- trunk/scipy/sparse/tests/test_sparse.py 2007-09-18 03:18:35 UTC (rev 3318)
+++ trunk/scipy/sparse/tests/test_sparse.py 2007-09-18 15:04:50 UTC (rev 3319)
@@ -361,7 +361,7 @@
class _test_horiz_slicing:
- """Tests vertical slicing (e.g. [:, 0]). Tests for individual sparse
+ """Tests horizontal slicing (e.g. [:, 0]). Tests for individual sparse
matrix types that implement this should derive from this class.
"""
def check_get_horiz_slice(self):
@@ -428,6 +428,23 @@
caught += 1
assert caught == 2
+class _test_slicing:
+ """Tests vertical and horizontal slicing (e.g. [:,0:2]). Tests for
+ individual sparse matrix types that implement this should derive from this
+ class.
+ """
+ def check_get_slices(self):
+ B = asmatrix(arange(50.).reshape(5,10))
+ A = self.spmatrix(B)
+ assert_array_equal(B[2:5,0:3], A[2:5,0:3].todense())
+ assert_array_equal(B[1:,:-1], A[1:,:-1].todense())
+ assert_array_equal(B[:-1,1:], A[:-1,1:].todense())
+
+ # Now test slicing when a column contains only zeros
+ E = matrix([[1, 0, 1], [4, 0, 0], [0, 0, 0], [0, 0, 1]])
+ F = self.spmatrix(E)
+ assert_array_equal(E[1:2, 1:2], F[1:2, 1:2].todense())
+ assert_array_equal(E[:, 1:], F[:, 1:].todense())
class _test_fancy_indexing:
"""Tests fancy indexing features. The tests for any matrix formats
@@ -574,7 +591,8 @@
-class test_csr(_test_cs, _test_horiz_slicing, _test_arith, NumpyTestCase):
+class test_csr(_test_cs, _test_horiz_slicing, _test_vert_slicing,
+ _test_slicing, _test_arith, NumpyTestCase):
spmatrix = csr_matrix
def check_constructor1(self):
@@ -642,9 +660,9 @@
assert_equal( asp[ir, ic], bsp[ir, ic] )
def check_get_submatrix(self):
- a = csr_matrix( array([[1,2,3],[1,2,3],[0,2,0]]) )
+ a = csr_matrix( array([[1,2,3,4],[1,2,3,5],[0,2,0,1]]) )
i0 = slice( 0, 2 )
- i1 = slice( 1, 3 )
+ i1 = ( 1, 3 )
b = a.get_submatrix( i0, i1 )
aa = a.toarray()
@@ -652,9 +670,10 @@
assert b.dtype == a.dtype
assert b.shape == (2,2)
- assert_equal( ab, aa[i0,i1] )
+ assert_equal( ab, aa[i0,i1[0]:i1[1]] )
-class test_csc(_test_cs, _test_vert_slicing, _test_arith, NumpyTestCase):
+class test_csc(_test_cs, _test_horiz_slicing, _test_vert_slicing,
+ _test_slicing, _test_arith, NumpyTestCase):
spmatrix = csc_matrix
def check_constructor1(self):
@@ -713,6 +732,19 @@
for ic in range( asp.shape[1] ):
assert_equal( asp[ir, ic], bsp[ir, ic] )
+ def check_get_submatrix(self):
+ a = csc_matrix( array([[1,2,3,4],[1,2,3,5],[0,2,0,1]]) )
+ i0 = slice( 0, 2 )
+ i1 = ( 1, 3 )
+ b = a.get_submatrix( i0, i1 )
+
+ aa = a.toarray()
+ ab = b.toarray()
+
+ assert b.dtype == a.dtype
+ assert b.shape == (2,2)
+ assert_equal( ab, aa[i0,i1[0]:i1[1]] )
+
class test_dok(_test_cs, NumpyTestCase):
spmatrix = dok_matrix
More information about the Scipy-svn
mailing list