1
2
3
4
5
6
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
21
22 @sweepargs(oblique=(False,True))
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
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
37
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
54 d = d_orig[:, :nf_s]
55 d_s = d + t1
56 d_t = N.dot(s * d, R) + t2
57
58
59 pm.train(d_s, d_t)
60 ds2 = Dataset(samples=d_s, labels=d_t)
61 pm2.train(ds2)
62
63
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
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
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
109
110 if __name__ == '__main__':
111 import runner
112