Example #1
0
        /// <summary>
        /// Calculate the accesible volume with 3 dye radii
        /// </summary>
        /// <param name="L">Linker length</param>
        /// <param name="W">Linker width (diameter)</param>
        /// <param name="R1">Dye radius 1</param>
        /// <param name="R2">Dye radius 2</param>
        /// <param name="R3">Dye radius 3</param>
        /// <param name="atom_i">Atom ID (original number in the pdb file)</param>
        public void Calculate3R(Double L, Double W, Double R1, Double R2, Double R3, Int32 atom_i)
        {
            // common grid
            Double dg1 = Math.Min(L * _avGrid.GridSize, W * _avGrid.GridSize);
            Double dg2 = Math.Min(R1 * 2.0 * _avGrid.GridSize, dg1);

            dg1 = Math.Min(R2 * 2.0 * _avGrid.GridSize, dg2);
            dg2 = Math.Min(R3 * 2.0 * _avGrid.GridSize, dg1);
            Double dg   = Math.Max(dg2, _avGrid.MinGridSize);
            Double Rmax = Math.Max(R1, R2); Rmax = Math.Max(Rmax, R3);

            Double x0 = mol.XLocal[atom_i], y0 = mol.YLocal[atom_i], z0 = mol.ZLocal[atom_i];
            Double dx, dy, dz;
            Int32  npm = (Int32)Math.Floor(L / dg);
            Int32  ng = 2 * npm + 1, ng3 = ng * ng * ng, n;
            Int32  offset;

            Double[] xg = new Double[ng];
            Double[] yg = new Double[ng];
            Double[] zg = new Double[ng];
            for (Int32 i = -npm; i <= npm; i++)
            {
                n     = i + npm;
                xg[n] = i * dg; yg[n] = i * dg; zg[n] = i * dg;
            }

            _density = new Byte[ng3];

            n = FpsNativeWrapper.AvCalculate3R(L, W, R1, R2, R3, atom_i, dg, mol.XLocal, mol.YLocal, mol.ZLocal, mol.vdWR, mol.NAtoms,
                                               AtomData.vdWRMax, _avGrid.LinkerInitialSphere, _avGrid.LinkSearchNodes, _density);

            _r = new Vector3[n];
            Double rn = 1.0 / (Double)n;

            n   = 0; dx = 0.0; dy = 0.0; dz = 0.0;
            x0 += mol.CM.X; y0 += mol.CM.Y; z0 += mol.CM.Z;
            for (Int32 ix = -npm; ix <= npm; ix++)
            {
                offset = ng * (ng * (ix + npm)) + npm;
                for (Int32 iy = -npm; iy <= npm; iy++)
                {
                    for (Int32 iz = -npm; iz <= npm; iz++)
                    {
                        for (Int32 dn = 0; dn < _density[iz + offset]; dn++)
                        {
                            _r[n].X = xg[ix + npm] + x0; dx += _r[n].X;
                            _r[n].Y = yg[iy + npm] + y0; dy += _r[n].Y;
                            _r[n].Z = zg[iz + npm] + z0; dz += _r[n++].Z;
                        }
                    }
                    offset += ng;
                }
            }

            // other saves
            _rmp.X        = dx * rn; _rmp.Y = dy * rn; _rmp.Z = dz * rn;
            _xGrid.Min    = xg[0] + x0; _yGrid.Min = yg[0] + y0; _zGrid.Min = zg[0] + z0;
            _xGrid.NNodes = ng; _yGrid.NNodes = ng; _zGrid.NNodes = ng;
            _xGrid.Step   = dg; _yGrid.Step = dg; _zGrid.Step = dg;
        }
