private static bool TryInsertPeakAlignment(IList <PeakAlignment> alignList, PeakAlignment alignment) { var reference = alignment.ReferencePeak; var other = alignment.AlignedPeak; if (Math.Min(reference.PercentArea, other.PercentArea) < ALIGN_AREA_MIN || reference.Abundances.Dot(other.Abundances) < ALIGN_DOT_MIN) { return(false); } PeakAlignment prev, next; var insertPos = GetSurroundingAlignments(alignList, reference, out prev, out next); if ((prev != null && other.RetentionTime < prev.AlignedPeak.RetentionTime) || (next != null && other.RetentionTime > next.AlignedPeak.RetentionTime)) { return(false); } alignList.Insert(insertPos, alignment); return(true); }
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))); }
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 bool TryInsertPeakAlignment(IList<PeakAlignment> alignList, PeakAlignment alignment) { var reference = alignment.ReferencePeak; var other = alignment.AlignedPeak; if (Math.Min(reference.PercentArea, other.PercentArea) < ALIGN_AREA_MIN || reference.Abundances.Dot(other.Abundances) < ALIGN_DOT_MIN) return false; PeakAlignment prev, next; var insertPos = GetSurroundingAlignments(alignList, reference, out prev, out next); if ((prev != null && other.RetentionTime < prev.AlignedPeak.RetentionTime) || (next != null && other.RetentionTime > next.AlignedPeak.RetentionTime)) { return false; } alignList.Insert(insertPos, alignment); return true; }
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 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 }