private static int GetSurroundingAlignments(IList <PeakAlignment> alignList, PeakMatchData target, out PeakAlignment prev, out PeakAlignment next) { prev = next = null; if (!alignList.Any()) { return(0); } var insertPos = alignList.Select(align => align.ReferencePeak).ToList().BinarySearch(target, RT_COMPARER); if (insertPos < 0) { insertPos = ~insertPos; } if (insertPos == 0) { next = alignList.First(); } else if (insertPos != alignList.Count) { prev = alignList[insertPos - 1]; next = alignList[insertPos]; } else { prev = alignList.Last(); } return(insertPos); }
private static PeakMatch MakePeakMatchBetween(float scale, PeakMatchData referenceTarget, PeakAlignment prev, PeakAlignment next) { if (prev == null && next == null) { return(null); } float startTime, endTime; var range = scale * (referenceTarget.EndTime - referenceTarget.StartTime); if (prev != null && next != null) { startTime = prev.AlignedPeak.RetentionTime + scale * (referenceTarget.StartTime - prev.ReferencePeak.RetentionTime); endTime = next.AlignedPeak.RetentionTime - scale * (next.ReferencePeak.RetentionTime - referenceTarget.EndTime); } else if (next != null) { endTime = next.AlignedPeak.StartTime - scale * (next.ReferencePeak.StartTime - referenceTarget.EndTime); startTime = endTime - range; } else { startTime = prev.AlignedPeak.EndTime + scale * (referenceTarget.StartTime - prev.ReferencePeak.EndTime); endTime = startTime + range; } return(new PeakMatch(startTime + (referenceTarget.ShiftLeft * range), endTime + (referenceTarget.ShiftRight * range))); }
public double GetMatchScore(PeakMatchData other) { var timeMin = Math.Min(MinTime, other.MinTime); var timeMax = Math.Max(MaxTime, other.MaxTime); return(SCORE_DOT_WEIGHT * Abundances.Dot(other.Abundances) + SCORE_RT_WEIGHT * (1 - Math.Abs((RetentionTime - timeMin) - (other.RetentionTime - timeMin)) / (timeMax - timeMin)) + SCORE_AREA_WEIGHT * (1 - Math.Abs(PercentArea - other.PercentArea))); }
public PeakAlignment(PeakMatchData referencePeak, PeakMatchData alignedPeak) { ReferencePeak = referencePeak; AlignedPeak = alignedPeak; }
private static void GetReferenceData(SrmDocument doc, PeptideDocNode nodePep, TransitionGroupDocNode nodeTranGroup, int resultsIndex, ChromFileInfoId resultsFile, out PeakMatchData referenceTarget, out PeakMatchData[] referenceMatchData, out DateTime?runTime) { referenceTarget = null; referenceMatchData = new PeakMatchData[0]; runTime = null; var referenceMatchDataList = new List <PeakMatchData>(); var mzMatchTolerance = (float)doc.Settings.TransitionSettings.Instrument.MzMatchTolerance; if (!nodeTranGroup.HasResults || resultsIndex < 0 || resultsIndex >= nodeTranGroup.Results.Count) { return; } var tranGroupChromInfo = nodeTranGroup.GetChromInfo(resultsIndex, resultsFile); if (tranGroupChromInfo == null) { return; } var chromSet = doc.Settings.MeasuredResults.Chromatograms[resultsIndex]; if (!doc.Settings.MeasuredResults.TryLoadChromatogram(chromSet, nodePep, nodeTranGroup, mzMatchTolerance, true, out var chromGroupInfos)) { return; } var chromGroupInfo = chromGroupInfos.FirstOrDefault(info => Equals(chromSet.GetFileInfo(tranGroupChromInfo.FileId).FilePath, info.FilePath)); if (chromGroupInfo == null || chromGroupInfo.NumPeaks == 0 || !chromGroupInfo.TimeIntensitiesGroup.HasAnyPoints) { return; } runTime = chromGroupInfo.RunStartTime; if (!tranGroupChromInfo.RetentionTime.HasValue || !tranGroupChromInfo.StartRetentionTime.HasValue || !tranGroupChromInfo.EndRetentionTime.HasValue) { return; } int peakIndex = -1; foreach (var transition in chromGroupInfo.TransitionPointSets) { peakIndex = transition.IndexOfPeak(tranGroupChromInfo.RetentionTime.Value); if (peakIndex != -1) { break; } } // Get time information float timeMin = chromGroupInfo.TimeIntensitiesGroup.MinTime; float timeMax = chromGroupInfo.TimeIntensitiesGroup.MaxTime; float totalArea = chromGroupInfo.TransitionPointSets.Sum(chromInfo => chromInfo.Peaks.Sum(peak => peak.Area)); for (int i = 0; i < chromGroupInfo.NumPeaks; i++) { referenceMatchDataList.Add(new PeakMatchData(nodeTranGroup, chromGroupInfo, mzMatchTolerance, i, totalArea, chromSet.OptimizationFunction)); } // Get ion abundance information var abundances = new IonAbundances(); foreach (var nodeTran in nodeTranGroup.Transitions) { var chromInfoCached = chromGroupInfo.GetTransitionInfo(nodeTran, mzMatchTolerance, chromSet.OptimizationFunction); if (chromInfoCached == null) { continue; } var tranChromInfo = nodeTran.Results[resultsIndex].First(r => r.FileIndex == tranGroupChromInfo.FileIndex); float area; if (peakIndex != -1) { // A peak exists here var cachedPeak = chromInfoCached.GetPeak(peakIndex); area = cachedPeak.Area; if (cachedPeak.RetentionTime.Equals(tranGroupChromInfo.RetentionTime.Value)) { var range = cachedPeak.EndTime - cachedPeak.StartTime; referenceMatchDataList[peakIndex].ShiftLeft = (tranChromInfo.StartRetentionTime - cachedPeak.StartTime) / range; referenceMatchDataList[peakIndex].ShiftRight = (tranChromInfo.EndRetentionTime - cachedPeak.EndTime) / range; } } else { area = tranChromInfo.Area; } abundances.Add(nodeTran, area); } referenceTarget = peakIndex != -1 ? referenceMatchDataList[peakIndex] : new PeakMatchData(abundances, abundances.Sum() / totalArea, tranGroupChromInfo.RetentionTime.Value, tranGroupChromInfo.StartRetentionTime.Value, tranGroupChromInfo.EndRetentionTime.Value, timeMin, timeMax); referenceMatchData = referenceMatchDataList.ToArray(); }
public double GetMatchScore(PeakMatchData other) { var timeMin = Math.Min(MinTime, other.MinTime); var timeMax = Math.Max(MaxTime, other.MaxTime); return SCORE_DOT_WEIGHT * Abundances.Dot(other.Abundances) + SCORE_RT_WEIGHT * (1 - Math.Abs((RetentionTime - timeMin) - (other.RetentionTime - timeMin)) / (timeMax - timeMin)) + SCORE_AREA_WEIGHT * (1 - Math.Abs(PercentArea - other.PercentArea)); }
private static PeakMatch GetPeakMatch(SrmDocument doc, ChromatogramSet chromSet, IPathContainer fileInfo, TransitionGroupDocNode nodeTranGroup, PeakMatchData referenceTarget, IEnumerable <PeakMatchData> referenceMatchData) { if (referenceTarget == null) { return(new PeakMatch(0, 0)); } var mzMatchTolerance = (float)doc.Settings.TransitionSettings.Instrument.MzMatchTolerance; ChromatogramGroupInfo[] loadInfos; if (!nodeTranGroup.HasResults || !doc.Settings.MeasuredResults.TryLoadChromatogram(chromSet, null, nodeTranGroup, mzMatchTolerance, true, out loadInfos)) { return(null); } var chromGroupInfo = loadInfos.FirstOrDefault(info => Equals(info.FilePath, fileInfo.FilePath)); if (chromGroupInfo == null || chromGroupInfo.NumPeaks == 0 || !chromGroupInfo.TimeIntensitiesGroup.HasAnyPoints) { return(null); } var matchData = new List <PeakMatchData>(); double totalArea = chromGroupInfo.TransitionPointSets.Sum(chromInfo => chromInfo.Peaks.Sum(peak => peak.Area)); for (int i = 0; i < chromGroupInfo.NumPeaks; i++) { matchData.Add(new PeakMatchData(nodeTranGroup, chromGroupInfo, mzMatchTolerance, i, totalArea, chromSet.OptimizationFunction)); } // TODO: Try to improve this. Align peaks in area descending order until peaks do not match var alignments = new List <PeakAlignment>(); bool referenceAligned = false; using (var referenceIter = referenceMatchData.OrderByDescending(d => d.PercentArea).GetEnumerator()) using (var curIter = matchData.OrderByDescending(d => d.PercentArea).GetEnumerator()) { while (referenceIter.MoveNext() && curIter.MoveNext()) { var alignAttempt = new PeakAlignment(referenceIter.Current, curIter.Current); if (!TryInsertPeakAlignment(alignments, alignAttempt)) { break; } if (referenceTarget == alignAttempt.ReferencePeak) { // Reference target aligned referenceAligned = true; matchData = new List <PeakMatchData> { alignAttempt.AlignedPeak }; break; } } } PeakMatch manualMatch = null; if (!referenceAligned) { PeakAlignment prev, next; GetSurroundingAlignments(alignments, referenceTarget, out prev, out next); if (prev != null || next != null) { // At least one alignment occurred var chromGroupMinTime = chromGroupInfo.TimeIntensitiesGroup.MinTime; var chromGroupMaxTime = chromGroupInfo.TimeIntensitiesGroup.MaxTime; float scale = (chromGroupMaxTime - chromGroupMinTime) / (referenceTarget.MaxTime - referenceTarget.MinTime); manualMatch = MakePeakMatchBetween(scale, referenceTarget, prev, next); if (chromGroupMinTime >= manualMatch.EndTime || manualMatch.StartTime >= chromGroupMaxTime) { manualMatch = null; } float curMinTime = prev == null ? chromGroupMinTime : prev.AlignedPeak.RetentionTime; float curMaxTime = next == null ? chromGroupMaxTime : next.AlignedPeak.RetentionTime; matchData = matchData.Where(d => curMinTime < d.RetentionTime && d.RetentionTime < curMaxTime).ToList(); } } PeakMatchData bestMatch = null; double bestScore = double.MinValue; foreach (var other in matchData) { var score = referenceTarget.GetMatchScore(other); if (bestMatch == null || score > bestScore) { bestScore = score; bestMatch = other; } } // If no matching peak with high enough score was found, but there is a matching // peak or some peak with a low score. if (bestMatch == null || (!referenceAligned && bestScore < INTEGRATE_SCORE_THRESHOLD && manualMatch != null)) { return(manualMatch); } if (referenceTarget.ShiftLeft == 0 && referenceTarget.ShiftRight == 0) { return(new PeakMatch(bestMatch.RetentionTime)); } var range = bestMatch.EndTime - bestMatch.StartTime; var startTime = bestMatch.StartTime + (referenceTarget.ShiftLeft * range); var endTime = bestMatch.EndTime + (referenceTarget.ShiftRight * range); return(startTime <= bestMatch.RetentionTime && bestMatch.RetentionTime <= endTime ? new PeakMatch(startTime, endTime) : new PeakMatch(bestMatch.RetentionTime)); // If the shifted boundaries exclude the peak itself, don't change the boundaries }
private static PeakMatch MakePeakMatchBetween(float scale, PeakMatchData referenceTarget, PeakAlignment prev, PeakAlignment next) { if (prev == null && next == null) return null; float startTime, endTime; var range = scale * (referenceTarget.EndTime - referenceTarget.StartTime); if (prev != null && next != null) { startTime = prev.AlignedPeak.RetentionTime + scale*(referenceTarget.StartTime - prev.ReferencePeak.RetentionTime); endTime = next.AlignedPeak.RetentionTime - scale*(next.ReferencePeak.RetentionTime - referenceTarget.EndTime); } else if (next != null) { endTime = next.AlignedPeak.StartTime - scale*(next.ReferencePeak.StartTime - referenceTarget.EndTime); startTime = endTime - range; } else { startTime = prev.AlignedPeak.EndTime + scale*(referenceTarget.StartTime - prev.ReferencePeak.EndTime); endTime = startTime + range; } return new PeakMatch(startTime + (referenceTarget.ShiftLeft*range), endTime + (referenceTarget.ShiftRight*range)); }
private static int GetSurroundingAlignments(IList<PeakAlignment> alignList, PeakMatchData target, out PeakAlignment prev, out PeakAlignment next) { prev = next = null; if (!alignList.Any()) return 0; var insertPos = alignList.Select(align => align.ReferencePeak).ToList().BinarySearch(target, RT_COMPARER); if (insertPos < 0) insertPos = ~insertPos; if (insertPos == 0) { next = alignList.First(); } else if (insertPos != alignList.Count) { prev = alignList[insertPos - 1]; next = alignList[insertPos]; } else { prev = alignList.Last(); } return insertPos; }
private static void GetReferenceData(SrmDocument doc, PeptideDocNode nodePep, TransitionGroupDocNode nodeTranGroup, int resultsIndex, int? resultsFile, out PeakMatchData referenceTarget, out PeakMatchData[] referenceMatchData, out DateTime? runTime) { referenceTarget = null; referenceMatchData = new PeakMatchData[0]; runTime = null; var referenceMatchDataList = new List<PeakMatchData>(); var mzMatchTolerance = (float) doc.Settings.TransitionSettings.Instrument.MzMatchTolerance; if (!nodeTranGroup.HasResults || resultsIndex < 0 || resultsIndex >= nodeTranGroup.Results.Count) return; var tranGroupChromInfo = nodeTranGroup.Results[resultsIndex][resultsFile ?? 0]; if (tranGroupChromInfo == null) return; var chromSet = doc.Settings.MeasuredResults.Chromatograms[resultsIndex]; ChromatogramGroupInfo[] chromGroupInfos; if (!doc.Settings.MeasuredResults.TryLoadChromatogram(chromSet, nodePep, nodeTranGroup, mzMatchTolerance, true, out chromGroupInfos)) return; var chromGroupInfo = chromGroupInfos.FirstOrDefault(info => Equals(chromSet.GetFileInfo(tranGroupChromInfo.FileId).FilePath, info.FilePath)); if (chromGroupInfo == null || chromGroupInfo.NumPeaks == 0 || !chromGroupInfo.Times.Any()) return; runTime = chromGroupInfo.RunStartTime; if (!tranGroupChromInfo.RetentionTime.HasValue || !tranGroupChromInfo.StartRetentionTime.HasValue || !tranGroupChromInfo.EndRetentionTime.HasValue) return; int peakIndex = -1; foreach (var transition in chromGroupInfo.TransitionPointSets) { peakIndex = transition.IndexOfPeak(tranGroupChromInfo.RetentionTime.Value); if (peakIndex != -1) break; } // Get time information float timeMin = chromGroupInfo.Times.First(); float timeMax = chromGroupInfo.Times.Last(); float totalArea = chromGroupInfo.TransitionPointSets.Sum(chromInfo => chromInfo.Peaks.Sum(peak => peak.Area)); for (int i = 0; i < chromGroupInfo.NumPeaks; i++) referenceMatchDataList.Add(new PeakMatchData(nodeTranGroup, chromGroupInfo, mzMatchTolerance, i, totalArea)); // Get ion abundance information var abundances = new IonAbundances(); foreach (var nodeTran in nodeTranGroup.Transitions) { var chromInfoCached = chromGroupInfo.GetTransitionInfo((float) nodeTran.Mz, mzMatchTolerance); if (chromInfoCached == null) continue; var tranChromInfo = nodeTran.Results[resultsIndex].First(r => r.FileIndex == tranGroupChromInfo.FileIndex); float area; if (peakIndex != -1) { // A peak exists here var cachedPeak = chromInfoCached.GetPeak(peakIndex); area = cachedPeak.Area; if (cachedPeak.RetentionTime.Equals(tranGroupChromInfo.RetentionTime.Value)) { var range = cachedPeak.EndTime - cachedPeak.StartTime; referenceMatchDataList[peakIndex].ShiftLeft = (tranChromInfo.StartRetentionTime - cachedPeak.StartTime)/range; referenceMatchDataList[peakIndex].ShiftRight = (tranChromInfo.EndRetentionTime - cachedPeak.EndTime)/range; } } else { area = tranChromInfo.Area; } abundances.Add(nodeTran, area); } referenceTarget = peakIndex != -1 ? referenceMatchDataList[peakIndex] : new PeakMatchData(abundances, abundances.Sum()/totalArea, tranGroupChromInfo.RetentionTime.Value, tranGroupChromInfo.StartRetentionTime.Value, tranGroupChromInfo.EndRetentionTime.Value, timeMin, timeMax); referenceMatchData = referenceMatchDataList.ToArray(); }
private static PeakMatch GetPeakMatch(SrmDocument doc, ChromatogramSet chromSet, IPathContainer fileInfo, TransitionGroupDocNode nodeTranGroup, PeakMatchData referenceTarget, IEnumerable<PeakMatchData> referenceMatchData) { if (referenceTarget == null) return new PeakMatch(0, 0); var mzMatchTolerance = (float) doc.Settings.TransitionSettings.Instrument.MzMatchTolerance; ChromatogramGroupInfo[] loadInfos; if (!nodeTranGroup.HasResults || !doc.Settings.MeasuredResults.TryLoadChromatogram(chromSet, null, nodeTranGroup, mzMatchTolerance, true, out loadInfos)) return null; var chromGroupInfo = loadInfos.FirstOrDefault(info => Equals(info.FilePath, fileInfo.FilePath)); if (chromGroupInfo == null || chromGroupInfo.NumPeaks == 0 || !chromGroupInfo.Times.Any()) return null; var matchData = new List<PeakMatchData>(); double totalArea = chromGroupInfo.TransitionPointSets.Sum(chromInfo => chromInfo.Peaks.Sum(peak => peak.Area)); for (int i = 0; i < chromGroupInfo.NumPeaks; i++) matchData.Add(new PeakMatchData(nodeTranGroup, chromGroupInfo, mzMatchTolerance, i, totalArea)); // TODO: Try to improve this. Align peaks in area descending order until peaks do not match var alignments = new List<PeakAlignment>(); bool referenceAligned = false; var referenceIter = referenceMatchData.OrderByDescending(d => d.PercentArea).GetEnumerator(); var curIter = matchData.OrderByDescending(d => d.PercentArea).GetEnumerator(); while (referenceIter.MoveNext() && curIter.MoveNext()) { var alignAttempt = new PeakAlignment(referenceIter.Current, curIter.Current); if (!TryInsertPeakAlignment(alignments, alignAttempt)) break; if (referenceTarget == alignAttempt.ReferencePeak) { // Reference target aligned referenceAligned = true; matchData = new List<PeakMatchData> {alignAttempt.AlignedPeak}; break; } } PeakMatch manualMatch = null; if (!referenceAligned) { PeakAlignment prev, next; GetSurroundingAlignments(alignments, referenceTarget, out prev, out next); if (prev != null || next != null) { // At least one alignment occurred var chromGroupMinTime = chromGroupInfo.Times.First(); var chromGroupMaxTime = chromGroupInfo.Times.Last(); float scale = (chromGroupMaxTime - chromGroupMinTime)/(referenceTarget.MaxTime - referenceTarget.MinTime); manualMatch = MakePeakMatchBetween(scale, referenceTarget, prev, next); if (chromGroupMinTime >= manualMatch.EndTime || manualMatch.StartTime >= chromGroupMaxTime) manualMatch = null; float curMinTime = prev == null ? chromGroupMinTime : prev.AlignedPeak.RetentionTime; float curMaxTime = next == null ? chromGroupMaxTime : next.AlignedPeak.RetentionTime; matchData = matchData.Where(d => curMinTime < d.RetentionTime && d.RetentionTime < curMaxTime).ToList(); } } PeakMatchData bestMatch = null; double bestScore = double.MinValue; foreach (var other in matchData) { var score = referenceTarget.GetMatchScore(other); if (bestMatch == null || score > bestScore) { bestScore = score; bestMatch = other; } } // If no matching peak with high enough score was found, but there is a matching // peak or some peak with a low score. if (bestMatch == null || (!referenceAligned && bestScore < INTEGRATE_SCORE_THRESHOLD && manualMatch != null)) return manualMatch; if (referenceTarget.ShiftLeft == 0 && referenceTarget.ShiftRight == 0) return new PeakMatch(bestMatch.RetentionTime); var range = bestMatch.EndTime - bestMatch.StartTime; var startTime = bestMatch.StartTime + (referenceTarget.ShiftLeft*range); var endTime = bestMatch.EndTime + (referenceTarget.ShiftRight*range); return startTime <= bestMatch.RetentionTime && bestMatch.RetentionTime <= endTime ? new PeakMatch(startTime, endTime) : new PeakMatch(bestMatch.RetentionTime); // If the shifted boundaries exclude the peak itself, don't change the boundaries }