Example #2
0
        /// <summary>
        /// Calculate some additional parameters needed for simulations
        /// </summary>
        public void Prepare()
        {
            if (Error != "")
            {
                return;
            }

            // min/max values of local coordinates
            double xmin = 1.0e6, xmax = -1.0e6, ymin = 1.0e6, ymax = -1.0e6, zmin = 1.0e6, zmax = -1.0e6;

            for (int i = 0; i < NAtoms; i++)
            {
                xmin      = Math.Min(xmin, XLocal[i]);
                xmax      = Math.Max(xmax, XLocal[i]);
                ymin      = Math.Min(ymin, YLocal[i]);
                ymax      = Math.Max(ymax, YLocal[i]);
                zmin      = Math.Min(zmin, ZLocal[i]);
                zmax      = Math.Max(zmax, ZLocal[i]);
                MaxRadius = new Vector3(Math.Max(MaxRadius.X, Math.Sqrt(YLocal[i] * YLocal[i] + ZLocal[i] * ZLocal[i]) + vdWR[i]),
                                        Math.Max(MaxRadius.Y, Math.Sqrt(XLocal[i] * XLocal[i] + ZLocal[i] * ZLocal[i]) + vdWR[i]),
                                        Math.Max(MaxRadius.Z, Math.Sqrt(XLocal[i] * XLocal[i] + YLocal[i] * YLocal[i]) + vdWR[i]));
            }

            // moment(s) of inertia
            double ixx = 0.0, iyy = 0.0, izz = 0.0, ixy = 0.0, ixz = 0.0, iyz = 0.0;
            double m = 0.0, x2, y2, z2;

            for (int i = 0; i < NAtoms; i++)
            {
                m    = AtomMass[i];
                x2   = XLocal[i] * XLocal[i]; y2 = YLocal[i] * YLocal[i]; z2 = ZLocal[i] * ZLocal[i];
                ixx += m * (y2 + z2);
                iyy += m * (x2 + z2);
                izz += m * (x2 + y2);
                ixy -= m * XLocal[i] * YLocal[i];
                ixz -= m * XLocal[i] * ZLocal[i];
                iyz -= m * YLocal[i] * ZLocal[i];
            }
            SimpleI = Math.Max(Math.Max(ixx, ixy), ixz);
            FullI   = new Matrix3(ixx, ixy, ixz, ixy, iyy, iyz, ixz, iyz, izz);

            // clusters of clustersize^3 angstrom
            const double clustersize = 10.0;
            int          nx, ny, nz, nxoff, nyoff, nzoff;

            nx    = (int)(Math.Ceiling(xmax / clustersize) + Math.Ceiling(-xmin / clustersize));
            ny    = (int)(Math.Ceiling(ymax / clustersize) + Math.Ceiling(-ymin / clustersize));
            nz    = (int)(Math.Ceiling(zmax / clustersize) + Math.Ceiling(-zmin / clustersize));
            nxoff = (int)Math.Ceiling(-xmin / clustersize);
            nyoff = (int)Math.Ceiling(-ymin / clustersize);
            nzoff = (int)Math.Ceiling(-zmin / clustersize);
            int nclusters = nx * ny * nz;

            AtomCluster[] atomcluster_tmp = new AtomCluster[nx * ny * nz];

            // sort atoms
            // first run: count atoms in each cluster
            int    nc, cNAtomsmax = 0;
            double rcsize = 1.0 / clustersize;

            for (int i = 0; i < NAtoms; i++)
            {
                nc = (int)(ZLocal[i] * rcsize + nzoff) + nz * ((int)(YLocal[i] * rcsize + nyoff)
                                                               + ny * ((int)(XLocal[i] * rcsize + nxoff)));
                atomcluster_tmp[nc].NAtoms++;
                cNAtomsmax = Math.Max(cNAtomsmax, atomcluster_tmp[nc].NAtoms);
            }
            // allocate index arrays
            int ncfull = 0;

            int[][] originalatomindex = new int[nclusters][];
            for (nc = 0; nc < nclusters; nc++)
            {
                if (atomcluster_tmp[nc].NAtoms > 0)
                {
                    originalatomindex[nc] = new int[atomcluster_tmp[nc].NAtoms];
                    ncfull++;
                }
            }

            // fill
            int[] atomcounters = new int[nclusters];
            for (int i = 0; i < NAtoms; i++)
            {
                nc = (int)(ZLocal[i] * rcsize + nzoff) + nz * ((int)(YLocal[i] * rcsize + nyoff)
                                                               + ny * ((int)(XLocal[i] * rcsize + nxoff)));
                originalatomindex[nc][atomcounters[nc]++] = i;
            }
            // remove empty
            AtomClusters = new AtomCluster[ncfull];
            ncfull       = 0;
            for (nc = 0; nc < nclusters; nc++)
            {
                if (atomcluster_tmp[nc].NAtoms > 0)
                {
                    originalatomindex[ncfull] = originalatomindex[nc];
                    AtomClusters[ncfull++]    = atomcluster_tmp[nc];
                }
            }
            // optimize each
            double  rmax, cx, cy, cz;
            int     ilocal;
            Vector3 rlocal;

            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                // get the center
                cx = 0.0; cy = 0.0; cz = 0.0;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    cx    += XLocal[ilocal]; cy += YLocal[ilocal]; cz += ZLocal[ilocal];
                }
                cx /= (double)AtomClusters[nc].NAtoms;
                cy /= (double)AtomClusters[nc].NAtoms;
                cz /= (double)AtomClusters[nc].NAtoms;
                AtomClusters[nc].ClusterCenter = new Vector3(cx, cy, cz);

                // find the most distant atom
                rmax = -1.0;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    rlocal = new Vector3(cx - XLocal[ilocal], cy - YLocal[ilocal], cz - ZLocal[ilocal]);
                    rmax   = Math.Max(Vector3.Abs(rlocal) + vdWR[ilocal], rmax);
                }
                AtomClusters[nc].ClusterRadius = rmax;
            }
            // try an alternative method : find a pair of most distant atoms for each dimension, try as a center
            int    jlocal;
            double absr;

            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                rmax   = -1.0;
                rlocal = AtomClusters[nc];
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    cx     = XLocal[ilocal]; cy = YLocal[ilocal]; cz = ZLocal[ilocal];
                    for (int j = i + 1; j < AtomClusters[nc].NAtoms; j++)
                    {
                        jlocal = originalatomindex[nc][j];
                        rlocal = new Vector3(XLocal[jlocal] - cx, YLocal[jlocal] - cy, ZLocal[jlocal] - cz);
                        absr   = Vector3.Abs(rlocal);
                        if (rmax < absr + vdWR[ilocal] + vdWR[jlocal])
                        {
                            rmax   = absr + vdWR[ilocal] + vdWR[jlocal];
                            rlocal = (absr == 0.0) ? new Vector3(cx, cy, cz) :
                                     new Vector3(cx, cy, cz) + rlocal * ((0.5 * rmax - vdWR[ilocal]) / absr);
                        }
                    }
                }
                // find the most distant atom
                rmax = -1.0;
                cx   = rlocal.X; cy = rlocal.Y; cz = rlocal.Z;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    rlocal = new Vector3(cx - XLocal[ilocal], cy - YLocal[ilocal], cz - ZLocal[ilocal]);
                    rmax   = Math.Max(Vector3.Abs(rlocal) + vdWR[ilocal], rmax);
                }
                if (rmax < AtomClusters[nc].ClusterRadius)
                {
                    AtomClusters[nc].ClusterCenter = new Vector3(cx, cy, cz);
                    AtomClusters[nc].ClusterRadius = rmax;
                }
            }

