Example #1
0
        public override bool GetLocalRealignmentWithTwoRotationCenters(LineTrackingCoordinateSystem axis1, Vector3 center1, LineTrackingCoordinateSystem axis2, Vector3 center2, out LineTrackingCoordinateSystem realignedAxis1, out LineTrackingCoordinateSystem realignedAxis2, out float errorDegrees)
        {
            Vector3 dir1 = axis1.Direction;
            Vector3 dir2 = axis2.Direction;

            if (VectorMath.GetAngleRadians(dir1, dir2) > Math.PI)
            {
                dir1 = -dir1;
            }

            Vector3 average = Vector3.Normalize(dir1 + dir2);

            Matrix mat1 = VectorMath.GetRotationMatrix(dir1, average);

            mat1.Translation += center1 - Vector3.Transform(center1, mat1);

            Matrix mat2 = VectorMath.GetRotationMatrix(dir2, average);

            mat2.Translation += center2 - Vector3.Transform(center2, mat2);

            realignedAxis1 = new LineTrackingCoordinateSystem(axis1);
            realignedAxis2 = new LineTrackingCoordinateSystem(axis2);
            realignedAxis1.ApplyTransform(mat1);
            realignedAxis2.ApplyTransform(mat2);

            errorDegrees = (float)VectorMath.GetAngleDegrees(dir1, average);

            return(true);
        }
Example #2
0
        private static void ValidateGeometryUtilities()
        {
            for (int i = 0; i < 10; i++)
            {
                // Check the proper quaternion is generated to go 'from'->'to'
                Random  r      = new Random();
                Vector3 v1     = Vector3.Normalize(new Vector3(r.Next(), r.Next(), r.Next()));
                Vector3 v2     = Vector3.Normalize(new Vector3(r.Next(), r.Next(), r.Next()));
                float   angle1 = r.Next() % 360;
                float   angle2 = r.Next() % 360;

                if (angle1 == 0 || angle2 == 0)
                {
                    continue;
                }

                Quaternion from          = Quaternion.CreateFromAxisAngle(v1, (float)VectorMath.DegreesToRad(angle1));
                Quaternion to            = Quaternion.CreateFromAxisAngle(v2, (float)VectorMath.DegreesToRad(angle2));
                Quaternion transformQuat = VectorMath.GetLocalRotation(from, to);

                Quaternion fromTo = from * transformQuat;
                //Quaternion fromTo = from;
                float newAngleBetween = VectorMath.GetAngleDegrees(to, fromTo);
                Debug.Assert(Math.Abs(newAngleBetween) < 5);

                float   verifyAngle1;
                Vector3 verifyAxis1;
                VectorMath.GetRotationVectorAndAngleDegrees(from, out verifyAxis1, out verifyAngle1);
                Debug.Assert(Vector3.Dot(verifyAxis1, v1) > 0.99 && Math.Abs(verifyAngle1 - angle1) < 1 || Vector3.Dot(verifyAxis1, v1) < -0.99 && Math.Abs(360 - verifyAngle1 - angle1) < 1);
                //Debug.Assert( <= 2);

                Quaternion verifyFrom = VectorMath.GetLocalRotation(Quaternion.Identity, from);
                VectorMath.GetRotationVectorAndAngleDegrees(verifyFrom, out verifyAxis1, out verifyAngle1);
                Debug.Assert(Vector3.Dot(verifyAxis1, v1) > 0.99 && Math.Abs(verifyAngle1 - angle1) < 1 || Vector3.Dot(verifyAxis1, v1) < -0.99 && Math.Abs(360 - verifyAngle1 - angle1) < 1);
            }

            {
                Quaternion       rotation1 = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (float)Math.PI / 2);
                CoordinateSystem cs        = new CoordinateSystem();
                cs.Translation = new Vector3(1, 2, 3);
                Console.WriteLine("PRE  = " + cs.Translation.ToString());
                cs.RotateLocal(new Vector3(-1, -2, -3), rotation1);
                Console.WriteLine("POST = " + cs.Translation.ToString());
            }

            {
                for (int i = 0; i < 10; i++)
                {
                    Random     r    = new Random();
                    Vector3    v1   = Vector3.Normalize(new Vector3(r.Next(), r.Next(), r.Next()));
                    Vector3    v2   = Vector3.Normalize(new Vector3(r.Next(), r.Next(), r.Next()));
                    Quaternion quat = VectorMath.GetRotationQuaternion(v1, v2);
                    Debug.Assert(Vector3.Dot(Vector3.Transform(v1, quat), v2) > 0.99);
                }
            }
        }
