Skip to content

Commit bc6a7c4

Browse files
authored
Fix for a "polarity mismatch" exception when searching for nearest precursor m/z match in a mixed polarity document... (#3383)
* Fix for a "polarity mismatch" exception when searching for nearest precursor m/z match in a mixed polarity document when the m/z is negative and has greater absolute value than any negative precursor m/z. Reported by user Paul
1 parent b2c4523 commit bc6a7c4

File tree

2 files changed

+49
-15
lines changed

2 files changed

+49
-15
lines changed

pwiz_tools/Skyline/Model/Results/PeptideFinder.cs

+37-15
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
*/
1919
using System;
2020
using System.Collections.Generic;
21-
using System.Collections;
2221
using pwiz.Common.Chemistry;
2322

2423
namespace pwiz.Skyline.Model.Results
@@ -61,22 +60,40 @@ public PeptideDocNode FindPeptide(SignedMz precursorMz)
6160
// Find closest precursor Mz match.
6261
var lookup = new PeptidePrecursorMz(null, precursorMz);
6362
int i = _precursorMzPeptideList.BinarySearch(lookup, PeptidePrecursorMz.COMPARER);
64-
if (i < 0)
63+
if (i >= 0)
6564
{
66-
i = ~i;
67-
if (i >= _precursorMzPeptideList.Count)
68-
i = _precursorMzPeptideList.Count - 1;
69-
else if (i > 0 &&
70-
precursorMz - _precursorMzPeptideList[i - 1].PrecursorMz <
71-
_precursorMzPeptideList[i].PrecursorMz - precursorMz)
72-
i--;
65+
return _precursorMzPeptideList[i].NodePeptide; // Exact match
7366
}
74-
var closestMatch = _precursorMzPeptideList[i];
7567

76-
// Return color seed only if the match is within allowed tolerance.
77-
return Math.Abs(closestMatch.PrecursorMz - precursorMz) > _mzMatchTolerance
78-
? null
79-
: closestMatch.NodePeptide;
68+
// BinarySearch returns bitwise complement of the index of the next larger element,
69+
// but the closest match might be the element we just passed. Also, if precursor Mz is negative,
70+
// we have to make sure search hasn't crossed over into positive territory. (SignedMz sorts
71+
// negative values before positive ones e.g. -100, -200, 100, 200)
72+
i = ~i;
73+
PeptidePrecursorMz closestMatch = null;
74+
var closestDistance = double.MaxValue;
75+
for (var candidateIndex = i - 1; candidateIndex <= i; candidateIndex++)
76+
{
77+
if (candidateIndex < 0 || candidateIndex >= _precursorMzPeptideList.Count)
78+
{
79+
continue;
80+
}
81+
var candidate = _precursorMzPeptideList[candidateIndex];
82+
if (candidate.PrecursorMz.IsNegative != precursorMz.IsNegative)
83+
{
84+
continue;
85+
}
86+
87+
var distance = Math.Abs(candidate.PrecursorMz - precursorMz);
88+
if (distance < closestDistance)
89+
{
90+
closestMatch = candidate;
91+
closestDistance = distance;
92+
}
93+
}
94+
95+
// Return only if the match is within allowed tolerance.
96+
return closestDistance > _mzMatchTolerance ? null : closestMatch?.NodePeptide;
8097
}
8198

8299
private sealed class PeptidePrecursorMz
@@ -97,10 +114,15 @@ public class MzComparer : IComparer<PeptidePrecursorMz>
97114
public int Compare(PeptidePrecursorMz p1, PeptidePrecursorMz p2)
98115
{
99116
// ReSharper disable PossibleNullReferenceException
100-
return Comparer.Default.Compare(p1.PrecursorMz, p2.PrecursorMz);
117+
return p1.PrecursorMz.CompareTo(p2.PrecursorMz);
101118
// ReSharper restore PossibleNullReferenceException
102119
}
103120
}
121+
122+
public override string ToString()
123+
{
124+
return $@"{PrecursorMz.RawValue} {NodePeptide}"; // For debug convenience, not user-facing
125+
}
104126
}
105127
}
106128
}

pwiz_tools/Skyline/TestFunctional/ExportIsolationListTest.cs

+12
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
using System.Linq;
2424
using System.Text;
2525
using Microsoft.VisualStudio.TestTools.UnitTesting;
26+
using pwiz.Common.Chemistry;
2627
using pwiz.Skyline.Alerts;
2728
using pwiz.Skyline.FileUI;
2829
using pwiz.Skyline.Model;
2930
using pwiz.Skyline.Model.DocSettings;
3031
using pwiz.Skyline.Model.DocSettings.Extensions;
32+
using pwiz.Skyline.Model.Results;
3133
using pwiz.Skyline.Properties;
3234
using pwiz.Skyline.Util.Extensions;
3335
using pwiz.SkylineTestUtil;
@@ -151,6 +153,16 @@ protected override void DoTest()
151153
var ceFirst = AsSmallMoleculesNegative ? 20.3 : 20.4;
152154
var ceLast = AsSmallMoleculesNegative ? 19.1 : 19.2;
153155

156+
// Test an issue found in the PeptideFinder class with mixed polarity docs
157+
if (SkylineWindow.Document.IsMixedPolarity())
158+
{
159+
var beyondMaxNegMz = (from precursor in SkylineWindow.Document.MoleculeTransitionGroups
160+
where precursor.PrecursorMz.IsNegative
161+
select precursor.PrecursorMz.RawValue).Min()-100.0;
162+
var finder = new PeptideFinder(SkylineWindow.Document);
163+
AssertEx.IsNull(finder.FindPeptide(new SignedMz(beyondMaxNegMz))); // This will throw a "polarity mismatch" exception if the issue is not fixed
164+
}
165+
154166
// Export Agilent unscheduled DDA list.
155167
ExportIsolationList(
156168
"AgilentUnscheduledDda.csv",

0 commit comments

Comments
 (0)