#if DEBUG
            if (DebugData.SaveAtomClusters)
            {
                // for debugging: save clusters xyz
                using (StreamWriter sw = new StreamWriter(this.Name + ".cluster.xyz", false))
                {
                    sw.WriteLine(AtomClusters.Length.ToString());
                    sw.WriteLine("cluster");
                    for (int i = 0; i < AtomClusters.Length; i++)
                    {
                        sw.WriteLine("L" + i.ToString() + "  " + AtomClusters[i].ClusterCenter.X.ToString("F3") + "  "
                                     + AtomClusters[i].ClusterCenter.Y.ToString("F3") + "  " + AtomClusters[i].ClusterCenter.Z.ToString("F3"));
                    }
                    sw.Close();
                }
                using (StreamWriter sw = new StreamWriter(this.Name + ".cluster.pml", false))
                {
                    sw.WriteLine("select all");
                    sw.WriteLine("translate [" + CM.X.ToString("F3") + "," + CM.Y.ToString("F3")
                                 + "," + CM.Z.ToString("F3") + "]");
                    sw.WriteLine("deselect");
                    for (int i = 0; i < AtomClusters.Length; i++)
                    {
                        sw.WriteLine("alter (name L" + i.ToString() + "), vdw=" + AtomClusters[i].ClusterRadius.ToString("F3"));
                    }
                    sw.Close();
                }
            }
