[Scipy-svn] r3959 - in trunk/scipy/sparse: . tests

scipy-svn@scip... scipy-svn@scip...
Tue Feb 26 23:35:40 CST 2008


Author: wnbell
Date: 2008-02-26 23:35:35 -0600 (Tue, 26 Feb 2008)
New Revision: 3959

Modified:
   trunk/scipy/sparse/csc.py
   trunk/scipy/sparse/csr.py
   trunk/scipy/sparse/tests/test_base.py
Log:
added fancy indexing to CSC matrix


Modified: trunk/scipy/sparse/csc.py
===================================================================
--- trunk/scipy/sparse/csc.py	2008-02-26 20:55:11 UTC (rev 3958)
+++ trunk/scipy/sparse/csc.py	2008-02-27 05:35:35 UTC (rev 3959)
@@ -7,12 +7,12 @@
 import numpy
 from numpy import array, matrix, asarray, asmatrix, zeros, rank, intc, \
         empty, hstack, isscalar, ndarray, shape, searchsorted, where, \
-        concatenate, deprecate
+        concatenate, deprecate, transpose, ravel
 
 from base import spmatrix, isspmatrix
 from sparsetools import csc_tocsr
 from sputils import upcast, to_native, isdense, isshape, getdtype, \
-        isscalarlike
+        isscalarlike, isintlike
 
 from compressed import _cs_matrix
 
@@ -131,7 +131,38 @@
         A.has_sorted_indices = True
         return A
 
-    
+
+    def __getitem__(self, key):
+        # use CSR to implement fancy indexing
+        if isinstance(key, tuple):
+            row = key[0]
+            col = key[1]
+
+            if isintlike(row) or isinstance(row, slice):
+                return self.T[col,row].T                
+            else:    
+                #[[1,2],??] or [[[1],[2]],??]
+                if isintlike(col) or isinstance(col,slice):
+                    return self.T[col,row].T                
+                else:
+                    row = asarray(row, dtype='intc')
+                    col = asarray(col, dtype='intc')
+                    if len(row.shape) == 1:
+                        return self.T[col,row]
+                    elif len(row.shape) == 2:
+                        row = row.reshape(-1)
+                        col = col.reshape(-1,1)
+                        return self.T[col,row].T                
+                    else:
+                        raise NotImplementedError('unsupported indexing')
+                        
+            return self.T[col,row].T
+        elif isintlike(key) or isinstance(key,slice):
+            return self.T[:,key].T                              #[i] or [1:2]
+        else:
+            return self.T[:,key].T                              #[[1,2]]
+
+
     # these functions are used by the parent class (_cs_matrix)
     # to remove redudancy between csc_matrix and csr_matrix
     def _swap(self,x):

Modified: trunk/scipy/sparse/csr.py
===================================================================
--- trunk/scipy/sparse/csr.py	2008-02-26 20:55:11 UTC (rev 3958)
+++ trunk/scipy/sparse/csr.py	2008-02-27 05:35:35 UTC (rev 3959)
@@ -8,7 +8,7 @@
 import numpy
 from numpy import array, matrix, asarray, asmatrix, zeros, rank, intc, \
         empty, hstack, isscalar, ndarray, shape, searchsorted, where, \
-        concatenate, deprecate, arange, ones
+        concatenate, deprecate, arange, ones, ravel
 
 from base import spmatrix, isspmatrix
 from sparsetools import csr_tocsc, csr_tobsr, csr_count_blocks, \
@@ -240,22 +240,34 @@
                 else:
                     P = extractor(col,self.shape[1]).T        #[1:2,[1,2]]
                     return self[row,:]*P
+                
             else:    
-                #[[1,2],??]
+                #[[1,2],??] or [[[1],[2]],??]
                 if isintlike(col) or isinstance(col,slice):
-                    P = extractor(row, self.shape[0])         
-                    return (P*self)[:,col]                   #[[1,2],j] or [[1,2],1:2] 
+                    P = extractor(row, self.shape[0])        #[[1,2],j] or [[1,2],1:2]   
+                    return (P*self)[:,col]                   
+
                 else:
-                    row = asindices(row)                     #[[1,2],[1,2]]
-                    col = asindices(col)
-                    if len(row) != len(col):
-                        raise IndexError('number of row and column indices differ')
-                    val = []
-                    for i,j in zip(row,col):
-                        val.append(self._get_single_element(i,j))
-                    return asmatrix(val)
+                    row = asindices(row)                     
+                    col = asindices(col) 
+                    if len(row.shape) == 1:
+                        if len(row) != len(col):             #[[1,2],[1,2]]
+                            raise IndexError('number of row and column indices differ')
+                        val = []
+                        for i,j in zip(row,col):
+                            val.append(self._get_single_element(i,j))
+                        return asmatrix(val)
+                    
+                    elif len(row.shape) == 2:
+                        row = ravel(row)                    #[[[1],[2]],[1,2]]
+                        P = extractor(row, self.shape[0])   
+                        return (P*self)[:,col]               
 
