/** * Return a midpoint of a helix, calculated from three positions of three adjacent subunit * centers. * * @param p1 center of first subunit * @param p2 center of second subunit * @param p3 center of third subunit * @return midpoint of helix */ private Point3d getMidPoint(Point3d p1, Point3d p2, Point3d p3) { Vector3d v1 = new Vector3d(); v1.sub(p1, p2); Vector3d v2 = new Vector3d(); v2.sub(p3, p2); Vector3d v3 = new Vector3d(); v3.add(v1); v3.add(v2); v3.normalize(); // calculat the total distance between to subunits double dTotal = v1.length(); // calculate the rise along the y-axis. The helix axis is aligned with y-axis, // therfore, the rise between subunits is the y-distance double rise = p2.y - p1.y; // use phythagorean theoremm to calculate chord length between two subunit centers double chord = Math.sqrt(dTotal * dTotal - rise * rise); // System.out.println("Chord d: " + dTotal + " rise: " + rise + "chord: " + chord); double angle = helixLayers.getByLargestContacts().getAxisAngle().angle; // using the axis angle and the chord length, we can calculate the radius of the helix // http://en.wikipedia.org/wiki/Chord_%28geometry%29 double radius = chord / Math.sin(angle / 2) / 2; // can this go to zero? // System.out.println("Radius: " + radius); // project the radius onto the vector that points toward the helix axis v3.scale(radius); v3.add(p2); // System.out.println("Angle: " + // Math.toDegrees(helixLayers.getByLowestAngle().getAxisAngle().angle)); Point3d cor = new Point3d(v3); return cor; }
private Vector3d orthogonalize(Vector3d vector1, Vector3d vector2) { double dot = vector1.dot(vector2); Vector3d ref = new Vector3d(vector2); // System.out.println("p.r: " + dot); // System.out.println("Orig refVector: " + referenceVector); if (dot < 0) { vector2.negate(); } if (Math.abs(dot) < 0.00001) { System.out.println("HelixAxisAligner: Warning: reference axis parallel"); } vector2.cross(vector1, vector2); // System.out.println("Intermed. refVector: " + vector2); vector2.normalize(); // referenceVector.cross(referenceVector, principalRotationVector); vector2.cross(vector1, vector2); vector2.normalize(); if (ref.dot(vector2) < 0) { vector2.negate(); } // System.out.println("Mod. refVector: " + vector2); return vector2; }
/** * Returns a transformation matrix that rotates refPoints to match coordPoints * * @param refPoints the points to be aligned * @param referenceVectors * @return */ private Matrix4d alignAxes(Vector3d[] axisVectors, Vector3d[] referenceVectors) { Matrix4d m1 = new Matrix4d(); AxisAngle4d a = new AxisAngle4d(); Vector3d axis = new Vector3d(); // calculate rotation matrix to rotate refPoints[0] into coordPoints[0] Vector3d v1 = new Vector3d(axisVectors[0]); Vector3d v2 = new Vector3d(referenceVectors[0]); double dot = v1.dot(v2); if (Math.abs(dot) < 0.999) { axis.cross(v1, v2); axis.normalize(); a.set(axis, v1.angle(v2)); m1.set(a); // make sure matrix element m33 is 1.0. It's 0 on Linux. m1.setElement(3, 3, 1.0); } else if (dot > 0) { // parallel axis, nothing to do -> identity matrix m1.setIdentity(); } else if (dot < 0) { // anti-parallel axis, flip around x-axis m1.set(flipX()); } // apply transformation matrix to all refPoints m1.transform(axisVectors[0]); m1.transform(axisVectors[1]); // calculate rotation matrix to rotate refPoints[1] into coordPoints[1] v1 = new Vector3d(axisVectors[1]); v2 = new Vector3d(referenceVectors[1]); Matrix4d m2 = new Matrix4d(); dot = v1.dot(v2); if (Math.abs(dot) < 0.999) { axis.cross(v1, v2); axis.normalize(); a.set(axis, v1.angle(v2)); m2.set(a); // make sure matrix element m33 is 1.0. It's 0 on Linux. m2.setElement(3, 3, 1.0); } else if (dot > 0) { // parallel axis, nothing to do -> identity matrix m2.setIdentity(); } else if (dot < 0) { // anti-parallel axis, flip around z-axis m2.set(flipZ()); } // apply transformation matrix to all refPoints m2.transform(axisVectors[0]); m2.transform(axisVectors[1]); // combine the two rotation matrices m2.mul(m1); // the RMSD should be close to zero Point3d[] axes = new Point3d[2]; axes[0] = new Point3d(axisVectors[0]); axes[1] = new Point3d(axisVectors[1]); Point3d[] ref = new Point3d[2]; ref[0] = new Point3d(referenceVectors[0]); ref[1] = new Point3d(referenceVectors[1]); if (SuperPosition.rmsd(axes, ref) > 0.1) { System.out.println( "Warning: AxisTransformation: axes alignment is off. RMSD: " + SuperPosition.rmsd(axes, ref)); } return m2; }