#endif

            /////////////////////////////////////////////////////////////////////////////////////////

            // remove atoms which can never be approached
            int       nnbr, nblocked = 0;
            double[]  xLocalnbr = new double[NAtoms];
            double[]  yLocalnbr = new double[NAtoms];
            double[]  zLocalnbr = new double[NAtoms];
            double[]  rthresh2 = new double[NAtoms];
            double[]  z2plus = new double[NAtoms];
            double[]  z2minus = new double[NAtoms];
            double    x0, y0, z0, rmin = AtomData.vdWRMin;
            Boolean[] atom_blocked = new Boolean[NAtoms];
            Boolean   accesible, zplus_blocked, zminus_blocked;

            double xg, yg, zg, rg, rxy, drmax, dtheta, dphi;

            for (int i = 0; i < NAtoms; i++)
            {
                accesible = false;
                x0        = XLocal[i]; y0 = YLocal[i]; z0 = ZLocal[i];
                rmax      = 2.0 * rmin + vdWR[i];
                // select neighbours within r1 + r2 + 2rmin
                nnbr = 0;
                for (int j = 0; j < NAtoms; j++)
                {
                    x2 = (XLocal[j] - x0) * (XLocal[j] - x0);
                    y2 = (YLocal[j] - y0) * (YLocal[j] - y0);
                    z2 = (ZLocal[j] - z0) * (ZLocal[j] - z0);
                    if (x2 + y2 + z2 < (rmax + vdWR[j]) * (rmax + vdWR[j]))
                    {
                        xLocalnbr[nnbr]  = XLocal[j] - x0;
                        yLocalnbr[nnbr]  = YLocal[j] - y0;
                        zLocalnbr[nnbr]  = ZLocal[j] - z0;
                        rthresh2[nnbr++] = (0.9 * rmin + vdWR[j]) * (0.9 * rmin + vdWR[j]);
                    }
                }
                // spherical grid
                rg     = vdWR[i] + rmin;
                drmax  = 0.1 * rmin / rg;
                nz     = (int)Math.Ceiling(Math.PI / drmax);
                dtheta = Math.PI / nz;
                for (double theta = Math.PI / 2.0; theta >= 0.0; theta -= dtheta)
                {
                    zg = rg * Math.Sin(theta);
                    for (int j = 0; j < nnbr; j++)
                    {
                        z2plus[j]  = (zLocalnbr[j] - zg) * (zLocalnbr[j] - zg);
                        z2minus[j] = (zLocalnbr[j] + zg) * (zLocalnbr[j] + zg);
                    }
                    rxy  = rg * Math.Cos(theta);
                    dphi = (rxy > 0.05 * rmin / Math.PI) ? 0.1 * rmin / rxy : 2.0 * Math.PI;
                    for (double phi = 0.0; phi <= 2.0 * Math.PI; phi += dphi)
                    {
                        xg = rxy * Math.Cos(phi);
                        yg = rxy * Math.Sin(phi);

                        // check all neighbours at zg and -zg
                        zplus_blocked  = false;
                        zminus_blocked = false;
                        for (int j = 0; j < nnbr; j++)
                        {
                            x2             = (xLocalnbr[j] - xg) * (xLocalnbr[j] - xg);
                            y2             = (yLocalnbr[j] - yg) * (yLocalnbr[j] - yg);
                            zplus_blocked  = zplus_blocked || (x2 + y2 + z2plus[j] < rthresh2[j]);
                            zminus_blocked = zminus_blocked || (x2 + y2 + z2minus[j] < rthresh2[j]);
                            if (zplus_blocked && zminus_blocked)
                            {
                                break;
                            }
                        }
                        accesible = accesible || (!zplus_blocked) || (!zminus_blocked);
                        if (accesible)
                        {
                            break;
                        }
                    }
                    if (accesible)
                    {
                        break;
                    }
                }
                atom_blocked[i] = !accesible;
                nblocked        = accesible ? nblocked : nblocked + 1;
            }

            // finally remove blocked atoms and reorder
            int ai = 0, unblocked = NAtoms - nblocked;
            MaxAtomsInCluster = 0;
            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                // first run: count blocked atoms
                nblocked = 0; // now in cluster nc
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    nblocked = atom_blocked[originalatomindex[nc][i]] ? nblocked + 1 : nblocked;
                }

                // second run: fill
                ai = 0;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    ilocal = originalatomindex[nc][i];
                    if (!atom_blocked[ilocal])
                    {
                        originalatomindex[nc][ai++] = ilocal;
                    }
                }
                AtomClusters[nc].NAtoms -= nblocked;
                MaxAtomsInCluster        = Math.Max(MaxAtomsInCluster, AtomClusters[nc].NAtoms);
            }

            // fill cluster arrays
            this.ClusteredAtomXYZ           = new Vector3[unblocked];
            this.ClusteredAtomvdwR          = new double[unblocked];
            this.ClusteredAtomOriginalIndex = new int[unblocked];
            if (XYZvdwRVectorArray != IntPtr.Zero)
            {
                Marshal.FreeHGlobal(XYZvdwRVectorArray);
            }
            XYZvdwRVectorArray = Marshal.AllocHGlobal((unblocked + 1) * sizeof(float) * 4);
            float[] XYZvdwRdata = new float[unblocked * 4];
            int     idata = 0, idata4 = 0, oi;
            for (nc = 0; nc < AtomClusters.Length; nc++)
            {
                AtomClusters[nc].StartIndexInClusterArrays = idata;
                for (int i = 0; i < AtomClusters[nc].NAtoms; i++)
                {
                    oi = originalatomindex[nc][i];
                    ClusteredAtomXYZ[idata]             = new Vector3(XLocal[oi], YLocal[oi], ZLocal[oi]);
                    ClusteredAtomvdwR[idata]            = vdWR[oi];
                    ClusteredAtomOriginalIndex[idata++] = oi;
                    XYZvdwRdata[idata4++] = (float)XLocal[oi];
                    XYZvdwRdata[idata4++] = (float)YLocal[oi];
                    XYZvdwRdata[idata4++] = (float)ZLocal[oi];
                    XYZvdwRdata[idata4++] = (float)vdWR[oi];
                }
            }
            Marshal.Copy(XYZvdwRdata, 0, FpsNativeWrapper.Aligned16(XYZvdwRVectorArray), XYZvdwRdata.Length);
            Prepared = true;
        }
