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 %2")
107  .arg(scanNum)
108  .arg(m_scanNumber));
109  }
110 
111  return true;
112 }
113 
114 std::size_t
115 TimsFrameBase::getNbrPeaks(std::size_t scanNum) const
116 {
117  throw PappsoException(
118  QObject::tr(
119  "ERROR unable to get number of peaks in TimsFrameBase for scan number %1")
120  .arg(scanNum));
121 }
122 
124 TimsFrameBase::getMassSpectrumSPtr(std::size_t scanNum) const
125 {
126  throw PappsoException(
127  QObject::tr(
128  "ERROR unable to getMassSpectrumSPtr in TimsFrameBase for scan number %1")
129  .arg(scanNum));
130 }
131 Trace
132 TimsFrameBase::cumulateScanToTrace(std::size_t scanNumBegin,
133  std::size_t scanNumEnd) const
134 {
135  throw PappsoException(
136  QObject::tr("ERROR unable to cumulateScanToTrace in TimsFrameBase for scan "
137  "number begin %1 end %2")
138  .arg(scanNumBegin)
139  .arg(scanNumEnd));
140 }
141 void
142 TimsFrameBase::cumulateScansInRawMap(std::map<quint32, quint32> &rawSpectrum
143  [[maybe_unused]],
144  std::size_t scanNumBegin,
145  std::size_t scanNumEnd) const
146 {
147  throw PappsoException(
148  QObject::tr(
149  "ERROR unable to cumulateScansInRawMap in TimsFrameBase for scan "
150  "number begin %1 end %2")
151  .arg(scanNumBegin)
152  .arg(scanNumEnd));
153 }
154 void
156 {
157  m_time = time;
158 }
159 
160 void
162 {
163 
164  qDebug() << " m_msMsType=" << type;
165  m_msMsType = type;
166 }
167 
168 unsigned int
170 {
171  if(m_msMsType == 0)
172  return 1;
173  return 2;
174 }
175 
176 double
178 {
179  return m_time;
180 }
181 
182 std::size_t
184 {
185  return m_timsId;
186 }
187 void
189  double C0,
190  double C1,
191  double C2,
192  double C3,
193  double C4,
194  [[maybe_unused]] double C5,
195  double C6,
196  double C7,
197  double C8,
198  double C9)
199 {
200  if(tims_model_type != 2)
201  {
202  throw pappso::PappsoException(QObject::tr(
203  "ERROR in TimsFrame::setTimsCalibration tims_model_type != 2"));
204  }
205  m_timsDvStart = C2; // C2 from TimsCalibration
206  m_timsTtrans = C4; // C4 from TimsCalibration
207  m_timsNdelay = C0; // C0 from TimsCalibration
208  m_timsVmin = C8; // C8 from TimsCalibration
209  m_timsVmax = C9; // C9 from TimsCalibration
210  m_timsC6 = C6;
211  m_timsC7 = C7;
212 
213 
214  m_timsSlope =
215  (C3 - m_timsDvStart) / C1; // //C3 from TimsCalibration // C2 from
216  // TimsCalibration // C1 from TimsCalibration
217 }
218 double
219 TimsFrameBase::getVoltageTransformation(std::size_t scanNum) const
220 {
221  double v = m_timsDvStart +
222  m_timsSlope * ((double)scanNum - m_timsTtrans - m_timsNdelay);
223 
224  if(v < m_timsVmin)
225  {
227  QObject::tr("ERROR in TimsFrame::getVoltageTransformation invalid tims "
228  "calibration, v < m_timsVmin"));
229  }
230 
231 
232  if(v > m_timsVmax)
233  {
235  QObject::tr("ERROR in TimsFrame::getVoltageTransformation invalid tims "
236  "calibration, v > m_timsVmax"));
237  }
238  return v;
239 }
240 double
241 TimsFrameBase::getDriftTime(std::size_t scanNum) const
242 {
243  return (m_accumulationTime / (double)m_scanNumber) * ((double)scanNum);
244 }
245 
246 double
248 {
249  return 1 / (m_timsC6 + (m_timsC7 / getVoltageTransformation(scanNum)));
250 }
251 
252 
253 std::size_t
254 TimsFrameBase::getScanNumFromOneOverK0(double one_over_k0) const
255 {
256  double temp = 1 / one_over_k0;
257  temp = temp - m_timsC6;
258  temp = temp / m_timsC7;
259  temp = 1 / temp;
260  temp = temp - m_timsDvStart;
261  temp = temp / m_timsSlope + m_timsTtrans + m_timsNdelay;
262  return (std::size_t)std::round(temp);
263 }
264 
265 bool
267 {
268  if((m_timsDvStart == other.m_timsDvStart) &&
269  (m_timsTtrans == other.m_timsTtrans) &&
270  (m_timsNdelay == other.m_timsNdelay) && (m_timsVmin == other.m_timsVmin) &&
271  (m_timsVmax == other.m_timsVmax) && (m_timsC6 == other.m_timsC6) &&
272  (m_timsC7 == other.m_timsC7) && (m_timsSlope == other.m_timsSlope))
273  {
274  return true;
275  }
276  return false;
277 }
278 
279 
282  std::map<quint32, quint32> &accumulated_scans) const
283 {
284  qDebug();
285  // qDebug();
286  // add flanking peaks
287  pappso::Trace local_trace;
288 
289  MzCalibrationInterface *mz_calibration_p =
291 
292 
293  DataPoint element;
294  for(auto &scan_element : accumulated_scans)
295  {
296  // intensity normalization
297  element.y = ((double)scan_element.second) * 100.0 / m_accumulationTime;
298 
299  // mz calibration
300  element.x = mz_calibration_p->getMzFromTofIndex(scan_element.first);
301 
302  local_trace.push_back(element);
303  }
304  local_trace.sortX();
305 
306  qDebug();
307  // qDebug();
308  return local_trace;
309 }
310 
313  std::map<quint32, quint32> &accumulated_scans) const
314 {
315  qDebug();
316  // qDebug();
317  // add flanking peaks
318  std::vector<quint32> keys;
319  transform(begin(accumulated_scans),
320  end(accumulated_scans),
321  back_inserter(keys),
322  [](std::map<quint32, quint32>::value_type const &pair) {
323  return pair.first;
324  });
325  std::sort(keys.begin(), keys.end());
326  pappso::DataPoint data_point_cumul;
327  data_point_cumul.x = 0;
328  data_point_cumul.y = 0;
329 
330  pappso::Trace local_trace;
331 
332  MzCalibrationInterface *mz_calibration_p =
334 
335 
336  quint32 last_key = 0;
337 
338  for(quint32 key : keys)
339  {
340  if(key == last_key + 1)
341  {
342  // cumulate
343  if(accumulated_scans[key] > accumulated_scans[last_key])
344  {
345  if(data_point_cumul.x == last_key)
346  {
347  // growing peak
348  data_point_cumul.x = key;
349  data_point_cumul.y += accumulated_scans[key];
350  }
351  else
352  {
353  // new peak
354  // flush
355  if(data_point_cumul.y > 0)
356  {
357  // intensity normalization
358  data_point_cumul.y *= 100.0 / m_accumulationTime;
359 
360 
361  // mz calibration
362  data_point_cumul.x =
363  mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
364  local_trace.push_back(data_point_cumul);
365  }
366 
367  // new point
368  data_point_cumul.x = key;
369  data_point_cumul.y = accumulated_scans[key];
370  }
371  }
372  else
373  {
374  data_point_cumul.y += accumulated_scans[key];
375  }
376  }
377  else
378  {
379  // flush
380  if(data_point_cumul.y > 0)
381  {
382  // intensity normalization
383  data_point_cumul.y *= 100.0 / m_accumulationTime;
384 
385 
386  qDebug() << "raw data x=" << data_point_cumul.x;
387  // mz calibration
388  data_point_cumul.x =
389  mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
390  qDebug() << "mz=" << data_point_cumul.x;
391  local_trace.push_back(data_point_cumul);
392  }
393 
394  // new point
395  data_point_cumul.x = key;
396  data_point_cumul.y = accumulated_scans[key];
397  }
398 
399  last_key = key;
400  }
401  // flush
402  if(data_point_cumul.y > 0)
403  {
404  // intensity normalization
405  data_point_cumul.y *= 100.0 / m_accumulationTime;
406 
407 
408  // mz calibration
409  data_point_cumul.x =
410  mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
411  local_trace.push_back(data_point_cumul);
412  }
413 
414  local_trace.sortX();
415  qDebug();
416  // qDebug();
417  return local_trace;
418 }
419 
422 {
423  if(msp_mzCalibration == nullptr)
424  {
425 
427  QObject::tr("ERROR in %1, %2, %3 msp_mzCalibration is null")
428  .arg(__FILE__)
429  .arg(__FUNCTION__)
430  .arg(__LINE__));
431  }
432  return msp_mzCalibration;
433 }
434 
435 void
437  MzCalibrationInterfaceSPtr mzCalibration)
438 {
439 
440  if(mzCalibration == nullptr)
441  {
442 
444  QObject::tr("ERROR in %1, %2, %3 msp_mzCalibration is null")
445  .arg(__FILE__)
446  .arg(__FUNCTION__)
447  .arg(__LINE__));
448  }
449  msp_mzCalibration = mzCalibration;
450 }
451 
452 } // 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
get voltage for a given scan number
virtual Trace cumulateScanToTrace(std::size_t scanNumBegin, std::size_t scanNumEnd) const
cumulate spectrum given a scan number range need the binary file
virtual std::size_t getNbrPeaks(std::size_t scanNum) const
get the number of peaks in this spectrum need the binary file
MzCalibrationInterfaceSPtr msp_mzCalibration
virtual MassSpectrumSPtr getMassSpectrumSPtr(std::size_t scanNum) const
get Mass spectrum with peaks for this scan number need the binary file
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
check that this scan number exists
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