/// <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; }
/// <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; }
// 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); }
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); }
// 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); }