Example #3
0
        // two molecules
        private Boolean CheckForClashes(int im1, int im2)
        {
            Molecule m1 = _molecules[im1];
            Molecule m2 = _molecules[im2];
            Vector3  dcm = translation[im1] - translation[im2], rc1, rc2;

            // check clusters
            Vector3[]   rc2cache = new Vector3[m2.AtomClusters.Length];
            double      sumr, dsq, dx2, dy2, dz2;
            Vector3     sumrv;
            AtomCluster c1, c2;
            Matrix3     rot1to2 = Matrix3.Transpose(rotation[im2]) * rotation[im1];
            Matrix3     rot2to1 = Matrix3.Transpose(rot1to2);
            Vector3     dcm1t   = Matrix3.Transpose(rotation[im1]) * dcm;
            Vector3     dcm2t   = Matrix3.Transpose(rotation[im2]) * dcm;

            int[] c2tocheck = new int[m2.AtomClusters.Length];
            int   j2, n2tocheck;

            int[] mustbechecked1 = new int[m1.AtomClusters.Length];
            int[] mustbechecked2 = new int[m2.AtomClusters.Length];

            // check if we can skip some of m2
            n2tocheck = 0;
            for (int j = 0; j < m2.AtomClusters.Length; j++)
            {
                c2    = m2.AtomClusters[j];
                rc2   = rot2to1 * c2 - dcm1t;
                dx2   = rc2.X * rc2.X;
                dy2   = rc2.Y * rc2.Y;
                dz2   = rc2.Z * rc2.Z;
                sumrv = m1.MaxRadius + c2.ClusterRadius;
                if ((dy2 + dz2 <= sumrv.X * sumrv.X) && (dx2 + dz2 <= sumrv.Y * sumrv.Y) && (dx2 + dy2 <= sumrv.Z * sumrv.Z))
                {
                    rc2cache[n2tocheck]    = c2;
                    c2tocheck[n2tocheck++] = j;
                }
            }

            for (int i = 0; i < m1.AtomClusters.Length; i++)
            {
                c1  = m1.AtomClusters[i];
                rc1 = rot1to2 * c1 + dcm2t;
                // if completely out of reach, skip the check
                dx2   = rc1.X * rc1.X;
                dy2   = rc1.Y * rc1.Y;
                dz2   = rc1.Z * rc1.Z;
                sumrv = m2.MaxRadius + c1.ClusterRadius;
                if ((dy2 + dz2 > sumrv.X * sumrv.X) || (dx2 + dz2 > sumrv.Y * sumrv.Y) || (dx2 + dy2 > sumrv.Z * sumrv.Z))
                {
                    continue;
                }
                // otherwise check selected clusters from m2
                for (int j = 0; j < n2tocheck; j++)
                {
                    j2   = c2tocheck[j];
                    rc2  = rc2cache[j];
                    c2   = m2.AtomClusters[j2];
                    dsq  = Vector3.SquareNormDiff(rc1, rc2);
                    sumr = c1.ClusterRadius + c2.ClusterRadius;
                    if (dsq < sumr * sumr) // clusters overlap, check all atoms
                    {
                        mustbechecked1[i]  = 1;
                        mustbechecked2[j2] = 1;
                        // clash |= CheckForClashes(c1, c2, im1, im2, dcm); // => replaced with unmanaged
                    }
                }
            }

            // this runs in m1's coordinate system!
            Vector3 fclash = new Vector3(), tclash1 = new Vector3(), tclash2 = new Vector3();
            double  dEClash = FpsNativeWrapper.CheckForClashes(FpsNativeWrapper.Aligned16(m1.XYZvdwRVectorArray),
                                                               FpsNativeWrapper.Aligned16(m2.XYZvdwRVectorArray), m1.AtomClusters, m2.AtomClusters,
                                                               m1.AtomClusters.Length, m2.AtomClusters.Length, mustbechecked1, mustbechecked2,
                                                               rot2to1, -dcm1t, kclash, ref fclash, ref tclash1, ref tclash2);

            force[im1]  += rotation[im1] * fclash;
            force[im2]  -= rotation[im1] * fclash;
            torque[im1] += rotation[im1] * tclash1;
            torque[im2] += rotation[im1] * tclash2;
            Eclash      += dEClash;

            return(dEClash > 1.0e-8);
        }
