libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
massspectrumminuscombiner.cpp
Go to the documentation of this file.
1/////////////////////// StdLib includes
2#include <vector>
3#include <map>
4#include <cmath>
5
6
7/////////////////////// Qt includes
8#include <QDebug>
9#include <QFile>
10#include <QThread>
11#if 0
12// For debugging purposes.
13#include <QFile>
14#endif
15
16
17/////////////////////// Local includes
21
22namespace pappso
23{
24
25
26//! Construct an uninitialized instance.
31
33 QObject *parent_p)
34 : MassSpectrumCombiner(decimal_places, parent_p)
35{
36}
37
39 const MassSpectrumMinusCombiner &other, QObject *parent_p)
40 : MassSpectrumCombiner(other, parent_p)
41
42{
43}
44
51
52//! Destruct the instance.
56
59{
60 if(this == &other)
61 return *this;
62
64
65 m_bins.assign(other.m_bins.begin(), other.m_bins.end());
66
67 return *this;
68}
69
70// We get a trace as parameter that this combiner needs to combine into the
71// map_trace we also get as parameter. This combiner is for a mass spectrum, and
72// thus it needs to have been configured to hold a vector of m/z values that are
73// bins into which DataPoint_s from trace are combined into map_trace. It is the
74// bins that drive the traversal of trace. For each bin, check if there is
75// (or are, if bins are big) data points in the trace that fit in it.
76
77// One important consideration is that the bins are formed before the call to
78// this combine() function and thus the distance between one m/z value and the
79// next is already determined. This means that we do not need to bother with the
80// conversion of m/z values to new decimal_places-defined values.
81
82// Another idea is that, upon the very first combination of the first spectrum
83// of the the thousands of spectra that are going to potentially be combined
84// into map_trace object, that map_trace object is *empty*. This means that we
85// can set the bins in that map_trace object and then iterated directly in the
86// destination map_trace and do the intensity incrementation calculation right
87// into the .second member of the pair that is being iterated into in the
88// map_trace object.
91 const Trace &trace) const
92{
93 // qDebug();
94
95 // If there is no single point in the trace we need to combine into the
96 // map_trace, then there is nothing to do.
97 if(!trace.size())
98 {
99 // qDebug() << "Thread:" << QThread::currentThreadId()
100 //<< "Returning right away because trace is empty.";
101 return map_trace;
102 }
103
104 // The destination map trace will be filled-in with the result of the
105 // combination.
106
107 // Sanity check:
108 if(!m_bins.size())
109 throw(ExceptionNotPossible("The bin vector cannot be empty."));
110
111 // qDebug() << qSetRealNumberPrecision(6) << "There are " << m_bins.size() <<
112 // "bins running from"
113 // << m_bins.front() << "to" << m_bins.back();
114
115 // Since the map_trace argument is used all along the combination of
116 // potentially thousands of mass spectra, we need to be careful. But
117 // clearly, if that map_trace object is empty, then, one way to accelerate the
118 // whole process is to copy the bins in there and later assume that
119 // the bin is already in it. So that we need not test each time if we have
120 // inserted the new data point or if we simply need to increment its
121 // intensity.
122
123 if(!map_trace.size())
124 {
125 std::transform(m_bins.begin(),
126 m_bins.end(),
127 std::inserter(map_trace, map_trace.end()),
128 [](double key) {
129 return std::make_pair(key, 0.0);
130 });
131 }
132
133 // We will need to only use these iterator variables if we do not want to
134 // loose consistency.
135
136 using TraceIter = std::vector<DataPoint>::const_iterator;
137 TraceIter trace_iter_begin = trace.begin();
138 TraceIter trace_iter = trace_iter_begin;
139 TraceIter trace_iter_end = trace.end();
140
141 // qDebug() << qSetRealNumberPrecision(6) << "The trace to combine has " <<
142 // trace.size()
143 // << "data points, with first a m/z" << trace.front().x << "and last
144 // at m/z"
145 // << trace.back().x;
146
147 // We will iterate in the destination map_trace that has been filled with
148 // the bins initially computed for this combiner.
149 using BinIter = std::map<double, double>::iterator;
150 BinIter map_trace_bin_iter = map_trace.begin();
151 BinIter map_trace_bin_end_iter = map_trace.end();
152
153 // We do not want to iterate in too many map_trace items before arriving
154 // to the map_trace item that matches the m/z value of the first data
155 // point in trace.
156
157 // Get the first map_trace bin that would match the very first data point in
158 // the trace that we need to combine into the map_trace. We want the first
159 // map_trace element having key >= trace_iter->x.
160 BinIter map_trace_bin_iter_for_mz = map_trace.upper_bound(trace_iter->x);
161
162 // If it's not the beginning, the previous element is what we want
163 if(map_trace_bin_iter_for_mz != map_trace.begin())
164 {
165 map_trace_bin_iter =
166 --map_trace_bin_iter_for_mz; // This is the greatest map_trace key <
167 // trace_iter->x
168 // qDebug() << "Found map_trace key=" << map_trace_bin_iter_for_mz->first
169 // << ", value=" << map_trace_bin_iter_for_mz->second;
170 }
171 else
172 {
173 // qDebug() << "The first bin found to match the first data point in trace
174 // is:"
175 // << map_trace.begin()->first;
176 }
177
178 // qDebug()
179 // << "The first bin found to match the first m/z value in the trace to
180 // combine is at index:"
181 // << std::distance(map_trace.begin(), map_trace_bin_iter);
182
183 while(map_trace_bin_iter != map_trace_bin_end_iter)
184 {
185 // qDebug() << qSetRealNumberPrecision(6)
186 // << "Now iterating in new bin with mz:" <<
187 // map_trace_bin_iter->first
188 // << "at a distance of the first bin:" <<
189 // std::distance(m_bins.begin(), map_trace_bin_iter);
190
191 // Now perform a loop over the data points in the mass spectrum.
192
193 // qDebug() << "Start looping in the trace to check if its DataPoint.x "
194 //"value matches that of the current bin."
195 //<< "trace_iter:" << trace_iter->toString()
196 //<< "at data point distance from first point in trace:"
197
198 while(trace_iter != trace_iter_end)
199 {
200 // std::cout << std::setprecision(10)
201 //<< "trace data point being iterated into: " << trace_iter->x
202 //<< " - " << trace_iter->y << std::endl;
203
204 // If trace is not to the end and the y value is not 0, perform the
205 // rounding and check if the obtained x value is in the current bin,
206 // that is if it is less or equal to the current bin.
207
208 // qDebug() << "Thread:" << QThread::currentThreadId();
209 // qDebug() << "trace_iter:" << trace_iter->toString()
210 //<< "data point distance:"
211 //<< std::distance(trace_iter_begin, trace_iter);
212
213
214 if(trace_iter->x <= map_trace_bin_iter->first)
215 {
216 // qDebug() << qSetRealNumberPrecision(6) << "Matched because
217 // trace x" << trace_iter->x
218 // << "is <= current bin m/z" <<
219 // map_trace_bin_iter->first;
220
221 // qDebug() << "Incrementing the y value by " << trace_iter->y;
222
223 map_trace_bin_iter->second -= trace_iter->y;
224
225 // qDebug() << qSetRealNumberPrecision(6)
226 // << "After incrementation of the intensity: " <<
227 // map_trace_bin_iter->second;
228
229 // Because we matched, we can step-up with the
230 // trace iterator. The idea is that, if the bins are large, then,
231 // multiple data points from a given mass spec acquisition' trace
232 // may fall inside that bin.
233
234 // qDebug() << "Now increment the trace iterator.";
235
236 ++trace_iter;
237 }
238 else
239 {
240 // The trace data point's x did not match the current map_trace
241 // bin m/z value because the former was greater than the latter.
242
243 // Because the DataPoint instances in the trace are sorted in
244 // increasing x order, we know we won't have to add any data point
245 // to this bin. So we break this loop, which will increment the
246 // map_trace bin iterator.
247
248 break;
249 }
250 }
251 // End of
252 // while(trace_iter != trace_iter_end)
253
254 // Each time we get here, that means that we have consumed all
255 // the mass spectra data points that matched the current bin.
256 // So go to the next bin.
257
258 if(trace_iter == trace_iter_end)
259 {
260 // Well, in fact we truly need to exit the loops...
261 break;
262 }
263
264 // qDebug() << "Now increment the bin iterator.";
265 ++map_trace_bin_iter;
266 }
267 // End of
268 // while(bin_iter != bin_end_iter)
269
270 return map_trace;
271}
272
273MapTrace &
275 const MapTrace &map_trace_in) const
276{
277 // qDebug();
278
279 if(!map_trace_in.size())
280 {
281 // qDebug() << "Thread:" << QThread::currentThreadId()
282 //<< "Returning right away because map_trace_in is empty.";
283 return map_trace_out;
284 }
285
286 Trace trace(map_trace_in);
287
288 return combine(map_trace_out, trace);
289}
290
291void
293{
294 // qDebug() << "registerJsConstructor for MassSpectrumMinusCombiner to
295 // QJSEngine.";
296
297 if(engine == nullptr)
298 {
299 qFatal() << "Cannot register class: engine is null";
300 }
301
302 // Register the meta object as a constructor
303 QJSValue jsMetaObject =
304 engine->newQMetaObject(&MassSpectrumMinusCombiner::staticMetaObject);
305 engine->globalObject().setProperty("MassSpectrumMinusCombiner", jsMetaObject);
306}
307
308} // namespace pappso
int m_decimalPlaces
Number of decimals to use for the keys (x values).
MassSpectrumCombiner(QObject *parent_p=nullptr)
Construct an uninitialized instance.
std::vector< pappso_double > m_bins
static void registerJsConstructor(QJSEngine *engine)
virtual Q_INVOKABLE MapTrace & combine(MapTrace &map_trace, const Trace &trace) const override
Q_INVOKABLE MassSpectrumMinusCombiner(QObject *parent_p=nullptr)
Construct an uninitialized instance.
virtual ~MassSpectrumMinusCombiner()
Destruct the instance.
MassSpectrumMinusCombiner & operator=(const MassSpectrumMinusCombiner &other)
A simple container of DataPoint instances.
Definition trace.h:152
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition aa.cpp:39
std::shared_ptr< const MassSpectrumMinusCombiner > MassSpectrumMinusCombinerCstSPtr