+                    else:
+                        raise NotImplementedError('unsupported indexing')
+                        
 
+
         elif isintlike(key) or isinstance(key,slice):
             return self[key,:]                                #[i] or [1:2]
         else:

Modified: trunk/scipy/sparse/tests/test_base.py
===================================================================
--- trunk/scipy/sparse/tests/test_base.py	2008-02-26 20:55:11 UTC (rev 3958)
+++ trunk/scipy/sparse/tests/test_base.py	2008-02-27 05:35:35 UTC (rev 3959)
@@ -651,24 +651,69 @@
     """Tests fancy indexing features.  The tests for any matrix formats
     that implement these features should derive from this class.
     """
-    # This isn't supported by any matrix objects yet:
-    def test_sequence_indexing(self):
-        B = asmatrix(arange(50.).reshape(5,10))
-        A = self.spmatrix(B)
-        assert_array_equal(B[(1,2),(3,4)], A[(1,2),(3,4)].todense())
-        assert_array_equal(B[(1,2,3),(3,4,5)], A[(1,2,3),(3,4,5)].todense())
-
     def test_fancy_indexing(self):
-        """Test for new indexing functionality"""
-        B = ones((5,10), float)
-        A = dok_matrix(B)
-        # Write me!
+        B = asmatrix(arange(50).reshape(5,10))
+        A = self.spmatrix( B )
 
-        # Both slicing and fancy indexing: not yet supported
-        # assert_array_equal(B[(1,2),:], A[(1,2),:].todense())
-        # assert_array_equal(B[(1,2,3),:], A[(1,2,3),:].todense())
+        # [i,j]
+        assert_equal(A[2,3],B[2,3])
+        assert_equal(A[-1,8],B[-1,8])
+        assert_equal(A[-1,-2],B[-1,-2])
 
+        # [i,1:2]
+        assert_equal(A[2,:].todense(),B[2,:])
+        assert_equal(A[2,5:-2].todense(),B[2,5:-2])
+       
+        # [i,[1,2]]
+        assert_equal(A[3,[1,3]].todense(),B[3,[1,3]])
+        assert_equal(A[-1,[2,-5]].todense(),B[-1,[2,-5]])
 