Example #4
0
        private void PrepareSimulation()
        {
            // molecules
            Nmolecules = _molecules.Count;
            int maxatomsincluster = 0;

            for (int i = 0; i < Nmolecules; i++)
            {
                minmass           = Math.Min(minmass, _molecules[i].Mass);
                maxatomsincluster = Math.Max(maxatomsincluster, _molecules[i].MaxAtomsInCluster);
            }

            // labeling positions
            int im;

            labelingpos_cm = new LabelingPositionList();
            labelingpos_cm.AddRange(this._labelingpositions);
            lpossim = new Vector3[labelingpos_cm.Count];
            LtoM    = new int[labelingpos_cm.Count];
            // convert to local coordinates
            for (int i = 0; i < labelingpos_cm.Count; i++)
            {
                im                 = _molecules.FindIndex(labelingpos_cm[i].Molecule);
                LtoM[i]            = im;
                labelingpos_cm[i] -= _molecules[im].CM;
                lpossim[i]         = labelingpos_cm[i];
            }

            // distances
            Distance dist_i;

            DtoL1      = new int[_distances.Count];
            DtoM1      = new int[_distances.Count];
            DtoL2      = new int[_distances.Count];
            DtoM2      = new int[_distances.Count];
            kplus      = new double[_distances.Count];
            kminus     = new double[_distances.Count];
            drmaxplus  = new double[_distances.Count];
            drmaxminus = new double[_distances.Count];
            double minerror = double.MaxValue;

            for (int i = 0; i < _distances.Count; i++)
            {
                DtoL1[i] = labelingpos_cm.FindIndex(_distances[i].Position1);
                DtoM1[i] = _molecules.FindIndex(labelingpos_cm.Find(_distances[i].Position1).Molecule);
                DtoL2[i] = labelingpos_cm.FindIndex(_distances[i].Position2);
                DtoM2[i] = _molecules.FindIndex(labelingpos_cm.Find(_distances[i].Position2).Molecule);

                // check if bond
                dist_i        = _distances[i];
                dist_i.IsBond = (labelingpos_cm[DtoL1[i]].Dye == DyeType.Unknown && labelingpos_cm[DtoL1[i]].AVData.AtomID > 0 &&
                                 labelingpos_cm[DtoL1[i]].AVData.AVType == AVSimlationType.None && labelingpos_cm[DtoL2[i]].Dye == DyeType.Unknown &&
                                 labelingpos_cm[DtoL2[i]].AVData.AtomID > 0 && labelingpos_cm[DtoL2[i]].AVData.AVType == AVSimlationType.None);
                _distances[i] = dist_i;

                // if bond, set small vdW radii to "exclude" from clashing
                if (dist_i.IsBond)
                {
                    foreach (var lp in new[] { labelingpos_cm[DtoL1[i]], labelingpos_cm[DtoL2[i]] })
                    {
                        int m     = _molecules.FindIndex(lp.Molecule);
                        int natom = Array.BinarySearch <int>(_molecules[m].OriginalAtomID, lp.AVData.AtomID);
                        _molecules[m].vdWR[natom] = AtomData.vdWRNoClash;
                        int natom_cluster = Array.FindIndex <int>(_molecules[m].ClusteredAtomOriginalIndex, n => n == natom);
                        if (natom_cluster >= 0)
                        {
                            _molecules[m].ClusteredAtomvdwR[natom_cluster] = AtomData.vdWRNoClash;
                            System.Runtime.InteropServices.Marshal.Copy(new[] { (float)AtomData.vdWRNoClash }, 0,
                                                                        FpsNativeWrapper.Aligned16(_molecules[m].XYZvdwRVectorArray) + (4 * natom_cluster + 3) * sizeof(float), 1);
                        }
                    }
                }

                // "spring constants"
                kplus[i]  = 2.0 / _distances[i].ErrPlus / _distances[i].ErrPlus;
                kminus[i] = 2.0 / _distances[i].ErrMinus / _distances[i].ErrMinus;
                //Console.Out.WriteLine("distance#" + i + " k+= " + kplus[i] + " k-= " + kminus[i] + " err+ " + _distances[i].ErrPlus + " err- " + _distances[i].ErrMinus);

                drmaxplus[i]  = SimulationParameters.MaxForce / kplus[i];
                drmaxminus[i] = -SimulationParameters.MaxForce / kminus[i];
                minerror      = Math.Min(minerror, Math.Min(_distances[i].ErrPlus, _distances[i].ErrMinus));
            }

            // simulation parameters
            kclash     = 2.0 / SimulationParameters.ClashTolerance / SimulationParameters.ClashTolerance;
            drmaxclash = -SimulationParameters.MaxForce / kclash;
            dr4dt      = Math.Min(SimulationParameters.ClashTolerance * 0.5, minerror);
        }
