Package mvpa :: Package tests :: Module test_maskeddataset

[hide private]
[frames] | no frames]

# Source Code for Module mvpa.tests.test_maskeddataset

      1  # emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
      2  # vi: set ft=python sts=4 ts=4 sw=4 et:
      3  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
      4  #
      5  #   See COPYING file distributed along with the PyMVPA package for the
      6  #   copyright and license terms.
      7  #
      8  ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
      9  """Unit tests for PyMVPA pattern handling"""
     10
     11  from mvpa.datasets.masked import *
     12  from mvpa.misc.exceptions import DatasetError
     13
     14  import unittest
     15  import numpy as N
     16  import random
     17
     18 -class MaskedDatasetTests(unittest.TestCase):
     19
     20 -    def testCreateMaskedDataset(self):
     21          data = MaskedDataset(samples=[range(5)], labels=1,
     22                               chunks=1)
     23          # simple sequence has to be a single pattern
     24          self.failUnlessEqual( data.nsamples, 1)
     25          # check correct pattern layout (1x5)
     26          self.failUnless(
     27              (data.samples == N.array([[0, 1, 2, 3, 4]])).all() )
     28
     29          # check for single label and origin
     30          self.failUnless( (data.labels == N.array([1])).all() )
     31          self.failUnless( (data.chunks == N.array([1])).all() )
     32
     33          # now try adding pattern with wrong shape
     34          self.failUnlessRaises(DatasetError,
     35                                data.__iadd__,
     36                                MaskedDataset(samples=N.ones((2,3)), labels=1,
     37                                              chunks=1))
     38
     39          # now add two real patterns
     40          data += MaskedDataset(samples=N.random.standard_normal((2,5)),
     41                                labels=2, chunks=2)
     42          self.failUnlessEqual( data.nsamples, 3 )
     43          self.failUnless( (data.labels == N.array([1,2,2]) ).all() )
     44          self.failUnless( (data.chunks == N.array([1,2,2]) ).all() )
     45
     46
     47          # test unique class labels
     48          data += MaskedDataset(samples=N.random.standard_normal((2,5)),
     49                                labels=3)
     50          self.failUnless( (data.uniquelabels == N.array([1,2,3]) ).all() )
     51
     52          # test wrong label length
     53          self.failUnlessRaises(DatasetError,
     54                                MaskedDataset,
     55                                samples=N.random.standard_normal((4,2,3,4)),
     56                                labels=[1, 2, 3],
     57                                chunks=2)
     58
     59          # test wrong origin length
     60          self.failUnlessRaises( DatasetError,
     61                                 MaskedDataset,
     62                                 samples=N.random.standard_normal((4,2,3,4)),
     63                                 labels=[1, 2, 3, 4],
     64                                 chunks=[2, 2, 2])
     65
     66
     67 -    def testShapeConversion(self):
     68          data = MaskedDataset(samples=N.arange(24).reshape((2,3,4)),
     69                               labels=1, chunks=1)
     70          self.failUnlessEqual(data.nsamples, 2)
     71          self.failUnlessEqual(data.samples.shape, (2,12))
     72          self.failUnless((data.samples ==
     73                           N.array([range(12),range(12,24)])).all())
     74
     75
     76 -    def testPatternShape(self):
     77          data = MaskedDataset(samples=N.ones((10,2,3,4)), labels=1, chunks=1)
     78          self.failUnless(data.samples.shape == (10,24))
     79
     80
     81 -    def testFeature2Coord(self):
     82          origdata = N.random.standard_normal((10,2,4,3,5))
     83          data = MaskedDataset( samples=origdata, labels=2, chunks=2 )
     84
     85          def randomCoord(shape):
     86              return [ random.sample(range(size),1)[0] for size in shape ]
     87
     88          # check 100 random coord2feature transformations
     89          for i in xrange(100):
     90              # choose random coord
     91              c = randomCoord((2,4,3,5))
     92              # tranform to feature_id
     93              id = data.mapper.getOutId(c)
     94
     95              # compare data from orig array (selected by coord)
     96              # and data from pattern array (selected by feature id)
     97              orig = origdata[:,c[0],c[1],c[2],c[3]]
     98              pat = data.samples[:, id]
     99
    100              self.failUnless((orig == pat).all())
    101
    102
    103 -    def testCoord2Feature(self):
    104          origdata = N.random.standard_normal((10,2,4,3,5))
    105          data = MaskedDataset(samples=origdata, labels=2, chunks=2)
    106
    107          def randomCoord(shape):
    108              return [ random.sample(range(size),1)[0] for size in shape ]
    109
    110          for id in xrange(data.nfeatures):
    111              # transform to coordinate
    112              c = data.mapper.getInId(id)
    113              self.failUnlessEqual(len(c), 4)
    114
    115              # compare data from orig array (selected by coord)
    116              # and data from pattern array (selected by feature id)
    117              orig = origdata[:,c[0],c[1],c[2],c[3]]
    118              pat = data.samples[:, id]
    119
    120              self.failUnless((orig == pat).all())
    121
    122
    123 -    def testFeatureSelection(self):
    124          origdata = N.random.standard_normal((10,2,4,3,5))
    125          data = MaskedDataset(samples=origdata, labels=2, chunks=2)
    126
    127          unmasked = data.samples.copy()
    128
    129          # default must be no mask
    130          self.failUnless( data.nfeatures == 120 )
    131          self.failUnless(data.mapper.getOutSize() == 120)
    132
    133          # check that full mask uses all features
    134          sel = data.selectFeaturesByMask( N.ones((2,4,3,5)) )
    135          self.failUnless( sel.nfeatures == data.samples.shape[1] )
    136          self.failUnless( data.nfeatures == 120 )
    137
    138          # check partial array mask
    139          partial_mask = N.zeros((2,4,3,5), dtype='uint')
    140          partial_mask[0,0,2,2] = 1
    141          partial_mask[1,2,2,0] = 1
    142
    143          sel = data.selectFeaturesByMask( partial_mask )
    144          self.failUnless( sel.nfeatures == 2 )
    145          self.failUnless( sel.mapper.getMask().shape == (2,4,3,5))
    146
    147          # check that feature selection does not change source data
    148          self.failUnless(data.nfeatures == 120)
    149          self.failUnlessEqual(data.mapper.getOutSize(), 120)
    150
    151          # check selection with feature list
    152          sel = data.selectFeatures([0,37,119])
    153          self.failUnless(sel.nfeatures == 3)
    154
    155          # check size of the masked patterns
    156          self.failUnless( sel.samples.shape == (10,3) )
    157
    158          # check that the right features are selected
    159          self.failUnless( (unmasked[:,[0,37,119]]==sel.samples).all() )
    160
    161
    162 -    def testPatternSelection(self):
    163          origdata = N.random.standard_normal((10,2,4,3,5))
    164          data = MaskedDataset(samples=origdata, labels=2, chunks=2)
    165
    166          self.failUnless( data.nsamples == 10 )
    167
    168          # set single pattern to enabled
    169          sel=data.selectSamples(5)
    170          self.failUnless( sel.nsamples == 1 )
    171          self.failUnless( data.nsamples == 10 )
    172
    173          # check duplicate selections
    174          sel = data.selectSamples([5,5])
    175          self.failUnless( sel.nsamples == 2 )
    176          self.failUnless( (sel.samples[0] == sel.samples[1]).all() )
    177          self.failUnless( len(sel.labels) == 2 )
    178          self.failUnless( len(sel.chunks) == 2 )
    179
    180          self.failUnless( sel.samples.shape == (2,120) )
    181
    182 -    def testCombinedPatternAndFeatureMasking(self):
    183          data = MaskedDataset(
    184              samples=N.arange( 20 ).reshape( (4,5) ), labels=1, chunks=1 )
    185
    186          self.failUnless( data.nsamples == 4 )
    187          self.failUnless( data.nfeatures == 5 )
    188          fsel = data.selectFeatures([1,2])
    189          fpsel = fsel.selectSamples([0,3])
    190          self.failUnless( fpsel.nsamples == 2 )
    191          self.failUnless( fpsel.nfeatures == 2 )
    192
    193          self.failUnless( (fpsel.samples == [[1,2],[16,17]]).all() )
    194
    195
    196 -    def testOrigMaskExtraction(self):
    197          origdata = N.random.standard_normal((10,2,4,3))
    198          data = MaskedDataset(samples=origdata, labels=2, chunks=2)
    199
    200          # check with custom mask
    201          sel = data.selectFeatures([5])
    202          self.failUnless( sel.samples.shape[1] == 1 )
    203          origmask = sel.mapper.getMask()
    204          self.failUnless( origmask[0,1,2] == True )
    205          self.failUnless( origmask.shape == (2,4,3) )
    206
    207
    208
    209 -    def testPatternMerge(self):
    210          data1 = MaskedDataset(samples=N.ones((5,5,1)), labels=1, chunks=1)
    211          data2 = MaskedDataset(samples=N.ones((3,5,1)), labels=2, chunks=1)
    212
    213          merged = data1 + data2
    214
    215          self.failUnless(merged.nsamples == 8 )
    216          self.failUnless((merged.labels == [ 1,1,1,1,1,2,2,2]).all())
    217          self.failUnless((merged.chunks == [ 1,1,1,1,1,1,1,1]).all())
    218
    219          data1 += data2
    220
    221          self.failUnless(data1.nsamples == 8 )
    222          self.failUnless((data1.labels == [ 1,1,1,1,1,2,2,2]).all())
    223          self.failUnless((data1.chunks == [ 1,1,1,1,1,1,1,1]).all())
    224
    225
    226 -    def testLabelRandomizationAndSampling(self):
    227          data = MaskedDataset(samples=N.ones((5,1)), labels=range(5), chunks=1)
    228          data += MaskedDataset(samples=N.ones((5,1))+1, labels=range(5), chunks=2)
    229          data += MaskedDataset(samples=N.ones((5,1))+2, labels=range(5), chunks=3)
    230          data += MaskedDataset(samples=N.ones((5,1))+3, labels=range(5), chunks=4)
    231          data += MaskedDataset(samples=N.ones((5,1))+4, labels=range(5), chunks=5)
    232          self.failUnless( data.samplesperlabel == {0:5, 1:5, 2:5, 3:5, 4:5} )
    233
    234          sample = data.getRandomSamples( 2 )
    235          self.failUnless( sample.samplesperlabel.values() == [ 2,2,2,2,2 ] )
    236
    237          self.failUnless( (data.uniquechunks == range(1,6)).all() )
    238
    239          # store the old labels
    240          origlabels = data.labels.copy()
    241
    242          data.permuteLabels(True)
    243
    244          self.failIf( (data.labels == origlabels).all() )
    245
    246          data.permuteLabels(False)
    247
    248          self.failUnless( (data.labels == origlabels).all() )
    249
    250          # now try another object with the same data
    251          data2 = MaskedDataset(samples=data.samples, labels=data.labels,
    252                                chunks=data.chunks )
    253
    254          # labels are the same as the originals
    255          self.failUnless( (data2.labels == origlabels).all() )
    256
    257          # now permute in the new object
    258          data2.permuteLabels( True )
    259
    260          # must not affect the old one
    261          self.failUnless( (data.labels == origlabels).all() )
    262          # but only the new one
    263          self.failIf( (data2.labels == origlabels).all() )
    264
    265
    266 -    def testFeatureMasking(self):
    267          mask = N.zeros((5,3),dtype='bool')
    268          mask[2,1] = True; mask[4,0] = True
    269          data = MaskedDataset(
    270              samples=N.arange( 60 ).reshape( (4,5,3) ), labels=1, chunks=1,
    271              mask=mask)
    272
    273          # check simple masking
    274          self.failUnless( data.nfeatures == 2 )
    275          self.failUnless( data.mapper.getOutId( (2,1) ) == 0
    276                       and data.mapper.getOutId( (4,0) ) == 1 )
    277          self.failUnlessRaises( ValueError, data.mapper.getOutId, (2,3) )
    278          self.failUnless( data.mapper.getMask().shape == (5,3) )
    279          self.failUnless( tuple(data.mapper.getInId( 1 )) == (4,0) )
    280
    281          # selection should be idempotent
    282          self.failUnless(data.selectFeaturesByMask( mask ).nfeatures == data.nfeatures )
    283          # check that correct feature get selected
    284          self.failUnless( (data.selectFeatures([1]).samples[:,0] \
    285                            == N.array([12, 27, 42, 57]) ).all() )
    286          self.failUnless(tuple( data.selectFeatures([1]).mapper.getInId(0) ) == (4,0) )
    287          self.failUnless( data.selectFeatures([1]).mapper.getMask().sum() == 1 )
    288
    289          # check sugarings
    290          # Access to simple attributes and samples
    291          self.failUnless(N.all(data.I == data.origids))
    292          self.failUnless(N.all(data.C == data.chunks))
    293          self.failUnless(N.all(data.L == data.labels))
    294          self.failUnless(N.all(data.S == data.samples))
    295          self.failUnless(N.all(data.O == data.mapper.reverse(data.samples)))
    296
    297          # Access to unique attributes
    298          self.failUnless(N.all(data.UC == data.uniquechunks))
    299          self.failUnless(N.all(data.UL == data.uniquelabels))
    300
    301
    302  #    def testROIMasking(self):
    303  #        mask=N.array([i/6 for i in range(60)], dtype='int').reshape(6,10)
    304  #        data = MaskedDataset(
    305  #            N.arange( 180 ).reshape( (3,6,10) ), 1, 1, mask=mask )
    306  #
    307  #        self.failIf( data.mapper.getMask().dtype == 'bool' )
    308  #        # check that the 0 masked features get cut
    309  #        self.failUnless( data.nfeatures == 54 )
    310  #        self.failUnless( (data.samples[:,0] == [6,66,126]).all() )
    311  #        self.failUnless( data.mapper.getMask().shape == (6,10) )
    312  #
    313  #        featsel = data.selectFeatures([19])
    314  #        self.failUnless( (data.samples[:,19] == featsel.samples[:,0]).all() )
    315  #
    316  #        # check single ROI selection works
    317  #        roisel = data.selectFeaturesByGroup([4])
    318  #        self.failUnless( (data.samples[:,19] == roisel.samples[:,1]).all() )
    319  #
    320  #        # check dual ROI selection works (plus keep feature order)
    321  #        roisel = data.selectFeaturesByGroup([6,4])
    322  #        self.failUnless( (data.samples[:,19] == roisel.samples[:,1]).all() )
    323  #        self.failUnless( (data.samples[:,32] == roisel.samples[:,8]).all() )
    324  #
    325  #        # check if feature coords can be recovered
    326  #        self.failUnless( (roisel.getCoordinate(8) == (3,8)).all() )
    327
    328
    329 -def suite():
    330      return unittest.makeSuite(MaskedDatasetTests)
    331
    332
    333  if __name__ == '__main__':
    334      import runner
    335