package org.biojava.nbio.structure.symmetry.internal; import static org.junit.Assert.*; import java.util.Arrays; import java.util.List; import javax.vecmath.AxisAngle4d; import javax.vecmath.Matrix4d; import javax.vecmath.Point3d; import javax.vecmath.Vector3d; import org.biojava.nbio.structure.symmetry.internal.CESymmParameters.SymmetryType; import org.biojava.nbio.structure.symmetry.internal.SymmetryAxes.Axis; import org.junit.Test; public class TestSymmetryAxes { @Test public void testClosedCase() { // D4 case SymmetryAxes axes = new SymmetryAxes(); // Level 1 is C4 along Z Matrix4d r90 = new Matrix4d(); r90.set(new AxisAngle4d(0, 0, 1, -Math.PI/2)); axes.addAxis(r90, 4, SymmetryType.CLOSED); // Level 2 is C2 along X Matrix4d r180 = new Matrix4d(); r180.set(new AxisAngle4d(1, 0, 0, Math.PI)); axes.addAxis(r180, 2, SymmetryType.CLOSED); assertEquals(2,axes.getElementaryAxes().size()); Matrix4d expectedEven = new Matrix4d(); expectedEven.setIdentity(); Matrix4d expectedOdd = new Matrix4d(r180); assertEquals(expectedEven, axes.getRepeatTransform(0)); assertEquals(expectedOdd, axes.getRepeatTransform(1)); expectedEven.mul(r90); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(2)); assertEquals(expectedOdd, axes.getRepeatTransform(3)); expectedEven.mul(r90); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(4)); assertEquals(expectedOdd, axes.getRepeatTransform(5)); expectedEven.mul(r90); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(6)); assertEquals(expectedOdd, axes.getRepeatTransform(7)); // Test Cauchy Form List<List<Integer>> relation = Arrays.asList( Arrays.asList(0,1,2,3,4,5,6,7), Arrays.asList(2,3,4,5,6,7,0,1) ); assertEquals(relation,axes.getRepeatRelation(0)); relation = Arrays.asList( Arrays.asList(0,1), Arrays.asList(1,0) ); assertEquals(relation,axes.getRepeatRelation(1)); relation = Arrays.asList( Arrays.asList(2,3), Arrays.asList(3,2) ); assertEquals(relation,axes.getRepeatRelation(1,2)); try { axes.getRepeatRelation(2); fail("Invalid level"); } catch(IndexOutOfBoundsException e) {} try { axes.getRepeatRelation(1,1); fail("Invalid firstRepeat"); } catch(IllegalArgumentException e) {} // Test Cyclic Form relation = Arrays.asList( Arrays.asList(0,2,4,6), Arrays.asList(1,3,5,7) ); assertEquals(relation,axes.getRepeatsCyclicForm(0)); relation = Arrays.asList( Arrays.asList(0,1) ); assertEquals(relation,axes.getRepeatsCyclicForm(1)); relation = Arrays.asList( Arrays.asList(2,3) ); assertEquals(relation,axes.getRepeatsCyclicForm(1,2)); try { axes.getRepeatsCyclicForm(2); fail("Invalid level"); } catch(IndexOutOfBoundsException e) {} try { axes.getRepeatsCyclicForm(1,1); fail("Invalid firstRepeat"); } catch(IllegalArgumentException e) {} // Expected location of each repeat Point3d[] repeats = new Point3d[] { new Point3d(1,1,1), new Point3d(1,-1,-1), new Point3d(-1,1,1), new Point3d(1,1,-1), new Point3d(-1,-1,1), new Point3d(-1,1,-1), new Point3d(1,-1,1), new Point3d(-1,-1,-1) }; // Inverse of (1,1,1) should give above points for(int i=0;i<8;i++) { Matrix4d m = axes.getRepeatTransform(i); m.invert(); Point3d x = new Point3d(repeats[0]); m.transform(x); assertTrue("Transformation "+i+"^-1 of "+repeats[0]+ "="+x+" not "+repeats[i],x.epsilonEquals(repeats[i], 1e-5)); } // Forward should map the above points onto the first one for(int i=0;i<8;i++) { Matrix4d m = axes.getRepeatTransform(i); Point3d x = new Point3d(repeats[i]); m.transform(x); assertTrue("Transformation "+i+" of "+repeats[i]+ "="+x+" not 1,1,1",x.epsilonEquals(repeats[0], 1e-5)); } Point3d x; List<Axis> symmetryAxes = axes.getSymmetryAxes(); assertEquals(5,symmetryAxes.size()); int axisNum = 0; // Repeat 2 -> 0 (90 deg around z) x = new Point3d(repeats[2]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[2]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); assertEquals(0,symmetryAxes.get(axisNum).getFirstRepeat()); axisNum++; // Repeat 1 -> 0 (180 deg around x) x = new Point3d(repeats[1]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[1]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); assertEquals(0,symmetryAxes.get(axisNum).getFirstRepeat()); axisNum++; // Repeat 3 -> 2 (180 deg around y) x = new Point3d(repeats[3]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[3]),round(x),round(repeats[2])),x.epsilonEquals(repeats[2], 1e-5)); assertEquals(2,symmetryAxes.get(axisNum).getFirstRepeat()); axisNum++; // Repeat 5 -> 4 (180 deg around x) x = new Point3d(repeats[5]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[5]),round(x),round(repeats[4])),x.epsilonEquals(repeats[4], 1e-5)); assertEquals(4,symmetryAxes.get(axisNum).getFirstRepeat()); axisNum++; // Repeat 7 -> 6 (180 deg around y) x = new Point3d(repeats[7]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[7]),round(x),round(repeats[6])),x.epsilonEquals(repeats[6], 1e-5)); assertEquals(6,symmetryAxes.get(axisNum).getFirstRepeat()); axisNum++; } private static Point3d round(Point3d p) { return new Point3d(Math.round(p.x*100)/100.,Math.round(p.y*100)/100.,Math.round(p.z*100)/100.); } @Test public void testOpenCase() { // D4 case SymmetryAxes axes = new SymmetryAxes(); // Level 1 is R4 along X Matrix4d t10 = new Matrix4d(); t10.set(1,new Vector3d(-10,0,0)); axes.addAxis(t10, 4, SymmetryType.OPEN); // Level 2 is C2 along X Matrix4d r180 = new Matrix4d(); r180.set(new AxisAngle4d(1, 0, 0, Math.PI)); axes.addAxis(r180, 2, SymmetryType.CLOSED); assertEquals(2,axes.getElementaryAxes().size()); Matrix4d expectedEven = new Matrix4d(); expectedEven.setIdentity(); Matrix4d expectedOdd = new Matrix4d(r180); assertEquals(expectedEven, axes.getRepeatTransform(0)); assertEquals(expectedOdd, axes.getRepeatTransform(1)); expectedEven.mul(t10); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(2)); assertEquals(expectedOdd, axes.getRepeatTransform(3)); expectedEven.mul(t10); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(4)); assertEquals(expectedOdd, axes.getRepeatTransform(5)); expectedEven.mul(t10); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(6)); assertEquals(expectedOdd, axes.getRepeatTransform(7)); // Test Cauchy Form List<List<Integer>> relation = Arrays.asList( Arrays.asList(0,1,2,3,4,5), Arrays.asList(2,3,4,5,6,7) ); assertEquals(relation,axes.getRepeatRelation(0)); relation = Arrays.asList( Arrays.asList(0,1), Arrays.asList(1,0) ); assertEquals(relation,axes.getRepeatRelation(1)); try { axes.getRepeatRelation(2); fail("Invalid level"); } catch(IndexOutOfBoundsException e) {} // Test Cyclic Form relation = Arrays.asList( Arrays.asList(0,2,4,6), Arrays.asList(1,3,5,7) ); assertEquals(relation,axes.getRepeatsCyclicForm(0)); relation = Arrays.asList( Arrays.asList(0,1) ); assertEquals(relation,axes.getRepeatsCyclicForm(1)); relation = Arrays.asList( Arrays.asList(2,3) ); assertEquals(relation,axes.getRepeatsCyclicForm(1,2)); try { axes.getRepeatsCyclicForm(2); fail("Invalid level"); } catch(IndexOutOfBoundsException e) {} try { axes.getRepeatsCyclicForm(1,1); fail("Invalid firstRepeat"); } catch(IllegalArgumentException e) {} // Expected location of each repeat Point3d[] repeats = new Point3d[] { new Point3d(-15,1,1), new Point3d(-15,-1,-1), new Point3d( -5,1,1), new Point3d( -5,-1,-1), new Point3d( 5,1,1), new Point3d( 5,-1,-1), new Point3d( 15,1,1), new Point3d( 15,-1,-1), }; // Inverse of first point should give above points for(int i=0;i<8;i++) { Matrix4d m = axes.getRepeatTransform(i); m.invert(); Point3d x = new Point3d(repeats[0]); m.transform(x); assertTrue("Transformation "+i+"^-1 of "+repeats[0]+ "="+x+" not "+repeats[i],x.epsilonEquals(repeats[i], 1e-5)); } // Forward should map the above points onto the first one for(int i=0;i<8;i++) { Matrix4d m = axes.getRepeatTransform(i); Point3d x = new Point3d(repeats[i]); m.transform(x); assertTrue("Transformation "+i+" of "+repeats[i]+ "="+x+" not "+repeats[0],x.epsilonEquals(repeats[0], 1e-5)); } Point3d x; List<Axis> symmetryAxes = axes.getSymmetryAxes(); assertEquals(5,symmetryAxes.size()); int axisNum = 0; // Repeat 2 -> 0 (shift 1) x = new Point3d(repeats[2]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[2]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); axisNum++; // All of these are actually equivalent // Repeat 1 -> 0 (180 deg around x) x = new Point3d(repeats[1]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[1]),round(x),round(repeats[0])),x.epsilonEquals(repeats[0], 1e-5)); axisNum++; // Repeat 3 -> 2 (180 deg around x) x = new Point3d(repeats[3]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[3]),round(x),round(repeats[2])),x.epsilonEquals(repeats[2], 1e-5)); axisNum++; // Repeat 5 -> 4 (180 deg around x) x = new Point3d(repeats[5]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[5]),round(x),round(repeats[4])),x.epsilonEquals(repeats[4], 1e-5)); axisNum++; // Repeat 7 -> 6 (180 deg around x) x = new Point3d(repeats[7]); symmetryAxes.get(axisNum).getOperator().transform(x); assertTrue(String.format("SymmAxis %d of %s=%s not %s",axisNum,round(repeats[7]),round(x),round(repeats[6])),x.epsilonEquals(repeats[6], 1e-5)); axisNum++; } /** * Test that the deprecated addAxis still works */ @SuppressWarnings("deprecation") @Test public void testOpenCaseOld() { // D4 case SymmetryAxes axes = new SymmetryAxes(); // Level 1 is R4 along X Matrix4d t10 = new Matrix4d(); t10.set(1,new Vector3d(1,0,0)); List<Integer> repeats = Arrays.asList(0,0,1,1,2,2,3,3); List<List<Integer>> superposition = Arrays.asList( Arrays.asList(0,1,2,3,4,5), Arrays.asList(2,3,4,5,6,7)); axes.addAxis(t10, superposition, repeats, 4); // Level 2 is C2 along X Matrix4d r180 = new Matrix4d(); r180.set(new AxisAngle4d(1, 0, 0, Math.PI)); repeats = Arrays.asList(0,1,0,1,0,1,0,1); superposition = Arrays.asList( Arrays.asList(0,1), Arrays.asList(1,0)); axes.addAxis(r180, superposition, repeats, 2); assertEquals(2,axes.getElementaryAxes().size()); Matrix4d expectedEven = new Matrix4d(); expectedEven.setIdentity(); Matrix4d expectedOdd = new Matrix4d(r180); assertEquals(expectedEven, axes.getRepeatTransform(0)); assertEquals(expectedOdd, axes.getRepeatTransform(1)); expectedEven.mul(t10); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(2)); assertEquals(expectedOdd, axes.getRepeatTransform(3)); expectedEven.mul(t10); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(4)); assertEquals(expectedOdd, axes.getRepeatTransform(5)); expectedEven.mul(t10); expectedOdd.mul(r180,expectedEven); assertEquals(expectedEven, axes.getRepeatTransform(6)); assertEquals(expectedOdd, axes.getRepeatTransform(7)); List<List<Integer>> relation = Arrays.asList( Arrays.asList(0,1,2,3,4,5), Arrays.asList(2,3,4,5,6,7) ); assertEquals(relation,axes.getRepeatRelation(0)); relation = Arrays.asList( Arrays.asList(0,1), Arrays.asList(1,0) ); assertEquals(relation,axes.getRepeatRelation(1)); try { axes.getRepeatRelation(2); fail("Invalid level"); } catch(IndexOutOfBoundsException e) {} } }