Example #3
0
        public static TwoAxisRealignment Create(SymmetryBuilder builder, string axis1, string axis2)
        {
            CoordinateSystem coordinateSystem1 = builder.GetPrincipalCoordinateSystem(axis1);
            CoordinateSystem coordinateSystem2 = builder.GetPrincipalCoordinateSystem(axis2);
            Line             principalAxis1    = Line.CreateFromPointAndDirection(coordinateSystem1.Translation, coordinateSystem1.UnitX); // The rosetta symdefs axes are along X of each transformed coordinate system, but something not requiring foreknowledge would be nice.
            Line             principalAxis2    = Line.CreateFromPointAndDirection(coordinateSystem2.Translation, coordinateSystem2.UnitX); // The rosetta symdefs axes are along X of each transformed coordinate system, but something not requiring foreknowledge would be nice.
            Quaternion       premultiply       = Quaternion.Inverse(coordinateSystem1.Transform.Rotation);

            principalAxis1.Direction = Vector3.Transform(principalAxis1.Direction, premultiply);
            principalAxis2.Direction = Vector3.Transform(principalAxis2.Direction, premultiply);
            principalAxis1.Point     = Vector3.Transform(principalAxis1.Point, premultiply);
            principalAxis2.Point     = Vector3.Transform(principalAxis2.Point, premultiply);
            float angleDegrees        = (float)VectorMath.GetAngleDegrees(principalAxis1.Direction, principalAxis2.Direction);
            TwoAxisRealignment result = TwoAxisRealignment.Create(angleDegrees, principalAxis1, principalAxis2);

            return(result);
        }
Example #4
0
        static void StartJobsAngleCXRCX(CxrcxFusionFlags options)
        {
            SymmetryBuilder symmetry = SymmetryBuilderFactory.CreateFromSymmetryName(options.Architecture);

            List <string>        filesOligomer1 = GetPdbFiles(Directory.GetCurrentDirectory(), options.OligomerRegex1).ToList();
            List <string>        filesOligomer2 = GetPdbFiles(Directory.GetCurrentDirectory(), options.OligomerRegex2).ToList();
            List <string>        filesRepeat    = GetPdbFiles(Directory.GetCurrentDirectory(), options.RepeatRegex).ToList();
            ThreadSafeJobCounter sharedCounter  = new ThreadSafeJobCounter();

            sharedCounter.Total = filesOligomer1.Count * filesOligomer2.Count * filesRepeat.Count;

            Console.WriteLine("Using the following spacer repeat proteins:");
            filesRepeat.ForEach(file => Console.WriteLine(file));

            Console.WriteLine("\nUsing the following files for h**o-oligomer 1:");
            filesOligomer1.ForEach(file => Console.WriteLine(file));

            Console.WriteLine("\nUsing the following files for h**o-oligomer 2:");
            filesOligomer2.ForEach(file => Console.WriteLine(file));

            float angleDegrees = (float)VectorMath.GetAngleDegrees(symmetry.GetPrincipalCoordinateSystem(options.UnitId1).UnitX, Vector3.Zero, symmetry.GetPrincipalCoordinateSystem(options.UnitId2).UnitX);

            Console.WriteLine("Angle for {0}:{1}:{2} calculated to: {3:F4}", options.Architecture, options.UnitId1, options.UnitId2, angleDegrees);

            // Parse oligomer 1 and offset it to positive Z
            foreach (string fileOligomer1 in filesOligomer1)
            {
                string pdbCodeOligomer1 = PdbQuick.CodeFromFilePath(fileOligomer1);
                IChain peptide1         = PdbQuick.ChainFromFileOrCode(fileOligomer1);

                if (peptide1 == null)
                {
                    Console.WriteLine("Pdb parsing failed for {0}", fileOligomer1);
                    continue;
                }

                peptide1.Translate(new Vector3(0, 0, 20 - Rmsd.GetBackboneCentroid(peptide1).Z));

                // Parse oligomer 2 and offset it to positive Z
                foreach (string fileOligomer2 in filesOligomer2)
                {
                    string pdbCodeOligomer2 = PdbQuick.CodeFromFilePath(fileOligomer2);
                    IChain peptide2         = PdbQuick.ChainFromFileOrCode(fileOligomer2);

                    if (peptide2 == null)
                    {
                        Console.WriteLine("Pdb parsing failed for {0}", fileOligomer2);
                        continue;
                    }

                    peptide2.Translate(new Vector3(0, 0, 20 - Rmsd.GetBackboneCentroid(peptide2).Z));

                    // Parse the repeat and offset it to positive Z
                    foreach (string fileRepeat in filesRepeat)
                    {
                        IChain repeat        = PdbQuick.ChainFromFileOrCode(fileRepeat);
                        string pdbCodeRepeat = PdbQuick.CodeFromFilePath(fileRepeat);

                        if (repeat == null)
                        {
                            Console.WriteLine("Pdb parsing failed for {0}", repeat);
                            continue;
                        }

                        repeat.Translate(new Vector3(0, 0, 20 - Rmsd.GetBackboneCentroid(repeat).Z));

                        JobStartParamsCXRCX startParams = new JobStartParamsCXRCX();
                        // things taken directly from user options
                        startParams.OutputPrefix = options.Architecture + "-" + options.UnitId1 + "-" + options.UnitId2;
                        startParams.UnitId1      = options.UnitId1;
                        startParams.UnitId2      = options.UnitId2;
                        startParams.ChainCount1  = options.Oligomerization1;
                        startParams.ChainCount2  = options.Oligomerization2;
                        startParams.TopX         = options.TopX;
                        // everything else:
                        startParams.Symmetry       = SymmetryBuilderFactory.CreateFromSymmetryName(options.Architecture);
                        startParams.PdbCodeBundle1 = pdbCodeOligomer1;
                        startParams.PdbCodeBundle2 = pdbCodeOligomer2;
                        startParams.PdbCodeRepeat  = pdbCodeRepeat;
                        startParams.Cx1            = peptide1;
                        startParams.Cx2            = peptide2;
                        startParams.Repeat         = repeat;
                        startParams.AngleDegrees   = angleDegrees;
                        startParams.Counter        = sharedCounter; // Shared counter across queued jobs
                        Debug.Assert(startParams.Validate(), "JobStartParamsCXRCX validation failure");

                        // Wait for free threads
                        _threadCountSemaphore.WaitOne();
                        sharedCounter.IncrementQueued();

                        // Start the job
                        Thread thread = new Thread(new ParameterizedThreadStart(RunJobAngleCXRCX));
                        thread.Start(startParams);
                        Console.WriteLine("Queuing triplet [Bundle {0}]:[Repeat {1}]:[Bundle {2}], {3:F2} degrees, {4:F2} % ({5}/{6})", pdbCodeOligomer1, pdbCodeRepeat, pdbCodeOligomer2, angleDegrees, startParams.Counter.PercentQueued, startParams.Counter.Queued, startParams.Counter.Total);
                    }
                }
            }
        }