Example #5
0
        // process a structure
        public double CalculateChi2(ref FilteringResult fr)
        {
            Molecule m;

            if (fr.MoleculeWeakReference == null || !fr.MoleculeWeakReference.TryGetTarget(out m))
            {
                m = new Molecule(fr.FullFileName);
            }
            fr.MoleculeWeakReference = new WeakReference <Molecule>(m);
            if (m.Error.Length > 0)
            {
                System.Windows.Forms.MessageBox.Show("Error reading file " + fr.FullFileName + ": " + m.Error, "Error",
                                                     System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
                return(MiscData.ENotCalculated);
            }
            AVEngine         av = new AVEngine(m, avparam);
            Int32            natom, ilp = 0, ilp1, ilp2, iref, nref_total = 0;
            List <Vector3[]> avcache = new List <Vector3[]>(labelingpos.Count);

            Vector3[]     t;
            Vector3[]     rmp = new Vector3[labelingpos.Count];
            Vector3       cr, cm; Matrix3 U;
            ReferenceAtom rr;
            Double        R06 = _filterParameters.R0 * _filterParameters.R0 * _filterParameters.R0 *
                                _filterParameters.R0 * _filterParameters.R0 * _filterParameters.R0,
                          dr, refrmsd_t = 0.0;

            fr.E        = 0.0;
            fr.InvalidR = 0;
            fr.RefRMSD  = 0.0;
            fr.Sigma1   = 0;
            fr.Sigma2   = 0;
            fr.Sigma3   = 0;

            foreach (LabelingPosition l in this.labelingpos)
            {
                // calculate AVs and mean positions
                if (l.AVData.AVType == AVSimlationType.SingleDyeR)
                {
                    natom = Array.BinarySearch <Int32>(m.OriginalAtomID, l.AVData.AtomID);
                    av.Calculate1R(l.AVData.L, l.AVData.W, l.AVData.R, natom);
                    t = new Vector3[av.R.Length];
                    Array.Copy(av.R, t, av.R.Length);
                    avcache.Add(t);
                    rmp[ilp++] = av.Rmp;
                }
                else if (l.AVData.AVType == AVSimlationType.ThreeDyeR)
                {
                    natom = Array.BinarySearch <Int32>(m.OriginalAtomID, l.AVData.AtomID);
                    av.Calculate3R(l.AVData.L, l.AVData.W, l.AVData.R1, l.AVData.R2, l.AVData.R3, natom);
                    t = new Vector3[av.R.Length];
                    Array.Copy(av.R, t, av.R.Length);
                    avcache.Add(t);
                    rmp[ilp++] = av.Rmp;
                }
                else if (l.AVData.AVType == AVSimlationType.None && referenceAtoms[ilp].Length > 0)
                {
                    // align reference atoms with the structure
                    // translation
                    cr = new Vector3();
                    cm = new Vector3();
                    for (iref = 0; iref < referenceAtoms[ilp].Length; iref++)
                    {
                        rr    = referenceAtoms[ilp][iref];
                        natom = rr.ConvertedN;
                        cr   += rr;
                        cm   += new Vector3(m.XLocal[natom] + m.CM.X, m.YLocal[natom] + m.CM.Y, m.ZLocal[natom] + m.CM.Z);
                    }
                    cr *= -1.0 / ((Double)referenceAtoms[ilp].Length);
                    cm *= -1.0 / ((Double)referenceAtoms[ilp].Length);

                    // rotation: see also SimulationResult.CalculateBestFitRotation
                    Mapack.Matrix Rxt = new Mapack.Matrix(referenceAtoms[ilp].Length, 3);
                    Mapack.Matrix Ry  = new Mapack.Matrix(3, referenceAtoms[ilp].Length);

                    for (iref = 0; iref < referenceAtoms[ilp].Length; iref++)
                    {
                        rr           = referenceAtoms[ilp][iref];
                        natom        = rr.ConvertedN;
                        Rxt[iref, 0] = rr.X + cr.X; Rxt[iref, 1] = rr.Y + cr.Y; Rxt[iref, 2] = rr.Z + cr.Z;
                        Ry[0, iref]  = m.XLocal[natom] + m.CM.X + cm.X;
                        Ry[1, iref]  = m.YLocal[natom] + m.CM.Y + cm.Y;
                        Ry[2, iref]  = m.ZLocal[natom] + m.CM.Z + cm.Z;
                    }

                    // Kabsch solution
                    Mapack.Matrix R = Ry * Rxt;
                    Mapack.SingularValueDecomposition svdR = new Mapack.SingularValueDecomposition(R);
                    Mapack.Matrix V  = svdR.VMatrix;
                    Mapack.Matrix rS = new Mapack.Matrix(3, 3);
                    rS[0, 0] = 1.0 / svdR.Diagonal[0];
                    rS[1, 1] = 1.0 / svdR.Diagonal[1];
                    rS[2, 2] = (R.Determinant > 0.0) ? 1.0 / svdR.Diagonal[2] : -1.0 / svdR.Diagonal[2];
                    Mapack.Matrix Um = R * V * rS * V.Transpose();
                    U = new Matrix3(Um[0, 0], Um[0, 1], Um[0, 2],
                                    Um[1, 0], Um[1, 1], Um[1, 2], Um[2, 0], Um[2, 1], Um[2, 2]);
                    U = Matrix3.RepairRotation(U);

                    // reference rmsd
                    for (iref = 0; iref < referenceAtoms[ilp].Length; iref++)
                    {
                        rr         = referenceAtoms[ilp][iref];
                        natom      = rr.ConvertedN;
                        refrmsd_t += Vector3.SquareNormDiff(U * (rr + cr),
                                                            new Vector3(m.XLocal[natom], m.YLocal[natom], m.ZLocal[natom]) + m.CM + cm);
                        nref_total++;
                    }

                    rmp[ilp++] = U * (l + cr) - cm;
                    avcache.Add(new Vector3[0]);
                }
                else
                {
                    rmp[ilp++] = l;
                    avcache.Add(new Vector3[0]);
                }
            }

            // calculate mp and FRET distances
            Distance d, dmp;
            Int32    activeR = 0;

            fr.RModel            = new DistanceList(dist.Count);
            fr.RmpModel          = new DistanceList(dist.Count);
            fr.RmpModel.DataType = dist.DataType;
            for (Int32 i = 0; i < dist.Count; i++)
            {
                dmp           = new Distance();
                d             = new Distance();
                dmp.Position1 = dist[i].Position1;
                dmp.Position2 = dist[i].Position2;
                d.Position1   = dist[i].Position1;
                d.Position2   = dist[i].Position2;
                ilp1          = labelingpos.FindIndex(d.Position1);
                ilp2          = labelingpos.FindIndex(d.Position2);
                dmp.R         = Vector3.Abs(rmp[ilp1] - rmp[ilp2]);
                if (dist.DataType == DistanceDataType.Rmp ||
                    labelingpos[ilp1].AVData.AVType == AVSimlationType.None || labelingpos[ilp2].AVData.AVType == AVSimlationType.None)
                {
                    d.R = dmp.R; // i.e. no clouds -> Rmp
                }
                else if (dist.DataType == DistanceDataType.RDAMeanE)
                {
                    if (avcache[ilp1].Length == 0 || avcache[ilp2].Length == 0)
                    {
                        d.R = Double.NaN;
                    }
                    else
                    {
                        d.R = FpsNativeWrapper.RdaMeanEFromAv(avcache[ilp1], avcache[ilp1].Length, avcache[ilp2], avcache[ilp2].Length,
                                                              avparam.ESamples, rnd.Next(), this._filterParameters.R0);
                    }
                }
                else if (dist.DataType == DistanceDataType.RDAMean)
                {
                    if (avcache[ilp1].Length == 0 || avcache[ilp2].Length == 0)
                    {
                        d.R = Double.NaN;
                    }
                    else
                    {
                        d.R = FpsNativeWrapper.RdaMeanFromAv(avcache[ilp1], avcache[ilp1].Length, avcache[ilp2], avcache[ilp2].Length,
                                                             avparam.ESamples, rnd.Next());
                    }
                }

                fr.RModel.Add(d);
                fr.RmpModel.Add(dmp);

                dr = d.R - dist[i].R;
                if (Double.IsNaN(d.R))
                {
                    fr.InvalidR++;
                }
                else if (!this._filterParameters.OptimizeSelected || dist[i].IsSelected)
                {
                    fr.E += dr > 0.0 ? dr * dr / dist[i].ErrPlus / dist[i].ErrPlus :
                            dr * dr / dist[i].ErrMinus / dist[i].ErrMinus;
                    activeR++;
                    if (dr > dist[i].ErrPlus)
                    {
                        fr.Sigma1++;
                    }
                    if (dr > 2.0 * dist[i].ErrPlus)
                    {
                        fr.Sigma2++;
                    }
                    if (dr > 3.0 * dist[i].ErrPlus)
                    {
                        fr.Sigma3++;
                    }
                    if (dr < -dist[i].ErrMinus)
                    {
                        fr.Sigma1++;
                    }
                    if (dr < -2.0 * dist[i].ErrMinus)
                    {
                        fr.Sigma2++;
                    }
                    if (dr < -3.0 * dist[i].ErrMinus)
                    {
                        fr.Sigma3++;
                    }
                }
            }

            fr.E       = fr.E / (Double)activeR;
            fr.RefRMSD = nref_total == 0 ? 0.0 : Math.Sqrt(refrmsd_t / (Double)nref_total);
            return(fr.E);
        }