//Calculate score based on All possible Products Masses for inter- or intra- crosslinks and deadend. public static void XlLocalizationForLoopCrosslink(Ms2ScanWithSpecificMass theScan, PsmCross psmCross, double modMass, CrosslinkerTypeClass crosslinker, List <ProductType> lp, Tolerance fragmentTolerance, List <int> linkPos) { var pmmhList = PsmCross.XlCalculateTotalProductMassesForLoopCrosslink(psmCross, modMass, crosslinker, lp, linkPos); List <double> scoreList = new List <double>(); List <MatchedIonInfo> miil = new List <MatchedIonInfo>(); foreach (var pmm in pmmhList) { var matchedIonMassesListPositiveIsMatch = new MatchedIonInfo(pmm.ProductMz.Length); double pmmScore = PsmCross.XlMatchIons(theScan.TheScan, fragmentTolerance, pmm.ProductMz, pmm.ProductName, matchedIonMassesListPositiveIsMatch); miil.Add(matchedIonMassesListPositiveIsMatch); scoreList.Add(pmmScore); } psmCross.XLBestScore = scoreList.Max(); psmCross.MatchedIonInfo = miil[scoreList.IndexOf(scoreList.Max())]; psmCross.XlPos = pmmhList[scoreList.IndexOf(scoreList.Max())].XlPos + 1; psmCross.XlPos2 = pmmhList[scoreList.IndexOf(scoreList.Max())].XlPos2 + 1; }
//Calculate score based on Product Masses. public static double XlMatchIons(IMsDataScan <IMzSpectrum <IMzPeak> > thisScan, Tolerance productMassTolerance, double[] sorted_theoretical_product_masses_for_this_peptide, string[] sorted_theoretical_product_name_for_this_peptide, MatchedIonInfo matchedIonMassesListPositiveIsMatch) { var TotalProductsHere = sorted_theoretical_product_masses_for_this_peptide.Length; if (TotalProductsHere == 0) { return(0); } int MatchingProductsHere = 0; double MatchingIntensityHere = 0; // speed optimizations double[] experimental_mzs = thisScan.MassSpectrum.XArray; double[] experimental_intensities = thisScan.MassSpectrum.YArray; int[] experimental_intensities_rank = GenerateIntensityRanks(experimental_mzs, experimental_intensities); int num_experimental_peaks = experimental_mzs.Length; int currentTheoreticalIndex = -1; double currentTheoreticalMass; do { currentTheoreticalIndex++; currentTheoreticalMass = sorted_theoretical_product_masses_for_this_peptide[currentTheoreticalIndex]; } while (double.IsNaN(currentTheoreticalMass) && currentTheoreticalIndex < sorted_theoretical_product_masses_for_this_peptide.Length - 1); if (double.IsNaN(currentTheoreticalMass)) { return(0); } double currentTheoreticalMz = currentTheoreticalMass + Constants.protonMass; int testTheoreticalIndex; double testTheoreticalMZ; double testTheoreticalMass; // Loop over all experimenal indices for (int experimentalIndex = 0; experimentalIndex < num_experimental_peaks; experimentalIndex++) { double currentExperimentalMZ = experimental_mzs[experimentalIndex]; // If found match if (productMassTolerance.Within(currentExperimentalMZ, currentTheoreticalMz)) { MatchingProductsHere++; MatchingIntensityHere += experimental_intensities[experimentalIndex]; matchedIonMassesListPositiveIsMatch.MatchedIonMz[currentTheoreticalIndex] = currentTheoreticalMass; matchedIonMassesListPositiveIsMatch.MatchedIonIntensity[currentTheoreticalIndex] = experimental_intensities[experimentalIndex]; matchedIonMassesListPositiveIsMatch.MatchedIonName[currentTheoreticalIndex] = sorted_theoretical_product_name_for_this_peptide[currentTheoreticalIndex]; matchedIonMassesListPositiveIsMatch.MatchedIonIntensityRank[currentTheoreticalIndex] = experimental_intensities_rank[experimentalIndex]; currentTheoreticalIndex++; if (currentTheoreticalIndex == TotalProductsHere) { break; } currentTheoreticalMass = sorted_theoretical_product_masses_for_this_peptide[currentTheoreticalIndex]; currentTheoreticalMz = currentTheoreticalMass + Constants.protonMass; } // Else if for sure did not reach the next theoretical yet, move to next experimental else if (currentExperimentalMZ < currentTheoreticalMz) { continue; } // Else if for sure passed a theoretical else { // Mark the theoretical as missed matchedIonMassesListPositiveIsMatch.MatchedIonMz[currentTheoreticalIndex] = -currentTheoreticalMass; // Move on to next index and never come back! currentTheoreticalIndex++; if (currentTheoreticalIndex == TotalProductsHere) { break; } currentTheoreticalMass = sorted_theoretical_product_masses_for_this_peptide[currentTheoreticalIndex]; currentTheoreticalMz = currentTheoreticalMass + Constants.protonMass; // Start with the current ones testTheoreticalIndex = currentTheoreticalIndex; testTheoreticalMZ = currentTheoreticalMz; testTheoreticalMass = currentTheoreticalMass; // Mark the skipped theoreticals as not found. The last one is not for sure, might be flipped! while (currentExperimentalMZ > testTheoreticalMZ) { matchedIonMassesListPositiveIsMatch.MatchedIonMz[testTheoreticalIndex] = -currentTheoreticalMass; // Store old info for possible reuse currentTheoreticalMass = testTheoreticalMass; currentTheoreticalMz = testTheoreticalMZ; currentTheoreticalIndex = testTheoreticalIndex; // Update test stuff! testTheoreticalIndex++; if (testTheoreticalIndex == TotalProductsHere) { break; } testTheoreticalMass = sorted_theoretical_product_masses_for_this_peptide[testTheoreticalIndex]; testTheoreticalMZ = testTheoreticalMass + Constants.protonMass; } experimentalIndex--; } } return(MatchingProductsHere + MatchingIntensityHere / thisScan.TotalIonCurrent); }
//Calculate score based on All possible Products Masses for inter- or intra- crosslinks and deadend. public static void XlLocalization(Ms2ScanWithSpecificMass theScan, PsmCross psmCross, double modMass, CrosslinkerTypeClass crosslinker, List <ProductType> lp, Tolerance fragmentTolerance, bool Charge_2_3, bool Charge_2_3_PrimeFragment, List <int> linkPos) { var pmmhList = PsmCross.XlCalculateTotalProductMasses(psmCross, modMass, crosslinker, lp, Charge_2_3, Charge_2_3_PrimeFragment, linkPos); List <double> scoreList = new List <double>(); List <MatchedIonInfo> miil = new List <MatchedIonInfo>(); foreach (var pmm in pmmhList) { var matchedIonMassesListPositiveIsMatch = new MatchedIonInfo(pmm.ProductMz.Length); double pmmScore = PsmCross.XlMatchIons(theScan.TheScan, fragmentTolerance, pmm.ProductMz, pmm.ProductName, matchedIonMassesListPositiveIsMatch); miil.Add(matchedIonMassesListPositiveIsMatch); scoreList.Add(pmmScore); } psmCross.XLBestScore = scoreList.Max(); psmCross.MatchedIonInfo = miil[scoreList.IndexOf(scoreList.Max())]; psmCross.XlPos = pmmhList[scoreList.IndexOf(scoreList.Max())].XlPos + 1; if (crosslinker.Cleavable) { psmCross.ParentIonMaxIntensityRanks = new List <int>(); if (psmCross.MatchedIonInfo.MatchedIonName.Any(p => p != null && p.Contains("PepS"))) { psmCross.ParentIonExist += "PepS"; psmCross.ParentIonExistNum += 1; } if (psmCross.MatchedIonInfo.MatchedIonName.Any(p => p != null && p.Contains("PepL"))) { psmCross.ParentIonExist += "PepL"; psmCross.ParentIonExistNum += 1; } //if (psmCross.MatchedIonInfo.MatchedIonName.Any(p => p != null && p.Equals("PepS2"))) //{ // psmCross.ParentIonExist += "PepS2"; // psmCross.ParentIonExistNum += 1; //} //if (psmCross.MatchedIonInfo.MatchedIonName.Any(p => p != null && p.Equals("PepL2"))) //{ // psmCross.ParentIonExist += "PepL2"; // psmCross.ParentIonExistNum += 1; //} for (int i = 0; i < psmCross.MatchedIonInfo.MatchedIonName.Length; i++) { if (psmCross.MatchedIonInfo.MatchedIonName[i] != null) { if (psmCross.MatchedIonInfo.MatchedIonName[i].Contains("Pep")) { psmCross.ParentIonMaxIntensityRanks.Add(psmCross.MatchedIonInfo.MatchedIonIntensityRank[i]); } } } } if (Charge_2_3 || Charge_2_3_PrimeFragment) { int Charge2IonExist = 0; for (int i = 0; i < psmCross.MatchedIonInfo.MatchedIonName.Length; i++) { if (psmCross.MatchedIonInfo.MatchedIonName[i] != null && (psmCross.MatchedIonInfo.MatchedIonName[i].Contains("t2") || psmCross.MatchedIonInfo.MatchedIonName[i].Contains("t3"))) { Charge2IonExist++; } } psmCross.Charge2IonExist = Charge2IonExist; } }