Example #5
0
        public override bool GetLocalRealignmentWithTwoRotationCenters(LineTrackingCoordinateSystem axis1, Vector3 center1, LineTrackingCoordinateSystem axis2, Vector3 center2, out LineTrackingCoordinateSystem realignedAxis1, out LineTrackingCoordinateSystem realignedAxis2, out float errorDegrees)
        {
            // Set out parameter default values
            realignedAxis1 = new LineTrackingCoordinateSystem(axis1);
            realignedAxis2 = new LineTrackingCoordinateSystem(axis2);
            errorDegrees   = float.NaN;

            // Find the points (p1 and p2) where axes (l1 and l2) are nearest and perpendicular to the rotation center
            // Find the plane normals (r1 and r2) defined by each center the new axis (p1->p2) that isn't yet tangent both spheres
            Vector3 p1   = Line.GetNearestPointOnLine(Line.CreateFrom(axis1), center1);
            Vector3 p2   = Line.GetNearestPointOnLine(Line.CreateFrom(axis2), center2);
            Line    p12  = Line.CreateFromTwoPoints(p1, p2);
            Vector3 r1   = Vector3.Normalize(Vector3.Cross(p1 - center1, p12.Direction)); // Plane normals
            Vector3 r2   = Vector3.Normalize(Vector3.Cross(p2 - center2, p12.Direction));
            Vector3 vC12 = center2 - center1;
            Vector3 uC12 = Vector3.Normalize(vC12);

            // Get the "average" plane that is created by rotating each plane about (p1->p2) until they are coincident
            Vector3 r = Vector3.Dot(r1, r2) > 0? Vector3.Normalize(r1 + r2) : Vector3.Normalize(r1 - r2); // This gives the normal for the nearest of two possible mid-planes

            Debug.Assert(Math.Abs(Vector3.Dot(r, p12.Direction)) < 0.001);

            // Project center1 and center2 onto the plane to determine circle centers and their radii
            Vector3 c1projection          = center1 + Vector3.Dot(p1 - center1, r) * r;
            Vector3 c2projection          = center2 + Vector3.Dot(p2 - center2, r) * r;
            float   c1radius              = Vector3.Distance(p1, c1projection);
            float   c2radius              = Vector3.Distance(p2, c2projection);
            Vector3 vProjectionC1C2       = c2projection - c1projection;
            Vector3 uProjectionC1C2       = Vector3.Normalize(vProjectionC1C2);
            float   distanceProjectionC12 = vProjectionC1C2.Length();

            Debug.Assert(Math.Abs(Vector3.Dot(p1 - c1projection, r)) < 0.001);
            Debug.Assert(Math.Abs(Vector3.Dot(p2 - c2projection, r)) < 0.001);

            // If one spherical surface fully contains the other, there are no solutions
            if (c1radius + distanceProjectionC12 < c2radius || c2radius + distanceProjectionC12 < c1radius)
            {
                return(false);
            }

            // Compute theta (angle between c1->c2 and the p1 on c1 or p2 on c2)
            //float originalTheta1 = (float) Math.Acos(p2 - c1proj)
            float solutionTheta1 = (float)Math.Acos((c1radius - c2radius) / distanceProjectionC12);
            float solutionTheta2 = c1radius + c2radius < distanceProjectionC12 ? (float)Math.Acos((c2radius + c2radius) / distanceProjectionC12) : float.NaN; // theta2 is only defined for spheres that don't overlap

            // Solutions exist at +/- theta1
            Vector3 positiveTheta1P1 = c1projection + Vector3.Transform(uProjectionC1C2, Quaternion.CreateFromAxisAngle(r, solutionTheta1));
            Vector3 positiveTheta1P2 = c2projection + Vector3.Transform(uProjectionC1C2, Quaternion.CreateFromAxisAngle(r, solutionTheta1));
            Vector3 negativeTheta1P1 = c1projection + Vector3.Transform(uProjectionC1C2, Quaternion.CreateFromAxisAngle(r, -solutionTheta1));
            Vector3 negativeTheta1P2 = c2projection + Vector3.Transform(uProjectionC1C2, Quaternion.CreateFromAxisAngle(r, -solutionTheta1));
            Vector3 uPositiveTheta1  = positiveTheta1P2 - positiveTheta1P1;
            Vector3 uNegativeTheta1  = negativeTheta1P1 - negativeTheta1P2;


            float radErrorPositiveTheta1 = (float)(VectorMath.GetAngleDegrees(positiveTheta1P1 - c1projection, p1 - c1projection) + VectorMath.GetAngleDegrees(positiveTheta1P2 - c2projection, p2 - c2projection));
            float radErrorNegativeTheta1 = (float)(VectorMath.GetAngleDegrees(negativeTheta1P1 - c1projection, p1 - c1projection) + VectorMath.GetAngleDegrees(negativeTheta1P2 - c2projection, p2 - c2projection));

            if (radErrorPositiveTheta1 < radErrorNegativeTheta1)
            {
                errorDegrees = radErrorPositiveTheta1;

                // Move the realigned axes to reflect rotation onto the p1->p2 line segment
                Quaternion rotation1 = VectorMath.GetRotationQuaternion(p1 - center1, positiveTheta1P1 - center1);
                Quaternion rotation2 = VectorMath.GetRotationQuaternion(p2 - center2, positiveTheta1P2 - center2);
                realignedAxis1.Translation -= center1;
                realignedAxis1.ApplyRotation(rotation1);
                realignedAxis1.Translation += center1;
                realignedAxis2.Translation -= center2;
                realignedAxis2.ApplyRotation(rotation2);
                realignedAxis2.Translation += center2;

                rotation1 = Vector3.Dot(realignedAxis1.Direction, uPositiveTheta1) > 0 ? VectorMath.GetRotationQuaternion(realignedAxis1.Direction, uPositiveTheta1) : VectorMath.GetRotationQuaternion(realignedAxis1.Direction, -uPositiveTheta1);
                rotation2 = Vector3.Dot(realignedAxis2.Direction, uPositiveTheta1) > 0 ? VectorMath.GetRotationQuaternion(realignedAxis2.Direction, uPositiveTheta1) : VectorMath.GetRotationQuaternion(realignedAxis2.Direction, -uPositiveTheta1);
                realignedAxis1.Translation -= center1;
                realignedAxis1.ApplyRotation(rotation1);
                realignedAxis1.Translation += center1;
                realignedAxis2.Translation -= center2;
                realignedAxis2.ApplyRotation(rotation2);
                realignedAxis2.Translation += center2;
            }
            else
            {
                errorDegrees = radErrorNegativeTheta1;
                return(false);
            }
            // TODO: negative theta1, theta2 positive and negative

            return(true);
        }