libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
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 <QObject>
33#include <cmath>
34#include <algorithm>
35
36namespace pappso
37{
38
39TimsFrameBase::TimsFrameBase(std::size_t timsId, quint32 scanNum)
40{
41 qDebug() << timsId;
42 m_timsId = timsId;
43
44 m_scanNumber = scanNum;
45}
46
47TimsFrameBase::TimsFrameBase([[maybe_unused]] const TimsFrameBase &other)
48{
49}
50
54
55void
56TimsFrameBase::setAccumulationTime(double accumulation_time_ms)
57{
58 m_accumulationTime = accumulation_time_ms;
59}
60
61
62void
64 double T2_frame,
65 double digitizerTimebase,
66 double digitizerDelay,
67 double C0,
68 double C1,
69 double C2,
70 double C3,
71 double C4,
72 double T1_ref,
73 double T2_ref,
74 double dC1,
75 double dC2)
76{
77
78 /* MzCalibrationModel1 mzCalibration(temperature_correction,
79 digitizerTimebase,
80 digitizerDelay,
81 C0,
82 C1,
83 C2,
84 C3,
85 C4);
86 */
87 msp_mzCalibration = std::make_shared<MzCalibrationModel1>(T1_frame,
88 T2_frame,
89 digitizerTimebase,
90 digitizerDelay,
91 C0,
92 C1,
93 C2,
94 C3,
95 C4,
96 T1_ref,
97 T2_ref,
98 dC1,
99 dC2);
100}
101
102bool
103TimsFrameBase::checkScanNum(std::size_t scanNum) const
104{
105 if(scanNum >= m_scanNumber)
106 {
108 QObject::tr("Invalid scan number : scanNum %1 > m_scanNumber %2")
109 .arg(scanNum)
110 .arg(m_scanNumber));
111 }
112
113 return true;
114}
115
116std::size_t
117TimsFrameBase::getNbrPeaks(std::size_t scanNum) const
118{
119 throw PappsoException(
120 QObject::tr(
121 "ERROR unable to get number of peaks in TimsFrameBase for scan number %1")
122 .arg(scanNum));
123}
124
125std::size_t
130
132TimsFrameBase::getMassSpectrumSPtr(std::size_t scanNum) const
133{
134 throw PappsoException(
135 QObject::tr(
136 "ERROR unable to getMassSpectrumSPtr in TimsFrameBase for scan number %1")
137 .arg(scanNum));
138}
139
140
143{
144 // qDebug();
145
146 return getMassSpectrumSPtr(scanNum);
147}
148Trace
149TimsFrameBase::cumulateScansToTrace(std::size_t scanNumBegin,
150 std::size_t scanNumEnd) const
151{
152 throw PappsoException(
153 QObject::tr("ERROR unable to cumulateScanToTrace in TimsFrameBase for scan "
154 "number begin %1 end %2")
155 .arg(scanNumBegin)
156 .arg(scanNumEnd));
157}
158
159Trace
161 std::size_t mzindex_merge_window [[maybe_unused]],
162 std::size_t scanNumBegin [[maybe_unused]],
163 std::size_t scanNumEnd [[maybe_unused]],
164 quint32 &minimum_index [[maybe_unused]],
165 quint32 &maximum_index [[maybe_unused]]) const
166{
167 throw PappsoException(QObject::tr("Non implemented function %1 %2 %3")
168 .arg(__FILE__)
169 .arg(__FUNCTION__)
170 .arg(__LINE__));
171}
172
173Trace
175 std::size_t mz_index_merge_window [[maybe_unused]],
176 double mz_range_begin [[maybe_unused]],
177 double mz_range_end [[maybe_unused]],
178 std::size_t mobility_scan_begin [[maybe_unused]],
179 std::size_t mobility_scan_end [[maybe_unused]],
180 quint32 &mz_minimum_index_out [[maybe_unused]],
181 quint32 &mz_maximum_index_out [[maybe_unused]]) const
182{
183 throw PappsoException(QObject::tr("Non implemented function %1 %2 %3")
184 .arg(__FILE__)
185 .arg(__FUNCTION__)
186 .arg(__LINE__));
187}
188
189Trace
190TimsFrameBase::getMobilityScan(std::size_t scanNum [[maybe_unused]],
191 std::size_t mz_index_merge_window
192 [[maybe_unused]],
193 double mz_range_begin [[maybe_unused]],
194 double mz_range_end [[maybe_unused]],
195 quint32 &mz_minimum_index_out [[maybe_unused]],
196 quint32 &mz_maximum_index_out
197 [[maybe_unused]]) const
198{
199 throw PappsoException(QObject::tr("Non implemented function %1 %2 %3")
200 .arg(__FILE__)
201 .arg(__FUNCTION__)
202 .arg(__LINE__));
203}
204
205void
206TimsFrameBase::cumulateScansInRawMap(std::map<quint32, quint32> &rawSpectrum
207 [[maybe_unused]],
208 std::size_t scanNumBegin,
209 std::size_t scanNumEnd) const
210{
211 throw PappsoException(
212 QObject::tr(
213 "ERROR unable to cumulateScansInRawMap in TimsFrameBase for scan "
214 "number begin %1 end %2")
215 .arg(scanNumBegin)
216 .arg(scanNumEnd));
217}
218
219
220quint64
222{
223 throw PappsoException(
224 QObject::tr(
225 "ERROR unable to cumulateSingleScanIntensities in TimsFrameBase for scan "
226 "number %1.")
227 .arg(scanNum));
228
229 return 0;
230}
231
232
233quint64
235 std::size_t scanNumEnd) const
236{
237 throw PappsoException(
238 QObject::tr(
239 "ERROR unable to cumulateScansInRawMap in TimsFrameBase for scan "
240 "number begin %1 end %2")
241 .arg(scanNumBegin)
242 .arg(scanNumEnd));
243
244 return 0;
245}
246
247void
249{
250 m_time = time;
251}
252
253void
255{
256
257 qDebug() << " m_msMsType=" << type;
258 m_msMsType = type;
259}
260
261unsigned int
263{
264 if(m_msMsType == 0)
265 return 1;
266 return 2;
267}
268
269double
271{
272 return m_time;
273}
274
275std::size_t
277{
278 return m_timsId;
279}
280void
282 double C0,
283 double C1,
284 double C2,
285 double C3,
286 double C4,
287 [[maybe_unused]] double C5,
288 double C6,
289 double C7,
290 double C8,
291 double C9)
292{
293 if(tims_model_type != 2)
294 {
295 throw pappso::PappsoException(QObject::tr(
296 "ERROR in TimsFrame::setTimsCalibration tims_model_type != 2"));
297 }
298 m_timsDvStart = C2; // C2 from TimsCalibration
299 m_timsTtrans = C4; // C4 from TimsCalibration
300 m_timsNdelay = C0; // C0 from TimsCalibration
301 m_timsVmin = C8; // C8 from TimsCalibration
302 m_timsVmax = C9; // C9 from TimsCalibration
303 m_timsC6 = C6;
304 m_timsC7 = C7;
305
306
308 (C3 - m_timsDvStart) / C1; // //C3 from TimsCalibration // C2 from
309 // TimsCalibration // C1 from TimsCalibration
310}
311double
313{
314 double v = m_timsDvStart +
315 m_timsSlope * ((double)scanNum - m_timsTtrans - m_timsNdelay);
316
317 if(v < m_timsVmin)
318 {
320 QObject::tr("ERROR in TimsFrame::getVoltageTransformation invalid tims "
321 "calibration, v < m_timsVmin"));
322 }
323
324
325 if(v > m_timsVmax)
326 {
328 QObject::tr("ERROR in TimsFrame::getVoltageTransformation invalid tims "
329 "calibration, v > m_timsVmax"));
330 }
331 return v;
332}
333double
334TimsFrameBase::getDriftTime(std::size_t scanNum) const
335{
336 return (m_accumulationTime / (double)m_scanNumber) * ((double)scanNum);
337}
338
339double
341{
342 return 1 / (m_timsC6 + (m_timsC7 / getVoltageTransformation(scanNum)));
343}
344
345
346std::size_t
348{
349 double temp = 1 / one_over_k0;
350 temp = temp - m_timsC6;
351 temp = temp / m_timsC7;
352 temp = 1 / temp;
353 temp = temp - m_timsDvStart;
354 temp = temp / m_timsSlope + m_timsTtrans + m_timsNdelay;
355 return (std::size_t)std::round(temp);
356}
357
358bool
360{
361 if((m_timsDvStart == other.m_timsDvStart) &&
362 (m_timsTtrans == other.m_timsTtrans) &&
363 (m_timsNdelay == other.m_timsNdelay) && (m_timsVmin == other.m_timsVmin) &&
364 (m_timsVmax == other.m_timsVmax) && (m_timsC6 == other.m_timsC6) &&
365 (m_timsC7 == other.m_timsC7) && (m_timsSlope == other.m_timsSlope))
366 {
367 return true;
368 }
369 return false;
370}
371
372
375 std::map<quint32, quint32> &accumulated_scans) const
376{
377 qDebug();
378 // qDebug();
379 // add flanking peaks
380 pappso::Trace local_trace;
381
382 MzCalibrationInterface *mz_calibration_p =
384
385
386 DataPoint element;
387 for(auto &scan_element : accumulated_scans)
388 {
389 // intensity normalization
390 element.y = ((double)scan_element.second) * 100.0 / m_accumulationTime;
391
392 // mz calibration
393 element.x = mz_calibration_p->getMzFromTofIndex(scan_element.first);
394
395 local_trace.push_back(element);
396 }
397 local_trace.sortX();
398
399 qDebug();
400 // qDebug();
401 return local_trace;
402}
403
406 std::map<quint32, quint32> &accumulated_scans) const
407{
408 qDebug();
409 // qDebug();
410 // add flanking peaks
411 std::vector<quint32> keys;
412 transform(begin(accumulated_scans),
413 end(accumulated_scans),
414 back_inserter(keys),
415 [](std::map<quint32, quint32>::value_type const &pair) {
416 return pair.first;
417 });
418 std::sort(keys.begin(), keys.end());
419 pappso::DataPoint data_point_cumul;
420 data_point_cumul.x = 0;
421 data_point_cumul.y = 0;
422
423 pappso::Trace local_trace;
424
425 MzCalibrationInterface *mz_calibration_p =
427
428
429 quint32 last_key = 0;
430
431 for(quint32 key : keys)
432 {
433 if(key == last_key + 1)
434 {
435 // cumulate
436 if(accumulated_scans[key] > accumulated_scans[last_key])
437 {
438 if(data_point_cumul.x == last_key)
439 {
440 // growing peak
441 data_point_cumul.x = key;
442 data_point_cumul.y += accumulated_scans[key];
443 }
444 else
445 {
446 // new peak
447 // flush
448 if(data_point_cumul.y > 0)
449 {
450 // intensity normalization
451 data_point_cumul.y *= 100.0 / m_accumulationTime;
452
453
454 // mz calibration
455 data_point_cumul.x =
456 mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
457 local_trace.push_back(data_point_cumul);
458 }
459
460 // new point
461 data_point_cumul.x = key;
462 data_point_cumul.y = accumulated_scans[key];
463 }
464 }
465 else
466 {
467 data_point_cumul.y += accumulated_scans[key];
468 }
469 }
470 else
471 {
472 // flush
473 if(data_point_cumul.y > 0)
474 {
475 // intensity normalization
476 data_point_cumul.y *= 100.0 / m_accumulationTime;
477
478
479 // qDebug() << "raw data x=" << data_point_cumul.x;
480 // mz calibration
481 data_point_cumul.x =
482 mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
483 // qDebug() << "mz=" << data_point_cumul.x;
484 local_trace.push_back(data_point_cumul);
485 }
486
487 // new point
488 data_point_cumul.x = key;
489 data_point_cumul.y = accumulated_scans[key];
490 }
491
492 last_key = key;
493 }
494 // flush
495 if(data_point_cumul.y > 0)
496 {
497 // intensity normalization
498 data_point_cumul.y *= 100.0 / m_accumulationTime;
499
500
501 // mz calibration
502 data_point_cumul.x =
503 mz_calibration_p->getMzFromTofIndex(data_point_cumul.x);
504 local_trace.push_back(data_point_cumul);
505 }
506
507 local_trace.sortX();
508 qDebug();
509 // qDebug();
510 return local_trace;
511}
512
515{
516 if(msp_mzCalibration == nullptr)
517 {
518
520 QObject::tr("ERROR in %1, %2, %3 msp_mzCalibration is null")
521 .arg(__FILE__)
522 .arg(__FUNCTION__)
523 .arg(__LINE__));
524 }
525 return msp_mzCalibration;
526}
527
528void
530 MzCalibrationInterfaceSPtr mzCalibration)
531{
532
533 if(mzCalibration == nullptr)
534 {
535
537 QObject::tr("ERROR in %1, %2, %3 msp_mzCalibration is null")
538 .arg(__FILE__)
539 .arg(__FUNCTION__)
540 .arg(__LINE__));
541 }
542 msp_mzCalibration = mzCalibration;
543}
544
545
546quint32
548{
549 quint32 max_value = 0;
550 for(quint32 i = 0; i < m_scanNumber; i++)
551 {
552 qDebug() << "m_scanNumber=" << m_scanNumber << " i=" << i;
553 std::vector<quint32> index_list = getScanIndexList(i);
554 auto it = std::max_element(index_list.begin(), index_list.end());
555 if(it != index_list.end())
556 {
557 max_value = std::max(max_value, *it);
558 }
559 }
560 return max_value;
561}
562
563std::vector<quint32>
564TimsFrameBase::getScanIndexList(std::size_t scanNum) const
565{
566 throw PappsoException(
567 QObject::tr(
568 "ERROR unable to getScanIndexList in TimsFrameBase for scan number %1")
569 .arg(scanNum));
570}
571
572
573std::vector<quint32>
574TimsFrameBase::getScanIntensities(std::size_t scanNum) const
575{
576 throw PappsoException(
577 QObject::tr(
578 "ERROR unable to getScanIntensities in TimsFrameBase for scan number %1")
579 .arg(scanNum));
580}
581
582Trace
584 std::size_t mz_index_lower_bound,
585 std::size_t mz_index_upper_bound,
586 XicExtractMethod method) const
587{
588 Trace im_trace;
589 DataPoint data_point;
590 for(quint32 i = 0; i < m_scanNumber; i++)
591 {
592 data_point.x = i;
593 data_point.y = 0;
594 qDebug() << "m_scanNumber=" << m_scanNumber << " i=" << i;
595 std::vector<quint32> index_list = getScanIndexList(i);
596 auto it_lower = std::find_if(index_list.begin(),
597 index_list.end(),
598 [mz_index_lower_bound](quint32 to_compare) {
599 if(to_compare < mz_index_lower_bound)
600 {
601 return false;
602 }
603 return true;
604 });
605
606
607 if(it_lower == index_list.end())
608 {
609 }
610 else
611 {
612
613
614 auto it_upper =
615 std::find_if(index_list.begin(),
616 index_list.end(),
617 [mz_index_upper_bound](quint32 to_compare) {
618 if(mz_index_upper_bound >= to_compare)
619 {
620 return false;
621 }
622 return true;
623 });
624 std::vector<quint32> intensity_list = getScanIntensities(i);
625 for(int j = std::distance(index_list.begin(), it_lower);
626 j < std::distance(index_list.begin(), it_upper);
627 j++)
628 {
629 if(method == XicExtractMethod::sum)
630 {
631 data_point.y += intensity_list[j];
632 }
633 else
634 {
635 data_point.y =
636 std::max((double)intensity_list[j], data_point.y);
637 }
638 }
639 }
640 im_trace.push_back(data_point);
641 }
642 qDebug();
643 return im_trace;
644}
645
646std::map<quint32, quint32> &
647TimsFrameBase::downsizeMzRawMap(std::size_t mzindex_merge_window,
648 std::map<quint32, quint32> &rawSpectrum) const
649{
650 std::map<quint32, quint32> new_spectrum;
651
652 for(auto &pair_mz_intensity : rawSpectrum)
653 {
654 quint32 mzkey = (pair_mz_intensity.first / mzindex_merge_window);
655 mzkey = (mzkey * mzindex_merge_window) + (mzindex_merge_window / 2);
656 auto it = new_spectrum.insert({mzkey, pair_mz_intensity.second});
657 if(it.second == false)
658 {
659 it.first->second += pair_mz_intensity.second;
660 }
661 }
662 rawSpectrum = new_spectrum;
663 return rawSpectrum;
664}
665
666std::vector<TimsFrameBase::RawValuePair> &
667TimsFrameBase::downsizeMzRawValuePairList(
668 std::size_t mzindex_merge_window,
669 std::vector<TimsFrameBase::RawValuePair> &rawSpectrum) const
670{
671
672 qDebug() << rawSpectrum.size();
673 std::vector<TimsFrameBase::RawValuePair> new_spectrum;
674
675 TimsFrameBase::RawValuePair current_point;
676 current_point.intensity_index = 0;
677 current_point.mz_tof_index = 0;
678 for(auto &pair_mz_intensity : rawSpectrum)
679 {
680 quint32 mzkey = (pair_mz_intensity.mz_tof_index / mzindex_merge_window);
681 mzkey = (mzkey * mzindex_merge_window) + (mzindex_merge_window / 2);
682
683 if(current_point.mz_tof_index != mzkey)
684 {
685 if(current_point.mz_tof_index > 0)
686 {
687 new_spectrum.push_back(current_point);
688 }
689
690 current_point.intensity_index = pair_mz_intensity.intensity_index;
691 current_point.mz_tof_index = mzkey;
692 }
693 else
694 {
695 current_point.intensity_index += pair_mz_intensity.intensity_index;
696 }
697 }
698
699 if(current_point.mz_tof_index > 0)
700 {
701 new_spectrum.push_back(current_point);
702 }
703 rawSpectrum = new_spectrum;
704 qDebug() << rawSpectrum.size();
705 return rawSpectrum;
706}
707// namespace pappso
708} // 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
virtual quint64 cumulateSingleScanIntensities(std::size_t scanNum) const
double getVoltageTransformation(std::size_t scanNum) const
get voltage for a given scan number
virtual std::size_t getTotalNumberOfScans() const
get the number of scans contained in this frame each scan represents an ion mobility slice
virtual Trace getIonMobilityTraceByMzIndexRange(std::size_t mz_index_lower_bound, std::size_t mz_index_upper_bound, XicExtractMethod method) const
get a mobility trace cumulating intensities inside the given mass index range
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
virtual 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
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
virtual quint64 cumulateScansIntensities(std::size_t scanNumBegin, std::size_t scanNumEnd) const
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 The intensities are NOT normalized with respe...
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...
virtual quint32 getMaximumRawMassIndex() const
get the maximum raw mass index contained in this frame
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
virtual Trace cumulateScansToTraceMzDownResolution(std::size_t mzindex_merge_window, std::size_t scanNumBegin, std::size_t scanNumEnd, quint32 &minimum_index, quint32 &maximum_index) const
cumulate spectrum given a scan number range need the binary file The intensities are normalized with ...
std::size_t getScanNumFromOneOverK0(double one_over_k0) const
get the scan number from a given 1/Ko mobility value
virtual Trace cumulateScansToTrace(std::size_t scanNumBegin, std::size_t scanNumEnd) const
cumulate spectrum given a scan number range need the binary file The intensities are normalized with ...
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
virtual Trace getMobilityScan(std::size_t scanNum, std::size_t mz_index_merge_window, double mz_range_begin, double mz_range_end, quint32 &mz_minimum_index_out, quint32 &mz_maximum_index_out) const
get a single mobility scan m/z + intensities
virtual Trace cumulateScansToTraceMzDownResolution2(std::size_t mz_index_merge_window, double mz_range_begin, double mz_range_end, std::size_t mobility_scan_begin, std::size_t mobility_scan_end, quint32 &mz_minimum_index_out, quint32 &mz_maximum_index_out) const
cumulate spectrum given a scan number range need the binary file The intensities are normalized with ...
void setMzCalibrationInterfaceSPtr(MzCalibrationInterfaceSPtr mzCalibration)
std::size_t getId() const
virtual std::vector< quint32 > getScanIntensities(std::size_t scanNum) const
get raw intensities without transformation from one scan it needs intensity normalization
virtual pappso::MassSpectrumCstSPtr getMassSpectrumCstSPtr(std::size_t scanNum) const final
get the mass spectrum corresponding to a scan number
A simple container of DataPoint instances.
Definition trace.h:148
void sortX(SortOrder sort_order=SortOrder::ascending)
Definition trace.cpp:1086
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< const MassSpectrum > MassSpectrumCstSPtr
std::shared_ptr< MassSpectrum > MassSpectrumSPtr
XicExtractMethod
Definition types.h:242
@ sum
sum of intensities
pappso_double x
Definition datapoint.h:23
pappso_double y
Definition datapoint.h:24
handle a single Bruker's TimsTof frame without binary data