private List <MatchedFragmentIon> ScoreChildScan(Ms2ScanWithSpecificMass parentScan, Ms2ScanWithSpecificMass childScan, int possibleSite, BestPeptideScoreNotch mainPeptide, BestPeptideScoreNotch otherPeptide) { bool shortMassAlphaMs3 = XLPrecusorSearchMode.Accepts(childScan.PrecursorMass, mainPeptide.BestPeptide.MonoisotopicMass + Crosslinker.CleaveMassShort) >= 0; bool longMassAlphaMs3 = XLPrecusorSearchMode.Accepts(childScan.PrecursorMass, mainPeptide.BestPeptide.MonoisotopicMass + Crosslinker.CleaveMassLong) >= 0; List <Product> childProducts; if (Crosslinker.Cleavable && (shortMassAlphaMs3 || longMassAlphaMs3)) { double massToLocalize = shortMassAlphaMs3 ? Crosslinker.CleaveMassShort : Crosslinker.CleaveMassLong; if (mainPeptide.BestPeptide.AllModsOneIsNterminus.TryGetValue(possibleSite + 1, out var existingMod)) { massToLocalize += existingMod.MonoisotopicMass.Value; } Dictionary <int, Modification> mod = new Dictionary <int, Modification> { { possibleSite + 1, new Modification(_monoisotopicMass: massToLocalize) } }; foreach (var otherExistingMod in mainPeptide.BestPeptide.AllModsOneIsNterminus.Where(p => p.Key != possibleSite + 1)) { mod.Add(otherExistingMod.Key, otherExistingMod.Value); } var peptideWithMod = new PeptideWithSetModifications(mainPeptide.BestPeptide.Protein, mainPeptide.BestPeptide.DigestionParams, mainPeptide.BestPeptide.OneBasedStartResidueInProtein, mainPeptide.BestPeptide.OneBasedEndResidueInProtein, mainPeptide.BestPeptide.CleavageSpecificityForFdrCategory, mainPeptide.BestPeptide.PeptideDescription, mainPeptide.BestPeptide.MissedCleavages, mod, mainPeptide.BestPeptide.NumFixedMods); childProducts = peptideWithMod.Fragment(CommonParameters.ChildScanDissociationType, FragmentationTerminus.Both).ToList(); } else if (Math.Abs(childScan.PrecursorMass - parentScan.PrecursorMass) < 0.01 && CommonParameters.DissociationType != CommonParameters.ChildScanDissociationType) { // same species got fragmented twice, the second time with a different dissociation type childProducts = CrosslinkedPeptide.XlGetTheoreticalFragments(CommonParameters.ChildScanDissociationType, Crosslinker, new List <int> { possibleSite }, otherPeptide.BestPeptide.MonoisotopicMass, mainPeptide.BestPeptide).First().Item2; } else { return(null); } var matchedChildIons = MatchFragmentIons(childScan, childProducts, CommonParameters); return(matchedChildIons); }
protected override MetaMorpheusEngineResults RunSpecific() { double progress = 0; int oldPercentProgress = 0; ReportProgress(new ProgressEventArgs(oldPercentProgress, "Performing crosslink search... " + CurrentPartition + "/" + commonParameters.TotalPartitions, nestedIds)); byte byteScoreCutoff = (byte)commonParameters.ScoreCutoff; Parallel.ForEach(Partitioner.Create(0, ListOfSortedms2Scans.Length), new ParallelOptions { MaxDegreeOfParallelism = commonParameters.MaxThreadsToUsePerFile }, (range, loopState) => { byte[] scoringTable = new byte[PeptideIndex.Count]; List <int> idsOfPeptidesPossiblyObserved = new List <int>(); for (int i = range.Item1; i < range.Item2; i++) { // Stop loop if canceled if (GlobalVariables.StopLoops) { loopState.Stop(); return; } // empty the scoring table to score the new scan (conserves memory compared to allocating a new array) Array.Clear(scoringTable, 0, scoringTable.Length); idsOfPeptidesPossiblyObserved.Clear(); var scan = ListOfSortedms2Scans[i]; // get fragment bins for this scan List <int> allBinsToSearch = GetBinsToSearch(scan); List <BestPeptideScoreNotch> bestPeptideScoreNotchList = new List <BestPeptideScoreNotch>(); // get allowed theoretical masses from the known experimental mass // note that this is the OPPOSITE of the classic search (which calculates experimental masses from theoretical values) // this is just PRELIMINARY precursor-mass filtering // additional checks are made later to ensure that the theoretical precursor mass is acceptable var notches = MassDiffAcceptor.GetAllowedPrecursorMassIntervals(scan.PrecursorMass); double lowestMassPeptideToLookFor = Double.NegativeInfinity; double highestMassPeptideToLookFor = Double.PositiveInfinity; double largestMassDiff = notches.Max(p => p.AllowedInterval.Maximum); double smallestMassDiff = notches.Min(p => p.AllowedInterval.Minimum); if (!Double.IsInfinity(largestMassDiff)) { double largestOppositeMassDiff = -1 * (notches.Max(p => p.AllowedInterval.Maximum) - scan.PrecursorMass); lowestMassPeptideToLookFor = scan.PrecursorMass + largestOppositeMassDiff; } if (!Double.IsNegativeInfinity(smallestMassDiff)) { double smallestOppositeMassDiff = -1 * (notches.Min(p => p.AllowedInterval.Minimum) - scan.PrecursorMass); highestMassPeptideToLookFor = scan.PrecursorMass + smallestOppositeMassDiff; } // first-pass scoring IndexedScoring(allBinsToSearch, scoringTable, byteScoreCutoff, idsOfPeptidesPossiblyObserved, scan.PrecursorMass, lowestMassPeptideToLookFor, highestMassPeptideToLookFor); // done with indexed scoring; refine scores and create PSMs if (idsOfPeptidesPossiblyObserved.Any()) { List <int> idsRankedByScore = new List <int>(); foreach (var id in idsOfPeptidesPossiblyObserved) { idsRankedByScore.Add(id); } idsRankedByScore = idsRankedByScore.OrderByDescending(p => scoringTable[p]).ToList(); idsRankedByScore = idsRankedByScore.Take(CrosslinkSearchTopNum).ToList(); if (CrosslinkSearchTop) { idsOfPeptidesPossiblyObserved = idsRankedByScore; } foreach (var id in idsOfPeptidesPossiblyObserved) { var peptide = PeptideIndex[id]; double thePrecursorMass = scan.PrecursorMass; int notch = MassDiffAcceptor.Accepts(scan.PrecursorMass, peptide.MonoisotopicMassIncludingFixedMods); BestPeptideScoreNotch bestPeptideScoreNotch = new BestPeptideScoreNotch(peptide, scoringTable[id], notch); bestPeptideScoreNotchList.Add(bestPeptideScoreNotch); } var possiblePsmCross = FindCrosslinkedPeptide(scan, bestPeptideScoreNotchList, i); if (possiblePsmCross != null) { lock (GlobalPsmsCross) GlobalPsmsCross.Add(possiblePsmCross); } } // report search progress progress++; var percentProgress = (int)((progress / ListOfSortedms2Scans.Length) * 100); if (percentProgress > oldPercentProgress) { oldPercentProgress = percentProgress; ReportProgress(new ProgressEventArgs(percentProgress, "Performing crosslink search... " + CurrentPartition + "/" + commonParameters.TotalPartitions, nestedIds)); } } }); return(new MetaMorpheusEngineResults(this)); }
/// <summary> /// Localizes the crosslink position on the alpha and beta peptides /// </summary> private CrosslinkSpectralMatch LocalizeCrosslinkSites(Ms2ScanWithSpecificMass theScan, BestPeptideScoreNotch alphaPeptide, BestPeptideScoreNotch betaPeptide, Crosslinker crosslinker, int ind, int inx) { CrosslinkSpectralMatch localizedCrosslinkedSpectralMatch = null; List <Tuple <List <int>, List <int> > > pairs = new List <Tuple <List <int>, List <int> > >(); if (crosslinker.CrosslinkerModSites.Equals(crosslinker.CrosslinkerModSites2)) { List <int> possibleAlphaXlSites = CrosslinkSpectralMatch.GetPossibleCrosslinkerModSites(crosslinker.CrosslinkerModSites.ToCharArray(), alphaPeptide.BestPeptide); List <int> possibleBetaXlSites = CrosslinkSpectralMatch.GetPossibleCrosslinkerModSites(crosslinker.CrosslinkerModSites.ToCharArray(), betaPeptide.BestPeptide); pairs.Add(new Tuple <List <int>, List <int> >(possibleAlphaXlSites, possibleBetaXlSites)); } else { List <int> possibleAlphaXlSites = CrosslinkSpectralMatch.GetPossibleCrosslinkerModSites(crosslinker.CrosslinkerModSites.ToCharArray(), alphaPeptide.BestPeptide); List <int> possibleBetaXlSites = CrosslinkSpectralMatch.GetPossibleCrosslinkerModSites(crosslinker.CrosslinkerModSites2.ToCharArray(), betaPeptide.BestPeptide); pairs.Add(new Tuple <List <int>, List <int> >(possibleAlphaXlSites, possibleBetaXlSites)); possibleAlphaXlSites = CrosslinkSpectralMatch.GetPossibleCrosslinkerModSites(crosslinker.CrosslinkerModSites2.ToCharArray(), alphaPeptide.BestPeptide); possibleBetaXlSites = CrosslinkSpectralMatch.GetPossibleCrosslinkerModSites(crosslinker.CrosslinkerModSites.ToCharArray(), betaPeptide.BestPeptide); pairs.Add(new Tuple <List <int>, List <int> >(possibleAlphaXlSites, possibleBetaXlSites)); } foreach (var pair in pairs) { List <int> possibleAlphaXlSites = pair.Item1; List <int> possibleBetaXlSites = pair.Item2; if (possibleAlphaXlSites.Any() && possibleBetaXlSites.Any()) { int bestAlphaSite = 0; int bestBetaSite = 0; List <MatchedFragmentIon> bestMatchedAlphaIons = new List <MatchedFragmentIon>(); List <MatchedFragmentIon> bestMatchedBetaIons = new List <MatchedFragmentIon>(); Dictionary <int, List <MatchedFragmentIon> > bestMatchedChildAlphaIons = new Dictionary <int, List <MatchedFragmentIon> >(); Dictionary <int, List <MatchedFragmentIon> > bestMatchedChildBetaIons = new Dictionary <int, List <MatchedFragmentIon> >(); double bestAlphaLocalizedScore = 0; double bestBetaLocalizedScore = 0; var fragmentsForEachAlphaLocalizedPossibility = CrosslinkedPeptide.XlGetTheoreticalFragments(CommonParameters.DissociationType, Crosslinker, possibleAlphaXlSites, betaPeptide.BestPeptide.MonoisotopicMass, alphaPeptide.BestPeptide).ToList(); foreach (int possibleSite in possibleAlphaXlSites) { foreach (var setOfFragments in fragmentsForEachAlphaLocalizedPossibility.Where(v => v.Item1 == possibleSite)) { var matchedChildAlphaIons = new Dictionary <int, List <MatchedFragmentIon> >(); var matchedIons = MatchFragmentIons(theScan, setOfFragments.Item2, CommonParameters); double score = CalculatePeptideScore(theScan.TheScan, matchedIons); // search child scans (MS2+MS3) foreach (Ms2ScanWithSpecificMass childScan in theScan.ChildScans) { var matchedChildIons = ScoreChildScan(theScan, childScan, possibleSite, alphaPeptide, betaPeptide); if (matchedChildIons == null) { continue; } matchedChildAlphaIons.Add(childScan.OneBasedScanNumber, matchedChildIons); //double childScore = CalculatePeptideScore(childScan.TheScan, matchedChildIons); //score += childScore; } if (score > bestAlphaLocalizedScore) { bestAlphaLocalizedScore = score; bestAlphaSite = possibleSite; bestMatchedAlphaIons = matchedIons; bestMatchedChildAlphaIons = matchedChildAlphaIons; } } } var fragmentsForEachBetaLocalizedPossibility = CrosslinkedPeptide.XlGetTheoreticalFragments(CommonParameters.DissociationType, Crosslinker, possibleBetaXlSites, alphaPeptide.BestPeptide.MonoisotopicMass, betaPeptide.BestPeptide).ToList(); var alphaMz = new HashSet <double>(bestMatchedAlphaIons.Select(p => p.Mz)); foreach (int possibleSite in possibleBetaXlSites) { foreach (var setOfFragments in fragmentsForEachBetaLocalizedPossibility.Where(v => v.Item1 == possibleSite)) { var matchedIons = MatchFragmentIons(theScan, setOfFragments.Item2, CommonParameters); var matchedChildBetaIons = new Dictionary <int, List <MatchedFragmentIon> >(); // remove any matched beta ions that also matched to the alpha peptide matchedIons.RemoveAll(p => alphaMz.Contains(p.Mz)); double score = CalculatePeptideScore(theScan.TheScan, matchedIons); // search child scans (MS2+MS3) foreach (Ms2ScanWithSpecificMass childScan in theScan.ChildScans) { var matchedChildIons = ScoreChildScan(theScan, childScan, possibleSite, betaPeptide, alphaPeptide); if (matchedChildIons == null) { continue; } matchedChildBetaIons.Add(childScan.OneBasedScanNumber, matchedChildIons); //double childScore = CalculatePeptideScore(childScan.TheScan, matchedChildIons); //score += childScore; } if (score > bestBetaLocalizedScore) { bestBetaLocalizedScore = score; bestBetaSite = possibleSite; bestMatchedBetaIons = matchedIons; bestMatchedChildBetaIons = matchedChildBetaIons; } } } if (bestAlphaLocalizedScore < CommonParameters.ScoreCutoff || bestBetaLocalizedScore < CommonParameters.ScoreCutoff) { return(null); } var localizedAlpha = new CrosslinkSpectralMatch(alphaPeptide.BestPeptide, alphaPeptide.BestNotch, bestAlphaLocalizedScore, 0, theScan, alphaPeptide.BestPeptide.DigestionParams, bestMatchedAlphaIons); var localizedBeta = new CrosslinkSpectralMatch(betaPeptide.BestPeptide, betaPeptide.BestNotch, bestBetaLocalizedScore, 0, theScan, betaPeptide.BestPeptide.DigestionParams, bestMatchedBetaIons); localizedAlpha.XlRank = new List <int> { ind, inx }; localizedAlpha.XLTotalScore = localizedAlpha.Score + localizedBeta.Score; localizedAlpha.BetaPeptide = localizedBeta; localizedAlpha.ChildMatchedFragmentIons = bestMatchedChildAlphaIons; localizedBeta.ChildMatchedFragmentIons = bestMatchedChildBetaIons; if (crosslinker.Cleavable) { //TODO: re-enable intensity ranks //psmCrossAlpha.ParentIonMaxIntensityRanks = psmCrossAlpha.MatchedFragmentIons.Where(p => p.NeutralTheoreticalProduct.ProductType == ProductType.M).Select(p => p.IntensityRank).ToList(); //localizedAlpha.ParentIonMaxIntensityRanks = new List<int>(); //localizedAlpha.ParentIonExistNum = psmCrossAlpha.ParentIonMaxIntensityRanks.Count; } localizedAlpha.CrossType = PsmCrossType.Cross; localizedCrosslinkedSpectralMatch = localizedAlpha; localizedCrosslinkedSpectralMatch.LinkPositions = new List <int> { bestAlphaSite }; localizedCrosslinkedSpectralMatch.BetaPeptide.LinkPositions = new List <int> { bestBetaSite }; } } return(localizedCrosslinkedSpectralMatch); }