// 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); }
// 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); }
/// <summary> /// Read reference atoms from an LP file /// </summary> /// <param name="m">Example molecule</param> /// <param name="classicpdb">True for pdb line format, false if tab-delimited</param> public void ReadRefAtoms(Molecule m, Boolean classicpdb) { // re-read the lp file to get reference frames referenceAtoms = new List <ReferenceAtom[]>(labelingpos.Count); Int32 j; String[] strdata; strdata = System.IO.File.ReadAllLines(labelingpos.FullPath); String[] tmpstr; Double x, y, z; Char[] separator = new Char[] { ' ', '\t' }; ReferenceAtom[] reftmp; for (Int32 i = 0; i < strdata.Length; i++) { // find LP line if (!LabelingPositionList.ValidLPLine(strdata[i])) { continue; } // now LP is found, count following pdb lines if any j = 0; if (classicpdb) { while (i + j + 1 < strdata.Length && strdata[i + j + 1].Length > 54 && strdata[i + j + 1].Substring(0, 4) == "ATOM") { j++; } } else { while (i + j + 1 < strdata.Length && strdata[i + j + 1].Length > 10 && strdata[i + j + 1].Substring(0, 4) == "ATOM") { j++; } } reftmp = new ReferenceAtom[j]; // read reference atoms j = 0; if (classicpdb) { while (i + j + 1 < strdata.Length && strdata[i + j + 1].Length > 54 && strdata[i + j + 1].Substring(0, 4) == "ATOM") { tmpstr = strdata[i + j + 1].Split(separator, StringSplitOptions.RemoveEmptyEntries); reftmp[j].OriginalN = Int32.Parse(tmpstr[1]); reftmp[j].ConvertedN = Array.BinarySearch <Int32>(m.OriginalAtomID, reftmp[j].OriginalN); if (Double.TryParse(strdata[i + j + 1].Substring(30, 8), out x) && Double.TryParse(strdata[i + j + 1].Substring(38, 8), out y) && Double.TryParse(strdata[i + j + 1].Substring(46, 8), out z)) { reftmp[j].X = x; reftmp[j].Y = y; reftmp[j].Z = z; } j++; } } else { while (i + j + 1 < strdata.Length && strdata[i + j + 1].Length > 10 && strdata[i + j + 1].Substring(0, 4) == "ATOM") { tmpstr = strdata[i + j + 1].Split(separator, StringSplitOptions.RemoveEmptyEntries); reftmp[j].OriginalN = Int32.Parse(tmpstr[1]); reftmp[j].ConvertedN = Array.BinarySearch <Int32>(m.OriginalAtomID, reftmp[j].OriginalN); if (Double.TryParse(tmpstr[6], out x) && Double.TryParse(tmpstr[7], out y) && Double.TryParse(tmpstr[8], out z)) { reftmp[j].X = x; reftmp[j].Y = y; reftmp[j].Z = z; } j++; } } referenceAtoms.Add(reftmp); i += j; } }