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 std::map<quint32, quint32> &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 auto ret = accumulate_into.insert(std::pair<quint32, quint32>(x, y));
250
251 if(ret.second == false)
252 {
253 // already existed : cumulate
254 ret.first->second += y;
255 }
256 tof_index++;
257 }
258 }
259 qDebug() << "end";
260}
261
262
263void
265 std::map<quint32, quint32> &accumulate_into,
266 quint32 accepted_tof_index_range_begin,
267 quint32 accepted_tof_index_range_end) const
268{
269 if(m_timsDataFrame.size() == 0)
270 return;
271 // checkScanNum(scanNum);
272
273
274 std::size_t size = m_scanSizeList[scanNum];
275
276 std::size_t offset = m_scanOffsetList[scanNum];
277
278 // qDebug() << "begin offset=" << offset << " size=" << size;
279 qint32 value = 0;
280 qint32 tof_index = 0;
281 for(std::size_t i = 0; i < size; i++)
282 {
283 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
284 // qDebug() << " i=" << i << " value=" << value;
285
286 if(value < 0)
287 {
288 tof_index += -1 * value;
289 }
290 else
291 {
292
293 quint32 x = tof_index;
294 quint32 y = value;
295
296
297 if(x < accepted_tof_index_range_begin)
298 {
299 tof_index++;
300 continue;
301 }
302 if(x > accepted_tof_index_range_end)
303 {
304 break;
305 }
306 auto ret = accumulate_into.insert(std::pair<quint32, quint32>(x, y));
307
308 if(ret.second == false)
309 {
310 // already existed : cumulate
311 ret.first->second += y;
312 }
313 tof_index++;
314 }
315 }
316 qDebug() << "end";
317}
318
319std::vector<quint32>
320TimsFrameType1::getScanIndexList(std::size_t scanNum) const
321{
322 qDebug();
323 checkScanNum(scanNum);
324
325 std::vector<quint32> mzindex_values;
326
327 try
328 {
329 qDebug();
330
331
332 if(m_timsDataFrame.size() == 0)
333 return mzindex_values;
334 qDebug();
335
336 std::size_t size = m_scanSizeList[scanNum];
337
338 std::size_t offset = m_scanOffsetList[scanNum];
339
340 qDebug() << " offset=" << offset << " size=" << size;
341 if(size == 0)
342 return mzindex_values;
343
344 qint32 value = 0;
345 qint32 tof_index = 0;
346 // std::vector<quint32> index_list;
347 for(std::size_t i = 0; i < size; i++)
348 {
349 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
350
351 if(value < 0)
352 {
353 tof_index += -1 * value;
354 }
355 else
356 {
357 mzindex_values.push_back(tof_index);
358 tof_index++;
359 }
360 }
361
362
363 qDebug();
364 return mzindex_values;
365 }
366 catch(PappsoException &error)
367 {
368 throw pappso::PappsoException(QObject::tr("Error %1 frameId=%2 "
369 "scanNum=%3 :\n%4")
370 .arg(__FUNCTION__)
371 .arg(getId())
372 .arg(scanNum)
373 .arg(error.qwhat()));
374 }
375 qDebug();
376}
377
378std::vector<quint32>
379TimsFrameType1::getScanIntensities(std::size_t scanNum) const
380{
381
382
383 qDebug() << " scanNum=" << scanNum;
384
385 checkScanNum(scanNum);
386
387 std::vector<quint32> int_values;
388
389 try
390 {
391 qDebug();
392
393
394 if(m_timsDataFrame.size() == 0)
395 return int_values;
396 qDebug();
397
398 std::size_t size = m_scanSizeList[scanNum];
399
400 std::size_t offset = m_scanOffsetList[scanNum];
401
402 qDebug() << " offset=" << offset << " size=" << size;
403 if(size == 0)
404 return int_values;
405
406 qint32 value = 0;
407 qint32 tof_index = 0;
408 // std::vector<quint32> index_list;
409 for(std::size_t i = 0; i < size; i++)
410 {
411 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
412
413 if(value < 0)
414 {
415 tof_index += -1 * value;
416 }
417 else
418 {
419 int_values.push_back(value);
420 tof_index++;
421 }
422 }
423
424
425 qDebug();
426 return int_values;
427 }
428 catch(PappsoException &error)
429 {
430 throw pappso::PappsoException(QObject::tr("Error %1 frameId=%2 "
431 "scanNum=%3 :\n%4")
432 .arg(__FUNCTION__)
433 .arg(getId())
434 .arg(scanNum)
435 .arg(error.qwhat()));
436 }
437}
438
440TimsFrameType1::getMassSpectrumSPtr(std::size_t scanNum) const
441{
442
443 qDebug() << " scanNum=" << scanNum;
444
445 checkScanNum(scanNum);
446
447 try
448 {
449 qDebug();
450
451 pappso::MassSpectrumSPtr mass_spectrum_sptr =
452 std::make_shared<pappso::MassSpectrum>();
453 // std::vector<DataPoint>
454
455 if(m_timsDataFrame.size() == 0)
456 return mass_spectrum_sptr;
457 qDebug();
458
459 std::size_t size = m_scanSizeList[scanNum];
460
461 std::size_t offset = m_scanOffsetList[scanNum];
462
463 qDebug() << " offset=" << offset << " size=" << size;
464 if(size == 0)
465 return mass_spectrum_sptr;
466
467
468 MzCalibrationInterface *mz_calibration_p =
470
471
472 qint32 value = 0;
473 qint32 tof_index = 0;
474 // std::vector<quint32> index_list;
475 DataPoint data_point;
476 for(std::size_t i = 0; i < size; i++)
477 {
478 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
479
480 if(value < 0)
481 {
482 tof_index += -1 * value;
483 }
484 else
485 {
486 data_point.y = value;
487
488 // intensity normalization
489 data_point.y *= 100.0 / m_accumulationTime;
490
491
492 // mz calibration
493 data_point.x = mz_calibration_p->getMzFromTofIndex(tof_index);
494 mass_spectrum_sptr.get()->push_back(data_point);
495 tof_index++;
496 }
497 }
498
499
500 qDebug() << mass_spectrum_sptr.get()->toString();
501 return mass_spectrum_sptr;
502 }
503 catch(PappsoException &error)
504 {
506 QObject::tr("Error TimsFrameType1::getMassSpectrumSPtr frameId=%1 "
507 "scanNum=%2 :\n%3")
508 .arg(getId())
509 .arg(scanNum)
510 .arg(error.qwhat()));
511 }
512}
513
514
516TimsFrameType1::getRawTraceSPtr(std::size_t scanNum) const
517{
518
519 // qDebug();
520
521 pappso::TraceSPtr trace_sptr = std::make_shared<pappso::Trace>();
522 // std::vector<DataPoint>
523
524 if(m_timsDataFrame.size() == 0)
525 return trace_sptr;
526 qDebug();
527
528 std::size_t size = m_scanSizeList[scanNum];
529
530 std::size_t offset = m_scanOffsetList[scanNum];
531
532 qDebug() << " offset=" << offset << " size=" << size;
533 if(size == 0)
534 return trace_sptr;
535
536 // qDebug();
537 qint32 value = 0;
538 qint32 tof_index = 0;
539
540 // std::vector<quint32> index_list;
541 DataPoint data_point;
542 for(std::size_t i = 0; i < size; i++)
543 {
544 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
545
546 if(value < 0)
547 {
548 tof_index += -1 * value;
549 }
550 else
551 {
552 data_point.y = value;
553
554 // intensity normalization
555 data_point.y *= 100.0 / m_accumulationTime;
556
557
558 // mz calibration
559 data_point.x = tof_index;
560 trace_sptr.get()->push_back(data_point);
561 tof_index++;
562 }
563 }
564
565
566 // qDebug();
567 return trace_sptr;
568}
569
570
571std::vector<TimsFrameType1::RawValuePair>
573 quint32 accepted_tof_index_range_begin,
574 quint32 accepted_tof_index_range_end) const
575{
576
577 // qDebug();
578
579 std::vector<TimsFrame::RawValuePair> trace_sptr;
580 // std::vector<DataPoint>
581
582 if(m_timsDataFrame.size() == 0)
583 return trace_sptr;
584 qDebug();
585
586 std::size_t size = m_scanSizeList[scanNum];
587
588 std::size_t offset = m_scanOffsetList[scanNum];
589
590 qDebug() << " offset=" << offset << " size=" << size;
591 if(size == 0)
592 return trace_sptr;
593
594 // qDebug();
595 qint32 value = 0;
596 qint32 tof_index = 0;
597
598 // std::vector<quint32> index_list;
599 TimsFrame::RawValuePair data_point;
600 for(std::size_t i = 0; i < size; i++)
601 {
602 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
603
604 if(value < 0)
605 {
606 tof_index += -1 * value;
607 }
608 else
609 {
610 data_point.intensity_index = value;
611
612 if(data_point.intensity_index < accepted_tof_index_range_begin)
613 {
614 tof_index++;
615 continue;
616 }
617 if(data_point.intensity_index > accepted_tof_index_range_end)
618 {
619 break;
620 }
621 // intensity normalization
622 data_point.intensity_index *= 100.0 / m_accumulationTime;
623
624
625 // mz calibration
626 data_point.mz_tof_index = tof_index;
627 trace_sptr.push_back(data_point);
628 tof_index++;
629 }
630 }
631
632
633 // qDebug();
634 return trace_sptr;
635}
636
637} // 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, std::map< quint32, quint32 > &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
virtual void cumulateScan(std::size_t scanNum, std::map< quint32, quint32 > &accumulate_into) const override
cumulate a scan into a map
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
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
handle a single Bruker's TimsTof frame type 1 compression