libpappsomspp
Library for mass spectrometry
timsframebase.cpp
Go to the documentation of this file.
1 /**
2  * \file pappsomspp/vendors/tims/timsframebase.cpp
3  * \date 16/12/2019
4  * \author Olivier Langella
5  * \brief handle a single Bruker's TimsTof frame without binary data
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 #include "timsframebase.h"
28 #include "../../../pappsomspp/pappsoexception.h"
29 #include "../../../pappsomspp/exception/exceptionoutofrange.h"
31 #include <QDebug>
32 #include <cmath>
33 
34 namespace pappso
35 {
36 
37 TimsFrameBase::TimsFrameBase(std::size_t timsId, quint32 scanNum)
38 {
39  qDebug() << timsId;
40  m_timsId = timsId;
41 
42  m_scanNumber = scanNum;
43 }
44 
45 TimsFrameBase::TimsFrameBase([[maybe_unused]] const TimsFrameBase &other)
46 {
47 }
48 
50 {
51 }
52 
53 void
54 TimsFrameBase::setAccumulationTime(double accumulation_time_ms)
55 {
56  m_accumulationTime = accumulation_time_ms;
57 }
58 
59 
60 void
62  double T2_frame,
63  double digitizerTimebase,
64  double digitizerDelay,
65  double C0,
66  double C1,
67  double C2,
68  double C3,
69  double C4,
70  double T1_ref,
71  double T2_ref,
72  double dC1,
73  double dC2)
74 {
75 
76  /* MzCalibrationModel1 mzCalibration(temperature_correction,
77  digitizerTimebase,
78  digitizerDelay,
79  C0,
80  C1,
81  C2,
82  C3,
83  C4);
84  */
85  msp_mzCalibration = std::make_shared<MzCalibrationModel1>(T1_frame,
86  T2_frame,
87  digitizerTimebase,
88  digitizerDelay,
89  C0,
90  C1,
91  C2,
92  C3,
93  C4,
94  T1_ref,
95  T2_ref,
96  dC1,
97  dC2);
98 }
99 
100 bool
101 TimsFrameBase::checkScanNum(std::size_t scanNum) const
102 {
103  if(scanNum >= m_scanNumber)
104  {
106  QObject::tr("Invalid scan number : scanNum%1 > m_scanNumber")
107  .arg(scanNum));
108  }
109 
110  return true;
111 }
112 
113 std::size_t
114 TimsFrameBase::getNbrPeaks(std::size_t scanNum) const
115 {
116  throw PappsoException(
117  QObject::tr(
118  "ERROR unable to get number of peaks in TimsFrameBase for scan number %1")
119  .arg(scanNum));
120 }
121 
123 TimsFrameBase::getMassSpectrumSPtr(std::size_t scanNum) const
124 {
125  throw PappsoException(
126  QObject::tr(
127  "ERROR unable to getMassSpectrumSPtr in TimsFrameBase for scan number %1")
128  .arg(scanNum));
129 }
130 Trace
131 TimsFrameBase::cumulateScanToTrace(std::size_t scanNumBegin,
132  std::size_t scanNumEnd) const
133 {
134  throw PappsoException(
135  QObject::tr("ERROR unable to cumulateScanToTrace in TimsFrameBase for scan "
136  "number begin %1 end %2")
137  .arg(scanNumBegin)
138  .arg(scanNumEnd));
139 }
140 void
141 TimsFrameBase::cumulateScansInRawMap(std::map<quint32, quint32> &rawSpectrum
142  [[maybe_unused]],
143  std::size_t scanNumBegin,
144  std::size_t scanNumEnd) const
145 {
146  throw PappsoException(
147  QObject::tr(
148  "ERROR unable to cumulateScansInRawMap in TimsFrameBase for scan "
149  "number begin %1 end %2")
150  .arg(scanNumBegin)
151  .arg(scanNumEnd));
152 }
153 void
155 {
156  m_time = time;
157 }
158 
159 void
161 {
162 
163  qDebug() << " m_msMsType=" << type;
164  m_msMsType = type;
165 }
166 
167 unsigned int
169 {
170  if(m_msMsType == 0)
171  return 1;
172  return 2;
173 }
174 
175 double
177 {
178  return m_time;
179 }
180 
181 std::size_t
183 {
184  return m_timsId;
185 }
186 void
188  double C0,
189  double C1,
190  double C2,
191  double C3,
192  double C4,
193  [[maybe_unused]] double C5,
194  double C6,
195  double C7,
196  double C8,
197  double C9)
198 {
199  if(tims_model_type != 2)
200  {
201  throw pappso::PappsoException(QObject::tr(
202  "ERROR in TimsFrame::setTimsCalibration tims_model_type != 2"));
203  }
204  m_timsDvStart = C2; // C2 from TimsCalibration
205  m_timsTtrans = C4; // C4 from TimsCalibration
206  m_timsNdelay = C0; // C0 from TimsCalibration
207  m_timsVmin = C8; // C8 from TimsCalibration
208  m_timsVmax = C9; // C9 from TimsCalibration
209  m_timsC6 = C6;
210  m_timsC7 = C7;
211 
212 
213  m_timsSlope =
214  (C3 - m_timsDvStart) / C1; // //C3 from TimsCalibration // C2 from
215  // TimsCalibration // C1 from TimsCalibration
216 }
217 double
218 TimsFrameBase::getVoltageTransformation(std::size_t scanNum) const
219 {
220  double v = m_timsDvStart +
221  m_timsSlope * ((double)scanNum - m_timsTtrans - m_timsNdelay);
222 
223  if(v < m_timsVmin)
224  {
226  QObject::tr("ERROR in TimsFrame::getVoltageTransformation invalid tims "
227  "calibration, v < m_timsVmin"));
228  }
229 
230 
231  if(v > m_timsVmax)
232  {
234  QObject::tr("ERROR in TimsFrame::getVoltageTransformation invalid tims "
235  "calibration, v > m_timsVmax"));
236  }
237  return v;
238 }
239 double
240 TimsFrameBase::getDriftTime(std::size_t scanNum) const
241 {
242  return (m_accumulationTime / (double)m_scanNumber) * ((double)scanNum);
243 }
244 
245 double
247 {
248  return 1 / (m_timsC6 + (m_timsC7 / getVoltageTransformation(scanNum)));
249 }
250 
251 
252 std::size_t
253 TimsFrameBase::getScanNumFromOneOverK0(double one_over_k0) const
254 {
255  double temp = 1 / one_over_k0;
256  temp = temp - m_timsC6;
257  temp = temp / m_timsC7;
258  temp = 1 / temp;
259  temp = temp - m_timsDvStart;
260  temp = temp / m_timsSlope + m_timsTtrans + m_timsNdelay;
261  return (std::size_t)std::round(temp);
262 }
263 
264 bool
266 {
267  if((m_timsDvStart == other.m_timsDvStart) &&
268  (m_timsTtrans == other.m_timsTtrans) &&
269  (m_timsNdelay == other.m_timsNdelay) && (m_timsVmin == other.m_timsVmin) &&
270  (m_timsVmax == other.m_timsVmax) && (m_timsC6 == other.m_timsC6) &&
271  (m_timsC7 == other.m_timsC7) && (m_timsSlope == other.m_timsSlope))
272  {
273  return true;
274  }
275  return false;
276 }
277 
278 
281  std::map<quint32, quint32> &accumulated_scans) const
282 {
283  qDebug();
284  // qDebug();
285  // add flanking peaks
286  pappso::Trace local_trace;
287 
288  MzCalibrationInterface *mz_calibration_p =
290 
291 
292  DataPoint element;
293  for(auto &scan_element : accumulated_scans)
294  {
295  // intensity normalization
296  element.y = ((double)scan_element.second) * 100.0 / m_accumulationTime;
297 
298  // mz calibration
299  element.x = mz_calibration_p->getMzFromTofIndex(scan_element.first);
300 
301  local_trace.push_back(element);
302  }
303  local_trace.sortX();
304 
305  qDebug();
306  // qDebug();
307  return local_trace;
308 }
309 
312  std::map<quint32, quint32> &accumulated_scans) const
313 {
314  qDebug();
315  // qDebug();
316  // add flanking peaks
317  std::vector<quint32> keys;
318  transform(begin(accumulated_scans),
319  end(accumulated_scans),
320  back_inserter(keys),
321  [](std::map<quint32, quint32>::value_type const &pair) {
322  return pair.first;
323  });
324  std::sort(keys.begin(), keys.end());
325  pappso::DataPoint data_point_cumul;
326  data_point_cumul.x = 0;
327  data_point_cumul.y = 0;
328 
329  pappso::Trace local_trace;
330 
331  MzCalibrationInterface *mz_calibration_p =
333 
334 
335  quint32 last_key = 0;
336 
337  for(quint32 key : keys)
338  {
339  if(key == last_key + 1)
340  {
341  // cumulate
342  if(accumulated_scans[key] > accumulated_scans[last_key])
343  {
344  if(data_point_cumul.x == last_key)
345  {
346  // growing peak
347  data_point_cumul.x = key;
348  data_point_cumul.y += accumulated_scans[key];
349  }
350  else
351  {
352  // new peak
353  // flush
354  if(data_point_cumul.y > 0)
355  {
356  // intensity normalization
357  data_point_cumul.y *= 100.0 / m_accumulationTime;
358 
359 
360  // mz calibration
361  data_point_cumul.x =
362  mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
363  local_trace.push_back(data_point_cumul);
364  }
365 
366  // new point
367  data_point_cumul.x = key;
368  data_point_cumul.y = accumulated_scans[key];
369  }
370  }
371  else
372  {
373  data_point_cumul.y += accumulated_scans[key];
374  }
375  }
376  else
377  {
378  // flush
379  if(data_point_cumul.y > 0)
380  {
381  // intensity normalization
382  data_point_cumul.y *= 100.0 / m_accumulationTime;
383 
384 
385  qDebug() << "raw data x=" << data_point_cumul.x;
386  // mz calibration
387  data_point_cumul.x =
388  mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
389  qDebug() << "mz=" << data_point_cumul.x;
390  local_trace.push_back(data_point_cumul);
391  }
392 
393  // new point
394  data_point_cumul.x = key;
395  data_point_cumul.y = accumulated_scans[key];
396  }
397 
398  last_key = key;
399  }
400  // flush
401  if(data_point_cumul.y > 0)
402  {
403  // intensity normalization
404  data_point_cumul.y *= 100.0 / m_accumulationTime;
405 
406 
407  // mz calibration
408  data_point_cumul.x =
409  mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
410  local_trace.push_back(data_point_cumul);
411  }
412 
413  local_trace.sortX();
414  qDebug();
415  // qDebug();
416  return local_trace;
417 }
418 
421 {
422  if(msp_mzCalibration == nullptr)
423  {
424 
426  QObject::tr("ERROR in %1, %2, %3 msp_mzCalibration is null")
427  .arg(__FILE__)
428  .arg(__FUNCTION__)
429  .arg(__LINE__));
430  }
431  return msp_mzCalibration;
432 }
433 
434 void
436  MzCalibrationInterfaceSPtr mzCalibration)
437 {
438 
439  if(mzCalibration == nullptr)
440  {
441 
443  QObject::tr("ERROR in %1, %2, %3 msp_mzCalibration is null")
444  .arg(__FILE__)
445  .arg(__FUNCTION__)
446  .arg(__LINE__));
447  }
448  msp_mzCalibration = mzCalibration;
449 }
450 
451 } // namespace pappso
virtual double getMzFromTofIndex(quint32 tof_index)=0
get m/z from time of flight raw index
double m_accumulationTime
accumulation time in milliseconds
double getTime() const
double getVoltageTransformation(std::size_t scanNum) const
virtual Trace cumulateScanToTrace(std::size_t scanNumBegin, std::size_t scanNumEnd) const
virtual std::size_t getNbrPeaks(std::size_t scanNum) const
MzCalibrationInterfaceSPtr msp_mzCalibration
virtual MassSpectrumSPtr getMassSpectrumSPtr(std::size_t scanNum) const
TimsFrameBase(std::size_t timsId, quint32 scanNum)
constructor for binary independant tims frame
double getDriftTime(std::size_t scanNum) const
get drift time of a scan number in milliseconds
pappso::Trace getTraceFromCumulatedScansBuiltinCentroid(std::map< quint32, quint32 > &accumulated_scans) const
transform accumulation of raw scans into a real mass spectrum with a simple centroid on raw integers
double m_time
retention time
void setAccumulationTime(double accumulation_time_ms)
quint32 m_scanNumber
total number of scans contained in this frame
virtual void cumulateScansInRawMap(std::map< quint32, quint32 > &rawSpectrum, std::size_t scanNumBegin, std::size_t scanNumEnd) const
cumulate scan list into a trace into a raw spectrum map
void setTime(double time)
std::size_t m_timsId
Tims frame database id (the SQL identifier of this frame)
pappso::Trace getTraceFromCumulatedScans(std::map< quint32, quint32 > &accumulated_scans) const
transform accumulation of raw scans into a real mass spectrum
virtual bool hasSameCalibrationData(const TimsFrameBase &other) const
tells if 2 tims frame has the same calibration data Usefull to know if raw data can be handled betwee...
unsigned int getMsLevel() const
void setTimsCalibration(int tims_model_type, double C0, double C1, double C2, double C3, double C4, double C5, double C6, double C7, double C8, double C9)
virtual const MzCalibrationInterfaceSPtr & getMzCalibrationInterfaceSPtr() const final
get the MzCalibration model to compute mz and TOF for this frame
std::size_t getScanNumFromOneOverK0(double one_over_k0) const
get the scan number from a given 1/Ko mobility value
void setMsMsType(quint8 type)
void setMzCalibration(double T1_frame, double T2_frame, double digitizerTimebase, double digitizerDelay, double C0, double C1, double C2, double C3, double C4, double T1_ref, double T2_ref, double dC1, double dC2)
double getOneOverK0Transformation(std::size_t scanNum) const
get 1/K0 value of a given scan (mobility value)
bool checkScanNum(std::size_t scanNum) const
void setMzCalibrationInterfaceSPtr(MzCalibrationInterfaceSPtr mzCalibration)
std::size_t getId() const
A simple container of DataPoint instances.
Definition: trace.h:132
void sortX()
Definition: trace.cpp:878
implement Bruker's model type 1 formula to compute m/z
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition: aa.cpp:39
std::shared_ptr< MzCalibrationInterface > MzCalibrationInterfaceSPtr
std::shared_ptr< MassSpectrum > MassSpectrumSPtr
Definition: massspectrum.h:54
pappso_double x
Definition: datapoint.h:22
pappso_double y
Definition: datapoint.h:23
handle a single Bruker's TimsTof frame without binary data