Merge branch 'features/pca_jaxb_datasetrefs_JAL-3171_JAL-3063_JAL-1767' into develop
[jalview.git] / test / jalview / math / RotatableMatrixTest.java
1 package jalview.math;
2
3 import static org.testng.Assert.assertEquals;
4
5 import jalview.math.RotatableMatrix.Axis;
6
7 import org.testng.annotations.BeforeMethod;
8 import org.testng.annotations.Test;
9
10 public class RotatableMatrixTest
11 {
12   private RotatableMatrix rm;
13
14   @BeforeMethod(alwaysRun = true)
15   public void setUp()
16   {
17     rm = new RotatableMatrix();
18
19     /*
20      * 0.5 1.0 1.5
21      * 1.0 2.0 3.0
22      * 1.5 3.0 4.5
23      */
24     for (int i = 1; i <= 3; i++)
25     {
26       for (int j = 1; j <= 3; j++)
27       {
28         rm.setValue(i - 1, j - 1, i * j / 2f);
29       }
30     }
31   }
32
33   @Test(groups = "Functional")
34   public void testPreMultiply()
35   {
36     float[][] pre = new float[3][3];
37     int i = 1;
38     for (int j = 0; j < 3; j++)
39     {
40       for (int k = 0; k < 3; k++)
41       {
42         pre[j][k] = i++;
43       }
44     }
45
46     rm.preMultiply(pre);
47
48     /*
49      * check rm[i, j] is now the product of the i'th row of pre
50      * and the j'th column of (original) rm
51      */
52     for (int j = 0; j < 3; j++)
53     {
54       for (int k = 0; k < 3; k++)
55       {
56         float expected = 0f;
57         for (int l = 0; l < 3; l++)
58         {
59           float rm_l_k = (l + 1) * (k + 1) / 2f;
60           expected += pre[j][l] * rm_l_k;
61         }
62         assertEquals(rm.getValue(j, k), expected,
63                 String.format("[%d, %d]", j, k));
64       }
65     }
66   }
67
68   @Test(groups = "Functional")
69   public void testVectorMultiply()
70   {
71     float[] result = rm.vectorMultiply(new float[] { 2f, 3f, 4.5f });
72
73     // vector times first column of matrix
74     assertEquals(result[0], 2f * 0.5f + 3f * 1f + 4.5f * 1.5f);
75
76     // vector times second column of matrix
77     assertEquals(result[1], 2f * 1.0f + 3f * 2f + 4.5f * 3f);
78
79     // vector times third column of matrix
80     assertEquals(result[2], 2f * 1.5f + 3f * 3f + 4.5f * 4.5f);
81   }
82
83   @Test(groups = "Functional")
84   public void testGetRotation()
85   {
86     float theta = 60f;
87     double cosTheta = Math.cos((theta * Math.PI / 180f));
88     double sinTheta = Math.sin((theta * Math.PI / 180f));
89
90     /*
91      * sanity check that sin(60) = sqrt(3) / 2, cos(60) = 1/2
92      */
93     double delta = 0.0001d;
94     assertEquals(cosTheta, 0.5f, delta);
95     assertEquals(sinTheta, Math.sqrt(3d) / 2d, delta);
96
97     /*
98      * so far so good, now verify rotations
99      * @see https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
100      */
101
102     /*
103      * 60 degrees about X axis should be
104      *  1   0   0 
105      *  0  cos -sin
106      *  0  sin cos
107      *  but code applies the negative of this
108      *  nb cos(-x) = cos(x), sin(-x) = -sin(x)
109      */
110     float[][] rot = RotatableMatrix.getRotation(theta, Axis.X);
111     assertEquals(rot[0][0], 1f, delta);
112     assertEquals(rot[0][1], 0f, delta);
113     assertEquals(rot[0][2], 0f, delta);
114     assertEquals(rot[1][0], 0f, delta);
115     assertEquals(rot[1][1], cosTheta, delta);
116     assertEquals(rot[1][2], sinTheta, delta);
117     assertEquals(rot[2][0], 0f, delta);
118     assertEquals(rot[2][1], -sinTheta, delta);
119     assertEquals(rot[2][2], cosTheta, delta);
120
121     /*
122      * 60 degrees about Y axis should be
123      *   cos 0 sin
124      *    0  1  0
125      *  -sin 0 cos
126      *  but code applies the negative of this
127      */
128     rot = RotatableMatrix.getRotation(theta, Axis.Y);
129     assertEquals(rot[0][0], cosTheta, delta);
130     assertEquals(rot[0][1], 0f, delta);
131     assertEquals(rot[0][2], -sinTheta, delta);
132     assertEquals(rot[1][0], 0f, delta);
133     assertEquals(rot[1][1], 1f, delta);
134     assertEquals(rot[1][2], 0f, delta);
135     assertEquals(rot[2][0], sinTheta, delta);
136     assertEquals(rot[2][1], 0f, delta);
137     assertEquals(rot[2][2], cosTheta, delta);
138
139     /*
140      * 60 degrees about Z axis should be
141      *  cos -sin 0
142      *  sin  cos 0
143      *   0    0  1
144      * - and it is!
145      */
146     rot = RotatableMatrix.getRotation(theta, Axis.Z);
147     assertEquals(rot[0][0], cosTheta, delta);
148     assertEquals(rot[0][1], -sinTheta, delta);
149     assertEquals(rot[0][2], 0f, delta);
150     assertEquals(rot[1][0], sinTheta, delta);
151     assertEquals(rot[1][1], cosTheta, delta);
152     assertEquals(rot[1][2], 0f, delta);
153     assertEquals(rot[2][0], 0f, delta);
154     assertEquals(rot[2][1], 0f, delta);
155     assertEquals(rot[2][2], 1f, delta);
156   }
157 }