pappsomspp
Library for mass spectrometry
timsframe.cpp
Go to the documentation of this file.
1 /**
2  * \file pappsomspp/vendors/tims/timsframe.cpp
3  * \date 23/08/2019
4  * \author Olivier Langella
5  * \brief handle a single Bruker's TimsTof frame
6  */
7 
8 /*******************************************************************************
9  * Copyright (c) 2019 Olivier Langella <Olivier.Langella@u-psud.fr>.
10  *
11  * This file is part of the PAPPSOms++ library.
12  *
13  * PAPPSOms++ is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * PAPPSOms++ is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with PAPPSOms++. If not, see <http://www.gnu.org/licenses/>.
25  *
26  ******************************************************************************/
27 
28 #include "timsframe.h"
29 #include "../../../pappsomspp/pappsoexception.h"
30 #include "../../../pappsomspp/exception/exceptionoutofrange.h"
31 #include <QDebug>
32 #include <QtEndian>
33 #include <memory>
34 #include <solvers.h>
36 
37 
38 namespace pappso
39 {
40 
41 TimsFrame::TimsFrame(std::size_t timsId,
42  quint32 scanNum,
43  char *p_bytes,
44  std::size_t len)
45  : TimsFrameBase(timsId, scanNum)
46 {
47  // langella@themis:~/developpement/git/bruker/cbuild$
48  // ./src/sample/timsdataSamplePappso
49  // /gorgone/pappso/fichiers_fabricants/Bruker/Demo_TimsTOF_juin2019/Samples/1922001/1922001-1_S-415_Pep_Pur-1ul_Slot1-10_1_2088.d/
50  qDebug() << timsId;
51 
52  m_timsDataFrame.resize(len);
53 
54  if(p_bytes != nullptr)
55  {
56  unshufflePacket(p_bytes);
57  }
58  else
59  {
60  if(m_scanNumber == 0)
61  {
62 
64  QObject::tr("TimsFrame::TimsFrame(%1,%2,nullptr,%3) FAILED")
65  .arg(m_timsId)
66  .arg(m_scanNumber)
67  .arg(len));
68  }
69  }
70 }
71 
72 TimsFrame::TimsFrame(const TimsFrame &other) : TimsFrameBase(other)
73 {
74 }
75 
77 {
78 }
79 
80 
81 void
82 TimsFrame::unshufflePacket(const char *src)
83 {
84  qDebug();
85  quint64 len = m_timsDataFrame.size();
86  if(len % 4 != 0)
87  {
89  QObject::tr("TimsFrame::unshufflePacket error: len%4 != 0"));
90  }
91 
92  quint64 nb_uint4 = len / 4;
93 
94  char *dest = m_timsDataFrame.data();
95  quint64 src_offset = 0;
96 
97  for(quint64 j = 0; j < 4; j++)
98  {
99  for(quint64 i = 0; i < nb_uint4; i++)
100  {
101  dest[(i * 4) + j] = src[src_offset];
102  src_offset++;
103  }
104  }
105  qDebug();
106 }
107 
108 std::size_t
109 TimsFrame::getNbrPeaks(std::size_t scanNum) const
110 {
111  if(m_timsDataFrame.size() == 0)
112  return 0;
113  /*
114  if(scanNum == 0)
115  {
116  quint32 res = (*(quint32 *)(m_timsDataFrame.constData() + 4)) -
117  (*(quint32 *)(m_timsDataFrame.constData()-4));
118  return res / 2;
119  }*/
120  if(scanNum == (m_scanNumber - 1))
121  {
122  auto nb_uint4 = m_timsDataFrame.size() / 4;
123 
124  std::size_t cumul = 0;
125  for(quint32 i = 0; i < m_scanNumber; i++)
126  {
127  cumul += (*(quint32 *)(m_timsDataFrame.constData() + (i * 4)));
128  }
129  return (nb_uint4 - cumul) / 2;
130  }
131  checkScanNum(scanNum);
132 
133  // quint32 *res = (quint32 *)(m_timsDataFrame.constData() + (scanNum * 4));
134  // qDebug() << " res=" << *res;
135  return (*(quint32 *)(m_timsDataFrame.constData() + ((scanNum + 1) * 4))) / 2;
136 }
137 
138 std::size_t
139 TimsFrame::getScanOffset(std::size_t scanNum) const
140 {
141  std::size_t offset = 0;
142  for(std::size_t i = 0; i < (scanNum + 1); i++)
143  {
144  offset += (*(quint32 *)(m_timsDataFrame.constData() + (i * 4)));
145  }
146  return offset;
147 }
148 
149 
150 std::vector<quint32>
151 TimsFrame::getScanIndexList(std::size_t scanNum) const
152 {
153  qDebug();
154  checkScanNum(scanNum);
155  std::vector<quint32> scan_tof;
156 
157  if(m_timsDataFrame.size() == 0)
158  return scan_tof;
159  scan_tof.resize(getNbrPeaks(scanNum));
160 
161  std::size_t offset = getScanOffset(scanNum);
162 
163  qint32 previous = -1;
164  for(std::size_t i = 0; i < scan_tof.size(); i++)
165  {
166  scan_tof[i] =
167  (*(quint32 *)(m_timsDataFrame.constData() + (offset * 4) + (i * 8))) +
168  previous;
169  previous = scan_tof[i];
170  }
171  qDebug();
172  return scan_tof;
173 }
174 
175 std::vector<quint32>
176 TimsFrame::getScanIntensities(std::size_t scanNum) const
177 {
178  qDebug();
179  checkScanNum(scanNum);
180  std::vector<quint32> scan_intensities;
181 
182  if(m_timsDataFrame.size() == 0)
183  return scan_intensities;
184 
185  scan_intensities.resize(getNbrPeaks(scanNum));
186 
187  std::size_t offset = getScanOffset(scanNum);
188 
189  for(std::size_t i = 0; i < scan_intensities.size(); i++)
190  {
191  scan_intensities[i] = (*(quint32 *)(m_timsDataFrame.constData() +
192  (offset * 4) + (i * 8) + 4));
193  }
194  qDebug();
195  return scan_intensities;
196 }
197 
198 
199 void
200 TimsFrame::cumulateScan(std::size_t scanNum,
201  std::map<quint32, quint32> &accumulate_into) const
202 {
203  qDebug();
204 
205  if(m_timsDataFrame.size() == 0)
206  return;
207  checkScanNum(scanNum);
208 
209 
210  std::size_t size = getNbrPeaks(scanNum);
211 
212  std::size_t offset = getScanOffset(scanNum);
213 
214  qint32 previous = -1;
215  for(std::size_t i = 0; i < size; i++)
216  {
217  quint32 x =
218  (*(quint32 *)((m_timsDataFrame.constData() + (offset * 4) + (i * 8))) +
219  previous);
220  quint32 y = (*(quint32 *)(m_timsDataFrame.constData() + (offset * 4) +
221  (i * 8) + 4));
222 
223  previous = x;
224 
225  auto ret = accumulate_into.insert(std::pair<quint32, quint32>(x, y));
226 
227  if(ret.second == false)
228  {
229  // already existed : cumulate
230  ret.first->second += y;
231  }
232  }
233  qDebug();
234 }
235 
236 
237 Trace
238 TimsFrame::cumulateScanToTrace(std::size_t scanNumBegin,
239  std::size_t scanNumEnd) const
240 {
241  qDebug();
242  try
243  {
244  Trace new_trace;
245  if(m_timsDataFrame.size() == 0)
246  return new_trace;
247  std::map<quint32, quint32> raw_spectrum;
248  // double local_accumulationTime = 0;
249 
250  std::size_t imax = scanNumEnd + 1;
251  qDebug();
252  for(std::size_t i = scanNumBegin; i < imax; i++)
253  {
254  qDebug() << i;
255  cumulateScan(i, raw_spectrum);
256  qDebug() << i;
257  // local_accumulationTime += m_accumulationTime;
258  }
259  qDebug();
260  pappso::DataPoint data_point_cumul;
261 
262  for(std::pair<quint32, quint32> pair_tof_intensity : raw_spectrum)
263  {
264  data_point_cumul.x =
265  getMzFromTof(getTofFromIndex(pair_tof_intensity.first));
266  // normalization
267  data_point_cumul.y =
268  pair_tof_intensity.second * ((double)100.0 / m_accumulationTime);
269  new_trace.push_back(data_point_cumul);
270  }
271  new_trace.sortX();
272  qDebug();
273  return new_trace;
274  }
275 
276  catch(std::exception &error)
277  {
278  qDebug() << __FILE__ << "@" << __LINE__ << __FUNCTION__ << "()"
279  << QString(
280  "Failure in TimsFrame::cumulateScanToTrace %1 to %2 :\n %3")
281  .arg(scanNumBegin, scanNumEnd)
282  .arg(error.what());
283  }
284 }
285 
286 
289  std::map<quint32, quint32> &accumulated_scans) const
290 {
291  qDebug();
292  // qDebug();
293  // add flanking peaks
294  std::vector<quint32> keys;
295  transform(begin(accumulated_scans),
296  end(accumulated_scans),
297  back_inserter(keys),
298  [](std::map<quint32, quint32>::value_type const &pair) {
299  return pair.first;
300  });
301  std::sort(keys.begin(), keys.end());
302  pappso::DataPoint data_point_cumul;
303  data_point_cumul.x = 0;
304  quint32 previous = 0;
305  quint32 hole_width = 2;
306 
307  pappso::Trace local_trace;
308 
309  bool go_up = true;
310  double previous_intensity = 0;
311  /*
312  for(quint32 key : keys)
313  {
314 
315  data_point_cumul.x =
316  getMzFromTof(getTofFromIndex(key));
317  // normalization
318  data_point_cumul.y =
319  accumulated_scans[key] * ((double)100.0 / m_accumulationTime);
320  mass_spectrum_sptr.get()->push_back(data_point_cumul);
321  }
322 */
323  for(quint32 key : keys)
324  {
325  if((key - previous) > hole_width)
326  {
327 
328  // qDebug() << " key:" << key << " previous:" << previous
329  // << " (key - previous):" << (key - previous);
330  if(data_point_cumul.x != 0)
331  {
332  data_point_cumul.x = data_point_cumul.x / data_point_cumul.y;
333 
334  data_point_cumul.x =
335  getMzFromTof(getTofFromIndex(data_point_cumul.x));
336  // normalization
337  data_point_cumul.y =
338  data_point_cumul.y * ((double)100.0 / m_accumulationTime);
339  local_trace.push_back(data_point_cumul);
340  }
341  // reset
342  data_point_cumul.x = 0;
343  data_point_cumul.y = 0;
344  previous_intensity = 0;
345  go_up = true;
346  }
347  double intensity = accumulated_scans[key];
348 
349  if(previous_intensity < intensity)
350  {
351  if(!go_up)
352  {
353  // stop
354  data_point_cumul.x = data_point_cumul.x / data_point_cumul.y;
355 
356  data_point_cumul.x =
357  getMzFromTof(getTofFromIndex(data_point_cumul.x));
358  // normalization
359  data_point_cumul.y =
360  data_point_cumul.y * ((double)100.0 / m_accumulationTime);
361  local_trace.push_back(data_point_cumul);
362 
363  // reset
364  data_point_cumul.x = 0;
365  data_point_cumul.y = 0;
366  previous_intensity = 0;
367  go_up = true;
368  }
369  }
370  else
371  {
372  if(go_up)
373  {
374  go_up = false;
375  }
376  else
377  {
378  }
379  }
380 
381 
382  data_point_cumul.x += ((double)key * intensity);
383  data_point_cumul.y += intensity;
384  previous = key;
385  previous_intensity = intensity;
386  }
387 
388 
389  if(data_point_cumul.x != 0)
390  {
391  data_point_cumul.x = data_point_cumul.x / data_point_cumul.y;
392 
393  data_point_cumul.x = getMzFromTof(getTofFromIndex(data_point_cumul.x));
394  // normalization
395  data_point_cumul.y =
396  data_point_cumul.y * ((double)100.0 / m_accumulationTime);
397  local_trace.push_back(data_point_cumul);
398  }
399  local_trace.sortX();
400  qDebug();
401  // qDebug();
402  return local_trace;
403 }
404 
406 TimsFrame::getMassSpectrumCstSPtr(std::size_t scanNum) const
407 {
408  qDebug();
409  return getMassSpectrumSPtr(scanNum);
410 }
411 
413 TimsFrame::getMassSpectrumSPtr(std::size_t scanNum) const
414 {
415 
416  qDebug() << " scanNum=" << scanNum;
417 
418  checkScanNum(scanNum);
419 
420  qDebug();
421 
422  pappso::MassSpectrumSPtr mass_spectrum_sptr =
423  std::make_shared<pappso::MassSpectrum>();
424  // std::vector<DataPoint>
425 
426  if(m_timsDataFrame.size() == 0)
427  return mass_spectrum_sptr;
428  qDebug();
429 
430  std::size_t size = getNbrPeaks(scanNum);
431 
432  std::size_t offset = getScanOffset(scanNum);
433 
434  qint32 previous = -1;
435  std::vector<quint32> index_list;
436  for(std::size_t i = 0; i < size; i++)
437  {
438  DataPoint data_point(
439  (*(quint32 *)((m_timsDataFrame.constData() + (offset * 4) + (i * 8))) +
440  previous),
441  (*(quint32 *)(m_timsDataFrame.constData() + (offset * 4) + (i * 8) +
442  4)));
443 
444  // intensity normalization
445  data_point.y *= 100.0 / m_accumulationTime;
446 
447  previous = data_point.x;
448 
449 
450  // mz calibration
451  double tof = (data_point.x * m_digitizerTimebase) + m_digitizerDelay;
452  data_point.x = getMzFromTof(tof);
453  mass_spectrum_sptr.get()->push_back(data_point);
454  }
455  qDebug();
456  return mass_spectrum_sptr;
457 }
458 
459 
460 void
462  std::vector<TimsXicStructure>::iterator &itXicListbegin,
463  std::vector<TimsXicStructure>::iterator &itXicListend,
464  XicExtractMethod method) const
465 {
466  std::vector<TimsXicStructure> tmp_xic_list(itXicListbegin, itXicListend);
467 
468  if(tmp_xic_list.size() == 0)
469  return;
470  /*
471  std::sort(tmp_xic_list.begin(), tmp_xic_list.end(), [](const TimsXicStructure
472  &a, const TimsXicStructure &b) { return a.mobilityIndexBegin <
473  b.mobilityIndexBegin;
474  });
475  */
476  std::vector<std::size_t> unique_scan_num_list;
477  for(auto &&struct_xic : tmp_xic_list)
478  {
479  for(std::size_t scan = struct_xic.mobilityIndexBegin;
480  scan <= struct_xic.mobilityIndexEnd;
481  scan++)
482  {
483  unique_scan_num_list.push_back(scan);
484  }
485  }
486  std::sort(unique_scan_num_list.begin(), unique_scan_num_list.end());
487  auto it_scan_num_end =
488  std::unique(unique_scan_num_list.begin(), unique_scan_num_list.end());
489  auto it_scan_num = unique_scan_num_list.begin();
490 
491  while(it_scan_num != it_scan_num_end)
492  {
493  MassSpectrumCstSPtr ms_spectrum = getMassSpectrumCstSPtr(*it_scan_num);
494  for(auto &&tmp_xic_struct : tmp_xic_list)
495  {
496  if(((*it_scan_num) >= tmp_xic_struct.mobilityIndexBegin) &&
497  ((*it_scan_num) <= tmp_xic_struct.mobilityIndexEnd))
498  {
499  if(method == XicExtractMethod::max)
500  {
501  tmp_xic_struct.tmpIntensity +=
502  ms_spectrum.get()->maxY(tmp_xic_struct.mzRange.lower(),
503  tmp_xic_struct.mzRange.upper());
504  }
505  else
506  {
507  // sum
508  tmp_xic_struct.tmpIntensity +=
509  ms_spectrum.get()->sumY(tmp_xic_struct.mzRange.lower(),
510  tmp_xic_struct.mzRange.upper());
511  }
512  }
513  }
514  it_scan_num++;
515  }
516 
517  for(auto &&tmp_xic_struct : tmp_xic_list)
518  {
519  if(tmp_xic_struct.tmpIntensity != 0)
520  {
521  tmp_xic_struct.xicSptr.get()->push_back(
522  {m_time, tmp_xic_struct.tmpIntensity});
523  }
524  }
525 }
526 
527 } // namespace pappso
pappso::TimsFrame::getScanIntensities
std::vector< quint32 > getScanIntensities(std::size_t scanNum) const
get raw intensities without transformation from one scan it needs intensity normalization
Definition: timsframe.cpp:193
pappso::TimsFrameBase::m_digitizerTimebase
double m_digitizerTimebase
Definition: timsframebase.h:171
pappso::TimsFrameBase::checkScanNum
bool checkScanNum(std::size_t scanNum) const
Definition: timsframebase.cpp:100
pappso::MassSpectrumCstSPtr
std::shared_ptr< const MassSpectrum > MassSpectrumCstSPtr
Definition: massspectrum.h:74
pappso::TimsFrame::getTraceFromCumulatedScans
pappso::Trace getTraceFromCumulatedScans(std::map< quint32, quint32 > &accumulated_scans) const
transform accumulation of raw scans into a real mass spectrum
Definition: timsframe.cpp:305
timsdirectxicextractor.h
minimum functions to extract XICs from Tims Data
pappso::DataPoint::y
pappso_double y
Definition: datapoint.h:23
timsframe.h
handle a single Bruker's TimsTof frame
pappso
Definition: aa.cpp:38
pappso::TimsFrame::getMassSpectrumSPtr
virtual pappso::MassSpectrumSPtr getMassSpectrumSPtr(std::size_t scanNum) const override
Definition: timsframe.cpp:430
pappso::DataPoint
Definition: datapoint.h:20
pappso::PeptideIonCter::y
pappso::TimsFrame::getMassSpectrumCstSPtr
pappso::MassSpectrumCstSPtr getMassSpectrumCstSPtr(std::size_t scanNum) const
get the mass spectrum corresponding to a scan number
Definition: timsframe.cpp:423
pappso::TimsFrame::TimsFrame
TimsFrame(std::size_t timsId, quint32 scanNum, char *p_bytes, std::size_t len)
Definition: timsframe.cpp:58
pappso::PeptideIonCter::x
pappso::TimsFrameBase::m_accumulationTime
double m_accumulationTime
accumulation time in milliseconds
Definition: timsframebase.h:169
pappso::TimsFrameBase::m_time
double m_time
retention time
Definition: timsframebase.h:182
pappso::Trace
A simple container of DataPoint instances.
Definition: trace.h:125
pappso::XicExtractMethod
XicExtractMethod
Definition: types.h:201
pappso::TimsFrame::m_timsDataFrame
QByteArray m_timsDataFrame
Definition: timsframe.h:141
pappso::TimsFrame::unshufflePacket
void unshufflePacket(const char *src)
Definition: timsframe.cpp:99
pappso::TimsFrame::getNbrPeaks
virtual std::size_t getNbrPeaks(std::size_t scanNum) const override
Definition: timsframe.cpp:126
pappso::DataPoint::x
pappso_double x
Definition: datapoint.h:22
pappso::Trace::sortX
void sortX()
Definition: trace.cpp:741
pappso::XicExtractMethod::max
maximum of intensities
pappso::TimsFrame::cumulateScanToTrace
virtual Trace cumulateScanToTrace(std::size_t scanNumBegin, std::size_t scanNumEnd) const override
cumulate scan list into a trace
Definition: timsframe.cpp:255
pappso::TimsFrame::getScanIndexList
std::vector< quint32 > getScanIndexList(std::size_t scanNum) const
get raw index list for one given scan index are not TOF nor m/z, just index on digitizer
Definition: timsframe.cpp:168
pappso::TimsFrameBase::getMzFromTof
double getMzFromTof(double tof) const
get m/z from time of flight
Definition: timsframebase.cpp:157
pappso::TimsFrame::getScanOffset
std::size_t getScanOffset(std::size_t scanNum) const
Definition: timsframe.cpp:156
pappso::TimsFrameBase::m_scanNumber
quint32 m_scanNumber
total number of scans contained in this frame
Definition: timsframebase.h:159
pappso::TimsFrame::~TimsFrame
~TimsFrame()
Definition: timsframe.cpp:93
pappso::TimsFrameBase::getTofFromIndex
double getTofFromIndex(quint32 index) const
get time of flight from raw index
Definition: timsframebase.cpp:151
pappso::TimsFrameBase::m_digitizerDelay
double m_digitizerDelay
Definition: timsframebase.h:172
pappso::TimsFrame::cumulateScan
void cumulateScan(std::size_t scanNum, std::map< quint32, quint32 > &accumulate_into) const
cumulate a scan into a map
Definition: timsframe.cpp:217
pappso::TimsFrame::extractTimsXicListInRtRange
void extractTimsXicListInRtRange(std::vector< TimsXicStructure >::iterator &itXicListbegin, std::vector< TimsXicStructure >::iterator &itXicListend, XicExtractMethod method) const
Definition: timsframe.cpp:478
pappso::MassSpectrumSPtr
std::shared_ptr< MassSpectrum > MassSpectrumSPtr
Definition: massspectrum.h:73
pappso::PappsoException
Definition: pappsoexception.h:60