libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
pappso::HighResPeakPicker Class Reference

#include <highrespeakpicker.h>

Classes

struct  Parameters
struct  PeakRange

Public Member Functions

 HighResPeakPicker (Parameters &parameters)
virtual ~HighResPeakPicker ()
void pick (const Trace &trace, Trace &picked_peaks, QList< PeakRange > &peak_ranges)

Protected Attributes

Parameters m_parameters

Detailed Description

Definition at line 24 of file highrespeakpicker.h.

Constructor & Destructor Documentation

◆ HighResPeakPicker()

pappso::HighResPeakPicker::HighResPeakPicker ( Parameters & parameters)

Definition at line 24 of file highrespeakpicker.cpp.

24 : m_parameters(parameters)
25{
26}

References m_parameters.

◆ ~HighResPeakPicker()

pappso::HighResPeakPicker::~HighResPeakPicker ( )
virtual

Definition at line 28 of file highrespeakpicker.cpp.

29{
30}

Member Function Documentation

◆ pick()

void pappso::HighResPeakPicker::pick ( const Trace & trace,
Trace & picked_peaks,
QList< PeakRange > & peak_ranges )

Definition at line 33 of file highrespeakpicker.cpp.

34{
35 picked_peaks.clear();
36
37 qsizetype trace_size = trace.size();
38
39 if(trace_size < 5)
40 return;
41
42 // signal-to-noise estimation
43 LocalSignalToNoiseEstimator::Parameters signal_to_noise_estimator_parameters;
44 LocalSignalToNoiseEstimator local_signal_estimator(signal_to_noise_estimator_parameters);
45
46 if(m_parameters.signalToNoise > 0.0)
47 {
48 // Computes, for each DataPoint in the trace, an estimage of local
49 // signal-to-ratio value that is consulted below.
50 local_signal_estimator.initialize(trace);
51 }
52
53 // Iterate in the trace and search for local maxima, that is, roughly,
54 // DataPoint instances that are higher than previous and next point.
55 for(qsizetype iter = 2; iter < trace_size - 2; ++iter)
56 {
57 // Skip any data point that is of an intensity below min_intensity
58 if(trace.at(iter).y < m_parameters.minimumIntensity)
59 {
60 qDebug() << "Now skipping low intensity peak at m/z:" << trace.at(iter).x
61 << "with intensity:" << trace.at(iter).y;
62 continue;
63 }
64 double center_data_point_mz = trace.at(iter).x;
65 double center_data_point_int = trace.at(iter).y;
66 double left_data_point_mz = trace.at(iter - 1).x;
67 double left_data_point_int = trace.at(iter - 1).y;
68 double right_data_point_mz = trace.at(iter + 1).x;
69 double right_data_point_int = trace.at(iter + 1).y;
70
71 // Do not interpolate when the left or right DataPoint is zero-intensity.
72 if(std::fabs(left_data_point_int) <
73 std::numeric_limits<double>::epsilon())
74 {
75 continue;
76 }
77 if(std::fabs(right_data_point_int) <
78 std::numeric_limits<double>::epsilon())
79 {
80 continue;
81 }
82
83 double current_snt_estimate = 0.0;
84 double current_snt_estimate_left_1 = 0.0;
85 double current_snt_estimate_right_1 = 0.0;
86
87 if(m_parameters.signalToNoise > 0.0)
88 {
89 current_snt_estimate =
90 local_signal_estimator.getSignalToNoiseRatio(iter);
91
92 // qDebug() << "For current center point at iter:" << iter
93 // << "with mz:" << center_data_point_mz << "of intensity"
94 // << center_data_point_int
95 // << "the snt estimate is:" << current_snt_estimate;
96
97 current_snt_estimate_left_1 =
98 local_signal_estimator.getSignalToNoiseRatio(iter - 1);
99 current_snt_estimate_right_1 =
100 local_signal_estimator.getSignalToNoiseRatio(iter + 1);
101 }
102
103 // Look for "peaking" data points meeting MZ and intensity/SNT criteria
104 // The currently iterated data point should at least have its
105 // intensity greater than both the left and right data points intensities.
106 // If the signal-to-noise checks are OK, than the data point becomes a peak "core",
107 // that is the top point of the peak shape.
108 if((center_data_point_int > left_data_point_int) &&
109 (center_data_point_int > right_data_point_int) &&
110 (current_snt_estimate >= m_parameters.signalToNoise) &&
111 (current_snt_estimate_left_1 >= m_parameters.signalToNoise) &&
112 (current_snt_estimate_right_1 >= m_parameters.signalToNoise))
113 {
114 // First check if the currently iterated center center point
115 // is surrounded by more intense peaks on its left-left or on its
116 // right-right, because that might indicate signal instability instead
117 // of an actual maximum. In this case, we do not consider the data
118 // point.
119
120 double current_snt_estimate_left_2 = 0.0;
121 double current_snt_estimate_right_2 = 0.0;
122
123 if(m_parameters.signalToNoise > 0.0)
124 {
125 current_snt_estimate_left_2 =
126 local_signal_estimator.getSignalToNoiseRatio(iter - 2);
127 current_snt_estimate_right_2 =
128 local_signal_estimator.getSignalToNoiseRatio(iter + 2);
129 }
130
131 // Checking signal-to-noise
132 if((iter > 1) && (iter + 2 < static_cast<qsizetype>(trace.size())) &&
133 (left_data_point_int < trace.at(iter - 2).y) &&
134 (right_data_point_int < trace.at(iter + 2).y) &&
135 (current_snt_estimate_left_2 >= m_parameters.signalToNoise) &&
136 (current_snt_estimate_right_2 >= m_parameters.signalToNoise))
137 {
138 // If the point left of the left data point (with respect to
139 // current center data point that was found to be a local maximum)
140 // and if the point right of the right data point (again, with
141 // respect to current center data point that was found to be a
142 // local maximum) and both of these left_left and right_right
143 // datapoints are above the signal to noise ratio, then we are
144 // experiencing signal instability.
145 ++iter;
146 continue;
147 }
148
149 QMap<double, double> peak_raw_data;
150
151 peak_raw_data[center_data_point_mz] = center_data_point_int;
152 peak_raw_data[left_data_point_mz] = left_data_point_int;
153 peak_raw_data[right_data_point_mz] = right_data_point_int;
154
155 // Peak core found, now extend it to the left
156 qsizetype k = 2;
157
158 // No need to extend peak if previous intensity was zero
159 bool previous_zero_left = false;
160 qsizetype missing_left_count = 0;
161 // Index of the left boundary for the spline interpolation
162 qsizetype left_boundary = iter - 1;
163
164 while((k <= iter) && // Prevent underflow
165 (iter - k + 1 > 0) && !previous_zero_left &&
166 (trace.at(iter - k).y <= peak_raw_data.begin().value()))
167 {
168 double current_snt_estimate_left_k = 0.0;
169
170 if(m_parameters.signalToNoise > 0.0)
171 {
172 current_snt_estimate_left_k =
173 local_signal_estimator.getSignalToNoiseRatio(iter - k);
174 }
175
176 if(current_snt_estimate_left_k >= m_parameters.signalToNoise)
177 {
178 peak_raw_data[trace.at(iter - k).x] = trace.at(iter - k).y;
179 }
180 {
181 ++missing_left_count;
182 if(missing_left_count <= m_parameters.missingPeakCount)
183 {
184 peak_raw_data[trace.at(iter - k).x] = trace.at(iter - k).y;
185 }
186 }
187
188 previous_zero_left = (trace.at(iter - k).y == 0);
189 left_boundary = iter - k;
190 ++k;
191 }
192
193 // Now do the same on the right
194 k = 2;
195
196 // No need to extend peak if previous intensity was zero
197 bool previous_zero_right = false;
198 qsizetype missing_right_count = 0;
199 // Index of the right boundary for the spline interpolation
200 qsizetype right_boundary(iter + 1);
201
202 while((iter + k < static_cast<qsizetype>(trace.size())) &&
203 !previous_zero_right &&
204 (trace.at(iter + k).y <= peak_raw_data.last()))
205 {
206 double current_snt_estimate_right_k = 0.0;
207
208 if(m_parameters.signalToNoise > 0.0)
209 {
210 current_snt_estimate_right_k =
211 local_signal_estimator.getSignalToNoiseRatio(iter + k);
212 }
213
214 if(current_snt_estimate_right_k >= m_parameters.signalToNoise)
215 {
216 peak_raw_data[trace.at(iter + k).x] = trace.at(iter + k).y;
217 }
218 else
219 {
220 ++missing_right_count;
221 if(missing_right_count <= m_parameters.missingPeakCount)
222 {
223 peak_raw_data[trace.at(iter + k).x] =
224 trace.at(iter + k).y;
225 }
226 }
227
228 previous_zero_right = (trace.at(iter + k).y == 0);
229 right_boundary = iter + k;
230 ++k;
231 }
232
233 // Skip peak altogether if the minimal number of 3 points for fitting is not reached
234 if(peak_raw_data.size() < 3)
235 {
236 continue;
237 }
238
239 // qDebug() << "peak_raw_data size:" << peak_raw_data.size();
240
241 CubicSplineModel cubic_spline_model(peak_raw_data);
242 // qDebug() << "Stack-allocated:" << &cubic_spline_model;
243
244
245 // qDebug() << "The cubic spline model has "
246 // << cubic_spline_model.getKnots().size() << "knots.";
247
248 // calculate maximum by evaluating the spline's 1st derivative
249 // (bisection method)
250 double max_peak_mz = center_data_point_mz;
251 double max_peak_int = center_data_point_int;
252 double threshold = 1e-6;
253 spline_bisection(cubic_spline_model,
254 left_data_point_mz,
255 right_data_point_mz,
256 max_peak_mz,
257 max_peak_int,
258 threshold);
259
260 // save picked peak into output spectrum
261 DataPoint data_point;
262
263 PeakRange peak_range;
264
265 data_point.x = max_peak_mz;
266 data_point.y = max_peak_int;
267 peak_range.mz_start = trace.at(left_boundary).x;
268 peak_range.mz_stop = trace.at(right_boundary).x;
269
270 // qDebug() << "Now appending new data point:" <<
271 // data_point.toString();
272
273 picked_peaks.append(data_point);
274
275 peak_ranges.push_back(peak_range);
276
277 // jump over profile data points that have been considered already
278 iter += k - 1;
279 }
280 }
281
282 // qDebug() << "Now returning" << picked_peaks.size()
283 // << "picked centroids:" << picked_peaks.toString();
284}
void spline_bisection(const CubicSplineModel &spline_model, double const mz_at_left, double const mz_at_right, double &center_peak_mz, double &center_peak_intensity, double const threshold)

References pappso::Trace::append(), pappso::LocalSignalToNoiseEstimator::getSignalToNoiseRatio(), pappso::LocalSignalToNoiseEstimator::initialize(), m_parameters, pappso::HighResPeakPicker::PeakRange::mz_start, pappso::HighResPeakPicker::PeakRange::mz_stop, pappso::spline_bisection(), pappso::DataPoint::x, pappso::DataPoint::y, and pappso::y.

Member Data Documentation

◆ m_parameters

Parameters pappso::HighResPeakPicker::m_parameters
protected

Definition at line 47 of file highrespeakpicker.h.

Referenced by HighResPeakPicker(), and pick().


The documentation for this class was generated from the following files: