libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
timsframetype1.cpp
Go to the documentation of this file.
1/**
2 * \file pappsomspp/vendors/tims/timsframetype1.cpp
3 * \date 3/10/2021
4 * \author Olivier Langella
5 * \brief handle a single Bruker's TimsTof frame type 1 compression
6 */
7
8/*******************************************************************************
9 * Copyright (c) 2021 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
29#include "timsframetype1.h"
30#include "../../../pappsomspp/pappsoexception.h"
31#include "../../../pappsomspp/exception/exceptionoutofrange.h"
32#include "../../../pappsomspp/exception/exceptionnotimplemented.h"
33#include <QDebug>
34#include <QObject>
35#include <liblzf/lzf.h>
36#include <cerrno>
37
38
39namespace pappso
40{
42 quint32 scanNum,
43 char *p_bytes,
44 std::size_t len)
45 : TimsFrame(timsId, scanNum)
46{
47 qDebug() << timsId;
48 m_timsDataFrame.resize(len * 2);
49
50 if(p_bytes != nullptr)
51 {
52 qDebug() << timsId;
53 copyAndLzfDecompress(p_bytes, len);
54 qDebug() << timsId;
55 }
56 else
57 {
58 if(m_scanNumber == 0)
59 {
60
62 QObject::tr(
63 "TimsFrameType1::TimsFrameType1(%1,%2,nullptr,%3) FAILED")
64 .arg(m_timsId)
65 .arg(m_scanNumber)
66 .arg(len));
67 }
68 }
69}
70
74
78
79
80void
81TimsFrameType1::copyAndLzfDecompress(const char *src, std::size_t len)
82{
83
84 qDebug() << " m_scanNumber=" << m_scanNumber << " len=" << len;
85 // the start position offset for each scan and the length of the last scan
86 // copy first m_scanNumber*4 bytes in qbyte array
87 std::size_t count = (m_scanNumber + 2) * 4;
88
89 qDebug() << " count=" << count;
90 if(m_timsDataFrame.size() < (long)(count + count))
91 {
92 qDebug() << " m_timsDataFrame.size()=" << m_timsDataFrame.size();
93 m_timsDataFrame.resize(count + count);
94 }
95
96 /*
97 std::size_t decompressed_size =
98 lzfDecompressScan(src + 3687 - 8,
99 9,
100 m_timsDataFrame.data() + 3660,
101 m_timsDataFrame.size() - 3660);
102
103 qDebug() << "decompressed_size=" << decompressed_size;
104 */
105 // memcpy(m_timsDataFrame.data(), src, count);
106
107 qDebug() << "offset begin at last :" << count + 4;
108
109 // std::vector<std::size_t> compressed_len_list;
110 std::size_t offset;
111 std::size_t previous_offset = (*(quint32 *)(src));
112 qDebug() << "first offset= " << previous_offset;
113 std::size_t cumul_decompressed_size = 0;
114
115
116 for(quint32 i = 1; i <= m_scanNumber; i++)
117 {
118 offset = (*(quint32 *)(src + (i * 4)));
119
120 std::size_t compressed_size = offset - previous_offset;
121
122 qDebug() << "scan i=" << i << " previous_offset=" << previous_offset
123 << " offset=" << offset << " length=" << compressed_size;
124 // compressed_len_list.push_back(offset - previous_offset);
125 std::size_t remaining_size = m_timsDataFrame.size();
126
127 if(cumul_decompressed_size < remaining_size)
128 {
129 remaining_size = remaining_size - cumul_decompressed_size;
130 }
131 else
132 {
133 remaining_size = 0;
134 }
135 qDebug() << " remaining_size=" << remaining_size;
136 std::size_t decompressed_size =
137 lzfDecompressScan(src + previous_offset - 8,
138 compressed_size,
139 m_timsDataFrame.data() + cumul_decompressed_size,
140 remaining_size);
141
142
143 m_scanOffsetList.push_back(cumul_decompressed_size);
144 m_scanSizeList.push_back(decompressed_size / 4);
145 cumul_decompressed_size += decompressed_size;
146 qDebug() << " decompressed_size=" << decompressed_size;
147
148
149 previous_offset = offset;
150 }
151 /*
152 std::size_t last_offset = (*(quint32 *)(src + (m_scanNumber * 4)));
153 qDebug() << "last scan length :" << last_offset;
154
155 qDebug() << "last scan length bonus:"
156 << (*(quint32 *)(src + (m_scanNumber + 1 * 4)));
157
158 qDebug() << " m_scanOffsetList.size()=" << m_scanOffsetList.size()
159 << " m_scanNumber=" << m_scanNumber;
160 */
161 /*
162 throw PappsoException(
163 QObject::tr("ERROR reading TimsFrameType1 ").arg(m_timsId));
164 */
165}
166
167
168unsigned int
170 unsigned int src_len,
171 char *dest,
172 unsigned int dest_len)
173{
174 qDebug() << "src=" << src << " src_len=" << src_len
175 << " dest_len=" << dest_len;
176 if(src_len == 0)
177 return 0;
178 unsigned int decompressed_size;
179 unsigned int more_space = src_len * 2;
180 decompressed_size = lzf_decompress(src, src_len, dest, dest_len);
181 while(decompressed_size == 0)
182 {
183 qDebug() << "dest_len=" << dest_len;
184 qDebug() << "decompressed_size=" << decompressed_size;
185
186 if(errno == EINVAL)
187 {
188 throw PappsoException(
189 QObject::tr("ERROR reading TimsFrameType1 %1 TIMS binary file %2: "
190 "LZF decompression error EINVAL")
191 .arg(m_timsId));
192 }
193 else if(errno == E2BIG)
194 {
195 qDebug() << " m_timsDataFrame.size()=" << m_timsDataFrame.size()
196 << " more_space=" << more_space;
197 m_timsDataFrame.resize(m_timsDataFrame.size() + more_space);
198 dest_len += more_space;
199 qDebug();
200 decompressed_size = lzf_decompress(src, src_len, dest, dest_len);
201 }
202 else
203 {
204 break;
205 }
206 }
207 return decompressed_size;
208}
209
210std::size_t
211TimsFrameType1::getNbrPeaks(std::size_t scanNum) const
212{
213 pappso::MassSpectrumSPtr mass_spectrum_sptr = getMassSpectrumSPtr(scanNum);
214 return mass_spectrum_sptr.get()->size();
215}
216
217
218void
220 TimsDataFastMap &accumulate_into) const
221{
222 if(m_timsDataFrame.size() == 0)
223 return;
224 // checkScanNum(scanNum);
225
226
227 std::size_t size = m_scanSizeList[scanNum];
228
229 std::size_t offset = m_scanOffsetList[scanNum];
230
231 // qDebug() << "begin offset=" << offset << " size=" << size;
232 qint32 value = 0;
233 qint32 tof_index = 0;
234 for(std::size_t i = 0; i < size; i++)
235 {
236 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
237 // qDebug() << " i=" << i << " value=" << value;
238
239 if(value < 0)
240 {
241 tof_index += -1 * value;
242 }
243 else
244 {
245
246 quint32 x = tof_index;
247 quint32 y = value;
248
249 accumulate_into.accumulateIntensity(x, y);
250
251 tof_index++;
252 }
253 }
254 qDebug() << "end";
255}
256
257
258void
260 TimsDataFastMap &accumulate_into,
261 quint32 accepted_tof_index_range_begin,
262 quint32 accepted_tof_index_range_end) const
263{
264 if(m_timsDataFrame.size() == 0)
265 return;
266 // checkScanNum(scanNum);
267
268
269 std::size_t size = m_scanSizeList[scanNum];
270
271 std::size_t offset = m_scanOffsetList[scanNum];
272
273 // qDebug() << "begin offset=" << offset << " size=" << size;
274 qint32 value = 0;
275 qint32 tof_index = 0;
276 for(std::size_t i = 0; i < size; i++)
277 {
278 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
279 // qDebug() << " i=" << i << " value=" << value;
280
281 if(value < 0)
282 {
283 tof_index += -1 * value;
284 }
285 else
286 {
287
288 quint32 x = tof_index;
289 quint32 y = value;
290
291
292 if(x < accepted_tof_index_range_begin)
293 {
294 tof_index++;
295 continue;
296 }
297 if(x > accepted_tof_index_range_end)
298 {
299 break;
300 }
301 accumulate_into.accumulateIntensity(x, y);
302
303 tof_index++;
304 }
305 }
306 qDebug() << "end";
307}
308
309std::vector<quint32>
310TimsFrameType1::getScanIndexList(std::size_t scanNum) const
311{
312 qDebug();
313 checkScanNum(scanNum);
314
315 std::vector<quint32> mzindex_values;
316
317 try
318 {
319 qDebug();
320
321
322 if(m_timsDataFrame.size() == 0)
323 return mzindex_values;
324 qDebug();
325
326 std::size_t size = m_scanSizeList[scanNum];
327
328 std::size_t offset = m_scanOffsetList[scanNum];
329
330 qDebug() << " offset=" << offset << " size=" << size;
331 if(size == 0)
332 return mzindex_values;
333
334 qint32 value = 0;
335 qint32 tof_index = 0;
336 // std::vector<quint32> index_list;
337 for(std::size_t i = 0; i < size; i++)
338 {
339 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
340
341 if(value < 0)
342 {
343 tof_index += -1 * value;
344 }
345 else
346 {
347 mzindex_values.push_back(tof_index);
348 tof_index++;
349 }
350 }
351
352
353 qDebug();
354 return mzindex_values;
355 }
356 catch(PappsoException &error)
357 {
358 throw pappso::PappsoException(QObject::tr("Error %1 frameId=%2 "
359 "scanNum=%3 :\n%4")
360 .arg(__FUNCTION__)
361 .arg(getId())
362 .arg(scanNum)
363 .arg(error.qwhat()));
364 }
365 qDebug();
366}
367
368std::vector<quint32>
369TimsFrameType1::getScanIntensities(std::size_t scanNum) const
370{
371
372
373 qDebug() << " scanNum=" << scanNum;
374
375 checkScanNum(scanNum);
376
377 std::vector<quint32> int_values;
378
379 try
380 {
381 qDebug();
382
383
384 if(m_timsDataFrame.size() == 0)
385 return int_values;
386 qDebug();
387
388 std::size_t size = m_scanSizeList[scanNum];
389
390 std::size_t offset = m_scanOffsetList[scanNum];
391
392 qDebug() << " offset=" << offset << " size=" << size;
393 if(size == 0)
394 return int_values;
395
396 qint32 value = 0;
397 qint32 tof_index = 0;
398 // std::vector<quint32> index_list;
399 for(std::size_t i = 0; i < size; i++)
400 {
401 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
402
403 if(value < 0)
404 {
405 tof_index += -1 * value;
406 }
407 else
408 {
409 int_values.push_back(value);
410 tof_index++;
411 }
412 }
413
414
415 qDebug();
416 return int_values;
417 }
418 catch(PappsoException &error)
419 {
420 throw pappso::PappsoException(QObject::tr("Error %1 frameId=%2 "
421 "scanNum=%3 :\n%4")
422 .arg(__FUNCTION__)
423 .arg(getId())
424 .arg(scanNum)
425 .arg(error.qwhat()));
426 }
427}
428
430TimsFrameType1::getMassSpectrumSPtr(std::size_t scanNum) const
431{
432
433 qDebug() << " scanNum=" << scanNum;
434
435 checkScanNum(scanNum);
436
437 try
438 {
439 qDebug();
440
441 pappso::MassSpectrumSPtr mass_spectrum_sptr =
442 std::make_shared<pappso::MassSpectrum>();
443 // std::vector<DataPoint>
444
445 if(m_timsDataFrame.size() == 0)
446 return mass_spectrum_sptr;
447 qDebug();
448
449 std::size_t size = m_scanSizeList[scanNum];
450
451 std::size_t offset = m_scanOffsetList[scanNum];
452
453 qDebug() << " offset=" << offset << " size=" << size;
454 if(size == 0)
455 return mass_spectrum_sptr;
456
457
458 MzCalibrationInterface *mz_calibration_p =
460
461
462 qint32 value = 0;
463 qint32 tof_index = 0;
464 // std::vector<quint32> index_list;
465 DataPoint data_point;
466 for(std::size_t i = 0; i < size; i++)
467 {
468 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
469
470 if(value < 0)
471 {
472 tof_index += -1 * value;
473 }
474 else
475 {
476 data_point.y = value;
477
478 // intensity normalization
479 data_point.y *= 100.0 / m_accumulationTime;
480
481
482 // mz calibration
483 data_point.x = mz_calibration_p->getMzFromTofIndex(tof_index);
484 mass_spectrum_sptr.get()->push_back(data_point);
485 tof_index++;
486 }
487 }
488
489
490 qDebug() << mass_spectrum_sptr.get()->toString();
491 return mass_spectrum_sptr;
492 }
493 catch(PappsoException &error)
494 {
496 QObject::tr("Error TimsFrameType1::getMassSpectrumSPtr frameId=%1 "
497 "scanNum=%2 :\n%3")
498 .arg(getId())
499 .arg(scanNum)
500 .arg(error.qwhat()));
501 }
502}
503
504
506TimsFrameType1::getRawTraceSPtr(std::size_t scanNum) const
507{
508
509 // qDebug();
510
511 pappso::TraceSPtr trace_sptr = std::make_shared<pappso::Trace>();
512 // std::vector<DataPoint>
513
514 if(m_timsDataFrame.size() == 0)
515 return trace_sptr;
516 qDebug();
517
518 std::size_t size = m_scanSizeList[scanNum];
519
520 std::size_t offset = m_scanOffsetList[scanNum];
521
522 qDebug() << " offset=" << offset << " size=" << size;
523 if(size == 0)
524 return trace_sptr;
525
526 // qDebug();
527 qint32 value = 0;
528 qint32 tof_index = 0;
529
530 // std::vector<quint32> index_list;
531 DataPoint data_point;
532 for(std::size_t i = 0; i < size; i++)
533 {
534 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
535
536 if(value < 0)
537 {
538 tof_index += -1 * value;
539 }
540 else
541 {
542 data_point.y = value;
543
544 // intensity normalization
545 data_point.y *= 100.0 / m_accumulationTime;
546
547
548 // mz calibration
549 data_point.x = tof_index;
550 trace_sptr.get()->push_back(data_point);
551 tof_index++;
552 }
553 }
554
555
556 // qDebug();
557 return trace_sptr;
558}
559
560
561std::vector<TimsFrameType1::RawValuePair>
563 quint32 accepted_tof_index_range_begin,
564 quint32 accepted_tof_index_range_end) const
565{
566
567 // qDebug();
568
569 std::vector<TimsFrame::RawValuePair> trace_sptr;
570 // std::vector<DataPoint>
571
572 if(m_timsDataFrame.size() == 0)
573 return trace_sptr;
574 qDebug();
575
576 std::size_t size = m_scanSizeList[scanNum];
577
578 std::size_t offset = m_scanOffsetList[scanNum];
579
580 qDebug() << " offset=" << offset << " size=" << size;
581 if(size == 0)
582 return trace_sptr;
583
584 // qDebug();
585 qint32 value = 0;
586 qint32 tof_index = 0;
587
588 // std::vector<quint32> index_list;
589 TimsFrame::RawValuePair data_point;
590 for(std::size_t i = 0; i < size; i++)
591 {
592 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
593
594 if(value < 0)
595 {
596 tof_index += -1 * value;
597 }
598 else
599 {
600 data_point.intensity_index = value;
601
602 if(data_point.intensity_index < accepted_tof_index_range_begin)
603 {
604 tof_index++;
605 continue;
606 }
607 if(data_point.intensity_index > accepted_tof_index_range_end)
608 {
609 break;
610 }
611 // intensity normalization
612 data_point.intensity_index *= 100.0 / m_accumulationTime;
613
614
615 // mz calibration
616 data_point.mz_tof_index = tof_index;
617 trace_sptr.push_back(data_point);
618 tof_index++;
619 }
620 }
621
622
623 // qDebug();
624 return trace_sptr;
625}
626
627} // namespace pappso
virtual double getMzFromTofIndex(quint32 tof_index)=0
get m/z from time of flight raw index
virtual const QString & qwhat() const
double m_accumulationTime
accumulation time in milliseconds
quint32 m_scanNumber
total number of scans contained in this frame
std::size_t m_timsId
Tims frame database id (the SQL identifier of this frame)
virtual const MzCalibrationInterfaceSPtr & getMzCalibrationInterfaceSPtr() const final
get the MzCalibration model to compute mz and TOF for this frame
bool checkScanNum(std::size_t scanNum) const
check that this scan number exists
std::size_t getId() const
virtual void cumulateScan2(std::size_t scanNum, TimsDataFastMap &accumulate_into, quint32 accepted_tof_index_range_begin, quint32 accepted_tof_index_range_end) const override
virtual std::vector< quint32 > getScanIndexList(std::size_t scanNum) const override
get raw index list for one given scan index are not TOF nor m/z, just index on digitizer
std::vector< std::size_t > m_scanSizeList
TimsFrameType1(std::size_t timsId, quint32 scanNum, char *p_bytes, std::size_t len)
void copyAndLzfDecompress(const char *src, std::size_t len)
copy buffer header and lzf decompress each scan for tims compression type 1
virtual std::vector< RawValuePair > getRawValuePairList(std::size_t scanNum, quint32 accepted_tof_index_range_begin, quint32 accepted_tof_index_range_end) const override
get the raw index tof_index and intensities (normalized)
virtual std::size_t getNbrPeaks(std::size_t scanNum) const override
get the number of peaks in this spectrum need the binary file
unsigned int lzfDecompressScan(const char *src, unsigned int src_len, char *dest, unsigned int dest_len)
decompress a single LZF compressed scan buffer
virtual pappso::MassSpectrumSPtr getMassSpectrumSPtr(std::size_t scanNum) const override
get the mass spectrum corresponding to a scan number
virtual std::vector< quint32 > getScanIntensities(std::size_t scanNum) const override
get raw intensities without transformation from one scan it needs intensity normalization
virtual void cumulateScan(std::size_t scanNum, TimsDataFastMap &accumulate_into) const override
cumulate a scan into a map
std::vector< std::size_t > m_scanOffsetList
virtual pappso::TraceSPtr getRawTraceSPtr(std::size_t scanNum) const override
get the raw index tof_index and intensities (normalized)
QByteArray m_timsDataFrame
Definition timsframe.h:279
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition aa.cpp:39
std::shared_ptr< Trace > TraceSPtr
Definition trace.h:135
std::shared_ptr< MassSpectrum > MassSpectrumSPtr
pappso_double x
Definition datapoint.h:23
pappso_double y
Definition datapoint.h:24
replacement for std::map
std::size_t accumulateIntensity(quint32 tofIndex, std::size_t intensity)
accumulates intesity for the given tof index
handle a single Bruker's TimsTof frame type 1 compression