Package mvpa :: Package tests :: Module test_procrust

[hide private]
[frames] | no frames]

# Source Code for Module mvpa.tests.test_procrust

      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 Procrustean mapper"""
     10
     11
     12  import unittest
     13  import numpy as N
     14  from numpy.linalg import norm
     15  from mvpa.datasets import Dataset
     16  from tests_warehouse import datasets, sweepargs
     17  from mvpa.mappers.procrustean import ProcrusteanMapper
     18
     19
     20 -class ProcrusteanMapperTests(unittest.TestCase):
     21
     22      @sweepargs(oblique=(False,True))
     23 -    def testSimple(self, oblique):
     24          d_orig = datasets['uni2large'].samples
     25          d_orig2 = datasets['uni4large'].samples
     26          for sdim, nf_s, nf_t, full_test \
     27                  in (('Same 2D',  2,  2,  True),
     28                      ('Same 10D', 10, 10, True),
     29                      ('2D -> 3D', 2,  3,  True),
     30                      ('3D -> 2D', 3,  2,  False)):
     31              # figure out some "random" rotation
     32              d = max(nf_s, nf_t)
     33              _u, _s, _vh = N.linalg.svd(d_orig[:, :d])
     34              R = _vh[:nf_s, :nf_t]
     35              if nf_s == nf_t:
     36                  # Test if it is indeed a rotation matrix ;)
     37                  # Lets flip first axis if necessary
     38                  if N.linalg.det(R) < 0:
     39                      R[:, 0] *= -1.0
     40                  adR = N.abs(1.0 - N.linalg.det(R))
     41                  self.failUnless(adR < 1e-10,
     42                                  "Determinant of rotation matrix should "
     43                                  "be 1. Got it 1+%g" % adR)
     44                  self.failUnless(norm(N.dot(R, R.T)
     45                                       - N.eye(R.shape[0])) < 1e-10)
     46
     47              for s, scaling in ((0.3, True), (1.0, False)):
     48                  pm = ProcrusteanMapper(scaling=scaling, oblique=oblique)
     49                  pm2 = ProcrusteanMapper(scaling=scaling, oblique=oblique)
     50
     51                  t1, t2 = d_orig[23, 1], d_orig[22, 1]
     52
     53                  # Create source/target data
     54                  d = d_orig[:, :nf_s]
     55                  d_s = d + t1
     56                  d_t = N.dot(s * d, R) + t2
     57
     58                  # train bloody mapper(s)
     59                  pm.train(d_s, d_t)
     60                  ds2 = Dataset(samples=d_s, labels=d_t)
     61                  pm2.train(ds2)
     62
     63                  # verify that both created the same transformation
     64                  npm2proj = norm(pm.proj - pm2.proj)
     65                  self.failUnless(npm2proj <= 1e-10,
     66                                  msg="Got transformation different by norm %g."
     67                                  " Had to be less than 1e-10" % npm2proj)
     68                  self.failUnless(norm(pm._offset_in - pm2._offset_in) <= 1e-10)
     69                  self.failUnless(norm(pm._offset_out - pm2._offset_out) <= 1e-10)
     70
     71                  # do forward transformation on the same source data
     72                  d_s_f = pm.forward(d_s)
     73
     74                  self.failUnlessEqual(d_s_f.shape, d_t.shape,
     75                      msg="Mapped shape should be identical to the d_t")
     76
     77                  dsf = d_s_f - d_t
     78                  ndsf = norm(dsf)/norm(d_t)
     79                  if full_test:
     80                      dsR = norm(s*R - pm.proj)
     81
     82                      if not oblique:
     83                          self.failUnless(dsR <= 1e-12,
     84                              msg="We should have got reconstructed rotation+scaling "
     85                                  "perfectly. Now got d scale*R=%g" % dsR)
     86
     87                          self.failUnless(N.abs(s - pm._scale) < 1e-12,
     88                              msg="We should have got reconstructed scale "
     89                                  "perfectly. Now got %g for %g" % (pm._scale, s))
     90
     91                      self.failUnless(ndsf <= 1e-12,
     92                        msg="%s: Failed to get to the target space correctly."
     93                          " normed error=%g" % (sdim, ndsf))
     94
     95                  # Test if we get back
     96                  d_s_f_r = pm.reverse(d_s_f)
     97
     98                  dsfr = d_s_f_r - d_s
     99                  ndsfr = norm(dsfr)/norm(d_s)
    100                  if full_test:
    101                      self.failUnless(ndsfr <= 1e-12,
    102                        msg="%s: Failed to reconstruct into source space correctly."
    103                          " normed error=%g" % (sdim, ndsfr))
    104
    105
    106
    107 -def suite():
    108      return unittest.makeSuite(ProcrusteanMapperTests)
    109
    110  if __name__ == '__main__':
    111      import runner
    112