Skip to content

Commit

Permalink
Fix for a "polarity mismatch" exception when searching for nearest pr…
Browse files Browse the repository at this point in the history
…ecursor 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
  • Loading branch information
bspratt authored Mar 4, 2025
1 parent b2c4523 commit bc6a7c4
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 15 deletions.
52 changes: 37 additions & 15 deletions pwiz_tools/Skyline/Model/Results/PeptideFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
*/
using System;
using System.Collections.Generic;
using System.Collections;
using pwiz.Common.Chemistry;

namespace pwiz.Skyline.Model.Results
Expand Down Expand Up @@ -61,22 +60,40 @@ public PeptideDocNode FindPeptide(SignedMz precursorMz)
// Find closest precursor Mz match.
var lookup = new PeptidePrecursorMz(null, precursorMz);
int i = _precursorMzPeptideList.BinarySearch(lookup, PeptidePrecursorMz.COMPARER);
if (i < 0)
if (i >= 0)
{
i = ~i;
if (i >= _precursorMzPeptideList.Count)
i = _precursorMzPeptideList.Count - 1;
else if (i > 0 &&
precursorMz - _precursorMzPeptideList[i - 1].PrecursorMz <
_precursorMzPeptideList[i].PrecursorMz - precursorMz)
i--;
return _precursorMzPeptideList[i].NodePeptide; // Exact match
}
var closestMatch = _precursorMzPeptideList[i];

// Return color seed only if the match is within allowed tolerance.
return Math.Abs(closestMatch.PrecursorMz - precursorMz) > _mzMatchTolerance
? null
: closestMatch.NodePeptide;
// BinarySearch returns bitwise complement of the index of the next larger element,
// but the closest match might be the element we just passed. Also, if precursor Mz is negative,
// we have to make sure search hasn't crossed over into positive territory. (SignedMz sorts
// negative values before positive ones e.g. -100, -200, 100, 200)
i = ~i;
PeptidePrecursorMz closestMatch = null;
var closestDistance = double.MaxValue;
for (var candidateIndex = i - 1; candidateIndex <= i; candidateIndex++)
{
if (candidateIndex < 0 || candidateIndex >= _precursorMzPeptideList.Count)
{
continue;
}
var candidate = _precursorMzPeptideList[candidateIndex];
if (candidate.PrecursorMz.IsNegative != precursorMz.IsNegative)
{
continue;
}

var distance = Math.Abs(candidate.PrecursorMz - precursorMz);
if (distance < closestDistance)
{
closestMatch = candidate;
closestDistance = distance;
}
}

// Return only if the match is within allowed tolerance.
return closestDistance > _mzMatchTolerance ? null : closestMatch?.NodePeptide;
}

private sealed class PeptidePrecursorMz
Expand All @@ -97,10 +114,15 @@ public class MzComparer : IComparer<PeptidePrecursorMz>
public int Compare(PeptidePrecursorMz p1, PeptidePrecursorMz p2)
{
// ReSharper disable PossibleNullReferenceException
return Comparer.Default.Compare(p1.PrecursorMz, p2.PrecursorMz);
return p1.PrecursorMz.CompareTo(p2.PrecursorMz);
// ReSharper restore PossibleNullReferenceException
}
}

public override string ToString()
{
return $@"{PrecursorMz.RawValue} {NodePeptide}"; // For debug convenience, not user-facing
}
}
}
}
12 changes: 12 additions & 0 deletions pwiz_tools/Skyline/TestFunctional/ExportIsolationListTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using pwiz.Common.Chemistry;
using pwiz.Skyline.Alerts;
using pwiz.Skyline.FileUI;
using pwiz.Skyline.Model;
using pwiz.Skyline.Model.DocSettings;
using pwiz.Skyline.Model.DocSettings.Extensions;
using pwiz.Skyline.Model.Results;
using pwiz.Skyline.Properties;
using pwiz.Skyline.Util.Extensions;
using pwiz.SkylineTestUtil;
Expand Down Expand Up @@ -151,6 +153,16 @@ protected override void DoTest()
var ceFirst = AsSmallMoleculesNegative ? 20.3 : 20.4;
var ceLast = AsSmallMoleculesNegative ? 19.1 : 19.2;

// Test an issue found in the PeptideFinder class with mixed polarity docs
if (SkylineWindow.Document.IsMixedPolarity())
{
var beyondMaxNegMz = (from precursor in SkylineWindow.Document.MoleculeTransitionGroups
where precursor.PrecursorMz.IsNegative
select precursor.PrecursorMz.RawValue).Min()-100.0;
var finder = new PeptideFinder(SkylineWindow.Document);
AssertEx.IsNull(finder.FindPeptide(new SignedMz(beyondMaxNegMz))); // This will throw a "polarity mismatch" exception if the issue is not fixed
}

// Export Agilent unscheduled DDA list.
ExportIsolationList(
"AgilentUnscheduledDda.csv",
Expand Down

0 comments on commit bc6a7c4

Please sign in to comment.