libpappsomspp
Library for mass spectrometry
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
72{
73}
74
76{
77}
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
262std::vector<quint32>
263TimsFrameType1::getScanIndexList(std::size_t scanNum) const
264{
265 qDebug();
266 checkScanNum(scanNum);
267
268 std::vector<quint32> mzindex_values;
269
270 try
271 {
272 qDebug();
273
274
275 if(m_timsDataFrame.size() == 0)
276 return mzindex_values;
277 qDebug();
278
279 std::size_t size = m_scanSizeList[scanNum];
280
281 std::size_t offset = m_scanOffsetList[scanNum];
282
283 qDebug() << " offset=" << offset << " size=" << size;
284 if(size == 0)
285 return mzindex_values;
286
287 qint32 value = 0;
288 qint32 tof_index = 0;
289 // std::vector<quint32> index_list;
290 for(std::size_t i = 0; i < size; i++)
291 {
292 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
293
294 if(value < 0)
295 {
296 tof_index += -1 * value;
297 }
298 else
299 {
300 mzindex_values.push_back(tof_index);
301 tof_index++;
302 }
303 }
304
305
306 qDebug();
307 return mzindex_values;
308 }
309 catch(PappsoException &error)
310 {
311 throw pappso::PappsoException(QObject::tr("Error %1 frameId=%2 "
312 "scanNum=%3 :\n%4")
313 .arg(__FUNCTION__)
314 .arg(getId())
315 .arg(scanNum)
316 .arg(error.qwhat()));
317 }
318 qDebug();
319}
320
321std::vector<quint32>
322TimsFrameType1::getScanIntensities(std::size_t scanNum) const
323{
324
325
326 qDebug() << " scanNum=" << scanNum;
327
328 checkScanNum(scanNum);
329
330 std::vector<quint32> int_values;
331
332 try
333 {
334 qDebug();
335
336
337 if(m_timsDataFrame.size() == 0)
338 return int_values;
339 qDebug();
340
341 std::size_t size = m_scanSizeList[scanNum];
342
343 std::size_t offset = m_scanOffsetList[scanNum];
344
345 qDebug() << " offset=" << offset << " size=" << size;
346 if(size == 0)
347 return int_values;
348
349 qint32 value = 0;
350 qint32 tof_index = 0;
351 // std::vector<quint32> index_list;
352 for(std::size_t i = 0; i < size; i++)
353 {
354 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
355
356 if(value < 0)
357 {
358 tof_index += -1 * value;
359 }
360 else
361 {
362 int_values.push_back(value);
363 tof_index++;
364 }
365 }
366
367
368 qDebug();
369 return int_values;
370 }
371 catch(PappsoException &error)
372 {
373 throw pappso::PappsoException(QObject::tr("Error %1 frameId=%2 "
374 "scanNum=%3 :\n%4")
375 .arg(__FUNCTION__)
376 .arg(getId())
377 .arg(scanNum)
378 .arg(error.qwhat()));
379 }
380}
381
383TimsFrameType1::getMassSpectrumSPtr(std::size_t scanNum) const
384{
385
386 qDebug() << " scanNum=" << scanNum;
387
388 checkScanNum(scanNum);
389
390 try
391 {
392 qDebug();
393
394 pappso::MassSpectrumSPtr mass_spectrum_sptr =
395 std::make_shared<pappso::MassSpectrum>();
396 // std::vector<DataPoint>
397
398 if(m_timsDataFrame.size() == 0)
399 return mass_spectrum_sptr;
400 qDebug();
401
402 std::size_t size = m_scanSizeList[scanNum];
403
404 std::size_t offset = m_scanOffsetList[scanNum];
405
406 qDebug() << " offset=" << offset << " size=" << size;
407 if(size == 0)
408 return mass_spectrum_sptr;
409
410
411 MzCalibrationInterface *mz_calibration_p =
413
414
415 qint32 value = 0;
416 qint32 tof_index = 0;
417 // std::vector<quint32> index_list;
418 DataPoint data_point;
419 for(std::size_t i = 0; i < size; i++)
420 {
421 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
422
423 if(value < 0)
424 {
425 tof_index += -1 * value;
426 }
427 else
428 {
429 data_point.y = value;
430
431 // intensity normalization
432 data_point.y *= 100.0 / m_accumulationTime;
433
434
435 // mz calibration
436 data_point.x = mz_calibration_p->getMzFromTofIndex(tof_index);
437 mass_spectrum_sptr.get()->push_back(data_point);
438 tof_index++;
439 }
440 }
441
442
443 qDebug() << mass_spectrum_sptr.get()->toString();
444 return mass_spectrum_sptr;
445 }
446 catch(PappsoException &error)
447 {
449 QObject::tr("Error TimsFrameType1::getMassSpectrumSPtr frameId=%1 "
450 "scanNum=%2 :\n%3")
451 .arg(getId())
452 .arg(scanNum)
453 .arg(error.qwhat()));
454 }
455}
456
457
459TimsFrameType1::getRawTraceSPtr(std::size_t scanNum) const
460{
461
462 // qDebug();
463
464 pappso::TraceSPtr trace_sptr = std::make_shared<pappso::Trace>();
465 // std::vector<DataPoint>
466
467 if(m_timsDataFrame.size() == 0)
468 return trace_sptr;
469 qDebug();
470
471 std::size_t size = m_scanSizeList[scanNum];
472
473 std::size_t offset = m_scanOffsetList[scanNum];
474
475 qDebug() << " offset=" << offset << " size=" << size;
476 if(size == 0)
477 return trace_sptr;
478
479 // qDebug();
480 qint32 value = 0;
481 qint32 tof_index = 0;
482
483 // std::vector<quint32> index_list;
484 DataPoint data_point;
485 for(std::size_t i = 0; i < size; i++)
486 {
487 value = (*(qint32 *)(m_timsDataFrame.constData() + offset + (i * 4)));
488
489 if(value < 0)
490 {
491 tof_index += -1 * value;
492 }
493 else
494 {
495 data_point.y = value;
496
497 // intensity normalization
498 data_point.y *= 100.0 / m_accumulationTime;
499
500
501 // mz calibration
502 data_point.x = tof_index;
503 trace_sptr.get()->push_back(data_point);
504 tof_index++;
505 }
506 }
507
508
509 // qDebug();
510 return trace_sptr;
511}
512
513} // 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 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::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:187
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
Definition: massspectrum.h:54
pappso_double x
Definition: datapoint.h:23
pappso_double y
Definition: datapoint.h:24
handle a single Bruker's TimsTof frame type 1 compression