18
18
*/
19
19
using System ;
20
20
using System . Collections . Generic ;
21
- using System . Collections ;
22
21
using pwiz . Common . Chemistry ;
23
22
24
23
namespace pwiz . Skyline . Model . Results
@@ -61,22 +60,40 @@ public PeptideDocNode FindPeptide(SignedMz precursorMz)
61
60
// Find closest precursor Mz match.
62
61
var lookup = new PeptidePrecursorMz ( null , precursorMz ) ;
63
62
int i = _precursorMzPeptideList . BinarySearch ( lookup , PeptidePrecursorMz . COMPARER ) ;
64
- if ( i < 0 )
63
+ if ( i >= 0 )
65
64
{
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
73
66
}
74
- var closestMatch = _precursorMzPeptideList [ i ] ;
75
67
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 ;
80
97
}
81
98
82
99
private sealed class PeptidePrecursorMz
@@ -97,10 +114,15 @@ public class MzComparer : IComparer<PeptidePrecursorMz>
97
114
public int Compare ( PeptidePrecursorMz p1 , PeptidePrecursorMz p2 )
98
115
{
99
116
// ReSharper disable PossibleNullReferenceException
100
- return Comparer . Default . Compare ( p1 . PrecursorMz , p2 . PrecursorMz ) ;
117
+ return p1 . PrecursorMz . CompareTo ( p2 . PrecursorMz ) ;
101
118
// ReSharper restore PossibleNullReferenceException
102
119
}
103
120
}
121
+
122
+ public override string ToString ( )
123
+ {
124
+ return $@ "{ PrecursorMz . RawValue } { NodePeptide } "; // For debug convenience, not user-facing
125
+ }
104
126
}
105
127
}
106
128
}
0 commit comments