+        # [1:2,j]
+        assert_equal(A[:,2].todense(),B[:,2])
+        assert_equal(A[3:4,9].todense(),B[3:4,9])
+        assert_equal(A[1:4,-5].todense(),B[1:4,-5])
+
+        # [1:2,[1,2]]
+        assert_equal(A[:,[2,8,3,-1]].todense(),B[:,[2,8,3,-1]])
+        assert_equal(A[3:4,[9]].todense(),B[3:4,[9]])
+        assert_equal(A[1:4,[-1,-5]].todense(),B[1:4,[-1,-5]])
+
+        # [[1,2],j]
+        assert_equal(A[[1,3],3].todense(),B[[1,3],3])
+        assert_equal(A[[2,-5],-4].todense(),B[[2,-5],-4])
+        
+        # [[1,2],1:2]
+        assert_equal(A[[1,3],:].todense(),B[[1,3],:])
+        assert_equal(A[[2,-5],8:-1].todense(),B[[2,-5],8:-1])
+    
+        # [[1,2],[1,2]]
+        assert_equal(A[[1,3],[2,4]],B[[1,3],[2,4]])
+        assert_equal(A[[-1,-3],[2,-4]],B[[-1,-3],[2,-4]])
+        
+        # [[[1],[2]],[1,2]]
+        assert_equal(A[[[1],[3]],[2,4]].todense(),B[[[1],[3]],[2,4]])
+        assert_equal(A[[[-1],[-3],[-2]],[2,-4]].todense(),B[[[-1],[-3],[-2]],[2,-4]])
+
+        # [i]
+        assert_equal(A[1].todense(),B[1])
+        assert_equal(A[-2].todense(),B[-2])
+
+        # [1:2]
+        assert_equal(A[1:4].todense(),B[1:4])
+        assert_equal(A[1:-2].todense(),B[1:-2])
+
+        # [[1,2]]
+        assert_equal(A[[1,3]].todense(),B[[1,3]])
+        assert_equal(A[[-1,-3]].todense(),B[[-1,-3]])
+
+        # [[1,2],:][:,[1,2]]
+        assert_equal(A[[1,3],:][:,[2,4]].todense(),    B[[1,3],:][:,[2,4]]    )
+        assert_equal(A[[-1,-3],:][:,[2,-4]].todense(), B[[-1,-3],:][:,[2,-4]] )
+
+        # [:,[1,2]][[1,2],:]
+        assert_equal(A[:,[1,3]][[2,4],:].todense(),    B[:,[1,3]][[2,4],:]    )
+        assert_equal(A[:,[-1,-3]][[2,-4],:].todense(), B[:,[-1,-3]][[2,-4],:] )
+
 class _TestArithmetic:
     """
     Test real/complex arithmetic
@@ -768,7 +813,7 @@
 class TestCSR(_TestCommon, _TestGetSet, _TestSolve,
         _TestInplaceArithmetic, _TestArithmetic, _TestMatvecOutput,
         _TestHorizSlicing, _TestVertSlicing, _TestBothSlicing,
-        TestCase):
+        _TestFancyIndexing, TestCase):
     spmatrix = csr_matrix
 
     def test_constructor1(self):
@@ -861,70 +906,11 @@
         assert_array_equal(asp.todense(),bsp.todense())
 
 
-    def test_fancy_slicing(self):
-        #TODO add this to csc_matrix
-        B = asmatrix(arange(50).reshape(5,10))
-        A = csr_matrix( B )
 
-        # [i,j]
-        assert_equal(A[2,3],B[2,3])
-        assert_equal(A[-1,8],B[-1,8])
-        assert_equal(A[-1,-2],B[-1,-2])
-
-        # [i,1:2]
-        assert_equal(A[2,:].todense(),B[2,:])
-        assert_equal(A[2,5:-2].todense(),B[2,5:-2])
-       
-        # [i,[1,2]]
-        assert_equal(A[3,[1,3]].todense(),B[3,[1,3]])
-        assert_equal(A[-1,[2,-5]].todense(),B[-1,[2,-5]])
-
-        # [1:2,j]
-        assert_equal(A[:,2].todense(),B[:,2])
-        assert_equal(A[3:4,9].todense(),B[3:4,9])
-        assert_equal(A[1:4,-5].todense(),B[1:4,-5])
-
-        # [1:2,[1,2]]
-        assert_equal(A[:,[2,8,3,-1]].todense(),B[:,[2,8,3,-1]])
-        assert_equal(A[3:4,[9]].todense(),B[3:4,[9]])
-        assert_equal(A[1:4,[-1,-5]].todense(),B[1:4,[-1,-5]])
-
-        # [[1,2],j]
-        assert_equal(A[[1,3],3].todense(),B[[1,3],3])
-        assert_equal(A[[2,-5],-4].todense(),B[[2,-5],-4])
-        
-        # [[1,2],1:2]
-        assert_equal(A[[1,3],:].todense(),B[[1,3],:])
-        assert_equal(A[[2,-5],8:-1].todense(),B[[2,-5],8:-1])
-    
-        # [[1,2],[1,2]]
-        assert_equal(A[[1,3],[2,4]],B[[1,3],[2,4]])
-        assert_equal(A[[-1,-3],[2,-4]],B[[-1,-3],[2,-4]])
-
-        # [i]
-        assert_equal(A[1].todense(),B[1])
-        assert_equal(A[-2].todense(),B[-2])
-
-        # [1:2]
-        assert_equal(A[1:4].todense(),B[1:4])
-        assert_equal(A[1:-2].todense(),B[1:-2])
-
-        # [[1,2]]
-        assert_equal(A[[1,3]].todense(),B[[1,3]])
-        assert_equal(A[[-1,-3]].todense(),B[[-1,-3]])
-
-        # [[1,2],:][:,[1,2]]
-        assert_equal(A[[1,3],:][:,[2,4]].todense(),    B[[1,3],:][:,[2,4]]    )
-        assert_equal(A[[-1,-3],:][:,[2,-4]].todense(), B[[-1,-3],:][:,[2,-4]] )
-
-        # [:,[1,2]][[1,2],:]
-        assert_equal(A[:,[1,3]][[2,4],:].todense(),    B[:,[1,3]][[2,4],:]    )
-        assert_equal(A[:,[-1,-3]][[2,-4],:].todense(), B[:,[-1,-3]][[2,-4],:] )
-
 class TestCSC(_TestCommon, _TestGetSet, _TestSolve,
         _TestInplaceArithmetic, _TestArithmetic, _TestMatvecOutput,
         _TestHorizSlicing, _TestVertSlicing, _TestBothSlicing,
-        TestCase):
+        _TestFancyIndexing, TestCase):
     spmatrix = csc_matrix
 
     def test_constructor1(self):



More information about the Scipy-svn mailing list