libpappsomspp
Library for mass spectrometry
timsdata.cpp
Go to the documentation of this file.
1/**
2 * \file pappsomspp/vendors/tims/timsdata.cpp
3 * \date 27/08/2019
4 * \author Olivier Langella
5 * \brief main Tims data handler
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
28#include "timsdata.h"
29#include "../../exception/exceptionnotfound.h"
30#include "../../exception/exceptioninterrupted.h"
31#include "../../processing/combiners/tracepluscombiner.h"
32#include "../../processing/filters/filtertriangle.h"
33#include "../../processing/filters/filtersuitestring.h"
34#include <QDebug>
35#include <QSqlError>
36#include <QSqlQuery>
37#include <QSqlRecord>
38#include <QMutexLocker>
39#include <QThread>
40#include <set>
41#include <QtConcurrent>
42
43namespace pappso
44{
45
46TimsData::TimsData(QDir timsDataDirectory)
47 : m_timsDataDirectory(timsDataDirectory)
48{
49
50 qDebug() << "Start of construction of TimsData";
52 if(!m_timsDataDirectory.exists())
53 {
54 throw PappsoException(
55 QObject::tr("ERROR TIMS data directory %1 not found")
56 .arg(m_timsDataDirectory.absolutePath()));
57 }
58
59 if(!QFileInfo(m_timsDataDirectory.absoluteFilePath("analysis.tdf")).exists())
60 {
61
62 throw PappsoException(
63 QObject::tr("ERROR TIMS data directory, %1 sqlite file not found")
64 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf")));
65 }
66
67 // Open the database
68 QSqlDatabase qdb = openDatabaseConnection();
69
70
71 QSqlQuery q(qdb);
72 if(!q.exec("select Key, Value from GlobalMetadata where "
73 "Key='TimsCompressionType';"))
74 {
75
76 qDebug();
77 throw PappsoException(
78 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
79 "command %2:\n%3\n%4\n%5")
80 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
81 .arg(q.lastQuery())
82 .arg(q.lastError().databaseText())
83 .arg(q.lastError().driverText())
84 .arg(q.lastError().nativeErrorCode()));
85 }
86
87
88 int compression_type = 0;
89 if(q.next())
90 {
91 compression_type = q.value(1).toInt();
92 }
93 qDebug() << " compression_type=" << compression_type;
95 QFileInfo(m_timsDataDirectory.absoluteFilePath("analysis.tdf_bin")),
96 compression_type);
97
98 qDebug();
99
100 // get number of precursors
102 if(!q.exec("SELECT COUNT( DISTINCT Id) FROM Precursors;"))
103 {
104 m_hasPrecursorTable = false;
105 }
106 else
107 {
108 m_hasPrecursorTable = true;
109 if(q.next())
110 {
111 m_totalNumberOfPrecursors = q.value(0).toLongLong();
112 }
113 }
114
115
117
118 // get number of scans
119 if(!q.exec("SELECT SUM(NumScans),COUNT(Id) FROM Frames"))
120 {
121 qDebug();
122 throw PappsoException(
123 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
124 "command %2:\n%3\n%4\n%5")
125 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
126 .arg(q.lastQuery())
127 .arg(qdb.lastError().databaseText())
128 .arg(qdb.lastError().driverText())
129 .arg(qdb.lastError().nativeErrorCode()));
130 }
131 if(q.next())
132 {
133 m_totalNumberOfScans = q.value(0).toLongLong();
134 m_totalNumberOfFrames = q.value(1).toLongLong();
135 }
136
137 if(!q.exec("select * from MzCalibration;"))
138 {
139 qDebug();
140 throw PappsoException(
141 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
142 "command %2:\n%3\n%4\n%5")
143 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
144 .arg(q.lastQuery())
145 .arg(q.lastError().databaseText())
146 .arg(q.lastError().driverText())
147 .arg(q.lastError().nativeErrorCode()));
148 }
149
150 while(q.next())
151 {
152 QSqlRecord record = q.record();
154 std::pair<int, QSqlRecord>(record.value(0).toInt(), record));
155 }
156
157 // m_mapTimsCalibrationRecord
158
159 if(!q.exec("select * from TimsCalibration;"))
160 {
161 qDebug();
162 throw PappsoException(
163 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
164 "command %2:\n%3\n%4\n%5")
165 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
166 .arg(q.lastQuery())
167 .arg(q.lastError().databaseText())
168 .arg(q.lastError().driverText())
169 .arg(q.lastError().nativeErrorCode()));
170 }
171 while(q.next())
172 {
173 QSqlRecord record = q.record();
175 std::pair<int, QSqlRecord>(record.value(0).toInt(), record));
176 }
177
178
179 // store frames
180 if(!q.exec("select Frames.TimsId, Frames.AccumulationTime, " // 1
181 "Frames.MzCalibration, " // 2
182 "Frames.T1, Frames.T2, " // 4
183 "Frames.Time, Frames.MsMsType, Frames.TimsCalibration, " // 7
184 "Frames.Id " // 8
185 " FROM Frames;"))
186 {
187 qDebug();
188 throw PappsoException(
189 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
190 "command %2:\n%3\n%4\n%5")
191 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
192 .arg(q.lastQuery())
193 .arg(q.lastError().databaseText())
194 .arg(q.lastError().driverText())
195 .arg(q.lastError().nativeErrorCode()));
196 }
197
199 while(q.next())
200 {
201 QSqlRecord record = q.record();
202 TimsFrameRecord &frame_record =
203 m_mapFramesRecord[record.value(8).toULongLong()];
204
205 frame_record.tims_offset = record.value(0).toULongLong();
206 frame_record.accumulation_time = record.value(1).toDouble();
207 frame_record.mz_calibration_id = record.value(2).toULongLong();
208 frame_record.frame_t1 = record.value(3).toDouble();
209 frame_record.frame_t2 = record.value(4).toDouble();
210 frame_record.frame_time = record.value(5).toDouble();
211 frame_record.msms_type = record.value(6).toInt();
212 frame_record.tims_calibration_id = record.value(7).toULongLong();
213 }
214
215 mcsp_ms2Filter = std::make_shared<pappso::FilterSuiteString>(
216 "chargeDeconvolution|0.02dalton mzExclusion|0.01dalton");
217
218
219 std::shared_ptr<FilterTriangle> ms1filter =
220 std::make_shared<FilterTriangle>();
221 ms1filter.get()->setTriangleSlope(50, 0.01);
222 mcsp_ms1Filter = ms1filter;
223 qDebug();
224}
225
226void
227TimsData::setMonoThread(bool is_mono_thread)
228{
229 m_isMonoThread = is_mono_thread;
230}
231
232QSqlDatabase
234{
235 QString database_connection_name = QString("%1_%2")
236 .arg(m_timsDataDirectory.absolutePath())
237 .arg((quintptr)QThread::currentThread());
238 // Open the database
239 QSqlDatabase qdb = QSqlDatabase::database(database_connection_name);
240 if(!qdb.isValid())
241 {
242 qDebug() << database_connection_name;
243 qdb = QSqlDatabase::addDatabase("QSQLITE", database_connection_name);
244 qdb.setDatabaseName(m_timsDataDirectory.absoluteFilePath("analysis.tdf"));
245 }
246
247
248 if(!qdb.open())
249 {
250 qDebug();
251 throw PappsoException(
252 QObject::tr("ERROR opening TIMS sqlite database file %1, database name "
253 "%2 :\n%3\n%4\n%5")
254 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
255 .arg(database_connection_name)
256 .arg(qdb.lastError().databaseText())
257 .arg(qdb.lastError().driverText())
258 .arg(qdb.lastError().nativeErrorCode()));
259 }
260 return qdb;
261}
262
263TimsData::TimsData([[maybe_unused]] const pappso::TimsData &other)
264{
265 qDebug();
266}
267
269{
270 // m_qdb.close();
271 if(mpa_timsBinDec != nullptr)
272 {
273 delete mpa_timsBinDec;
274 }
275 if(mpa_mzCalibrationStore != nullptr)
276 {
278 }
279}
280
281void
283{
284 m_builtinMs2Centroid = centroid;
285}
286
287bool
289{
291}
292
293void
295{
296 qDebug();
297 QSqlDatabase qdb = openDatabaseConnection();
298
299 QSqlQuery q =
300 qdb.exec(QString("SELECT Id, NumScans FROM "
301 "Frames ORDER BY Id"));
302 if(q.lastError().isValid())
303 {
304
305 throw PappsoException(
306 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
307 "command %2:\n%3\n%4\n%5")
308 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
309 .arg(q.lastQuery())
310 .arg(qdb.lastError().databaseText())
311 .arg(qdb.lastError().driverText())
312 .arg(qdb.lastError().nativeErrorCode()));
313 }
314 TimsFrameSPtr tims_frame;
315 bool index_found = false;
316 std::size_t timsId;
317 /** @brief number of scans in mobility dimension (number of TOF scans)
318 */
319 std::size_t numberScans;
320 std::size_t cumulScans = 0;
321 while(q.next() && (!index_found))
322 {
323 timsId = q.value(0).toULongLong();
324 numberScans = q.value(1).toULongLong();
325
326 // qDebug() << timsId;
327
329 std::pair<std::size_t, std::size_t>((cumulScans / 1000),
330 m_frameIdDescrList.size()));
331
332 m_frameIdDescrList.push_back({timsId, numberScans, cumulScans});
333 cumulScans += numberScans;
334 }
335 qDebug();
336}
337
338std::pair<std::size_t, std::size_t>
339TimsData::getScanCoordinateFromRawIndex(std::size_t raw_index) const
340{
341
342 std::size_t fast_access = raw_index / 1000;
343 qDebug() << " fast_access=" << fast_access;
344 auto map_it = m_thousandIndexToFrameIdDescrListIndex.find(fast_access);
346 {
347 throw ExceptionNotFound(
348 QObject::tr("ERROR raw index %1 not found (fast_access)")
349 .arg(raw_index));
350 }
351 std::size_t start_point_index = map_it->second;
352 while((start_point_index > 0) &&
353 (m_frameIdDescrList[start_point_index].m_cumulSize > raw_index))
354 {
355 start_point_index--;
356 }
357 for(std::size_t i = start_point_index; i < m_frameIdDescrList.size(); i++)
358 {
359
360 if(raw_index <
361 (m_frameIdDescrList[i].m_cumulSize + m_frameIdDescrList[i].m_size))
362 {
363 return std::pair<std::size_t, std::size_t>(
364 m_frameIdDescrList[i].m_frameId,
365 raw_index - m_frameIdDescrList[i].m_cumulSize);
366 }
367 }
368
369 throw ExceptionNotFound(
370 QObject::tr("ERROR raw index %1 not found").arg(raw_index));
371}
372
373
374std::size_t
376 std::size_t scan_num) const
377{
378
379 for(auto frameDescr : m_frameIdDescrList)
380 {
381 if(frameDescr.m_frameId == frame_id)
382 {
383 return frameDescr.m_cumulSize + scan_num;
384 }
385 }
386
387 throw ExceptionNotFound(
388 QObject::tr("ERROR raw index with frame=%1 scan=%2 not found")
389 .arg(frame_id)
390 .arg(scan_num));
391}
392
393/** @brief get a mass spectrum given its spectrum index
394 * @param raw_index a number begining at 0, corresponding to a Tims Scan in
395 * the order they lies in the binary data file
396 */
399{
400
401 qDebug() << " raw_index=" << raw_index;
402 try
403 {
404 auto coordinate = getScanCoordinateFromRawIndex(raw_index);
405 return getMassSpectrumCstSPtr(coordinate.first, coordinate.second);
406 }
407 catch(PappsoException &error)
408 {
409 throw PappsoException(
410 QObject::tr("Error TimsData::getMassSpectrumCstSPtrByRawIndex "
411 "raw_index=%1 :\n%2")
412 .arg(raw_index)
413 .arg(error.qwhat()));
414 }
415}
416
417
420{
421
422 qDebug() << " timsId=" << timsId;
423
424 const TimsFrameRecord &frame_record = m_mapFramesRecord[timsId];
425 if(timsId > m_totalNumberOfScans)
426 {
427 throw ExceptionNotFound(
428 QObject::tr("ERROR Frames database id %1 not found").arg(timsId));
429 }
430 TimsFrameBaseSPtr tims_frame;
431
432
433 tims_frame = std::make_shared<TimsFrameBase>(
434 TimsFrameBase(timsId, frame_record.tims_offset));
435
436 auto it_map_record =
438 if(it_map_record != m_mapMzCalibrationRecord.end())
439 {
440
441 double T1_frame = frame_record.frame_t1; // Frames.T1
442 double T2_frame = frame_record.frame_t2; // Frames.T2
443
444
445 tims_frame.get()->setMzCalibrationInterfaceSPtr(
447 T1_frame, T2_frame, it_map_record->second));
448 }
449 else
450 {
451 throw ExceptionNotFound(
452 QObject::tr("ERROR MzCalibration database id %1 not found")
453 .arg(frame_record.mz_calibration_id));
454 }
455
456 tims_frame.get()->setAccumulationTime(frame_record.accumulation_time);
457
458 tims_frame.get()->setTime(frame_record.frame_time);
459 tims_frame.get()->setMsMsType(frame_record.msms_type);
460
461
462 auto it_map_record_tims_calibration =
464 if(it_map_record_tims_calibration != m_mapTimsCalibrationRecord.end())
465 {
466
467 tims_frame.get()->setTimsCalibration(
468 it_map_record_tims_calibration->second.value(1).toInt(),
469 it_map_record_tims_calibration->second.value(2).toDouble(),
470 it_map_record_tims_calibration->second.value(3).toDouble(),
471 it_map_record_tims_calibration->second.value(4).toDouble(),
472 it_map_record_tims_calibration->second.value(5).toDouble(),
473 it_map_record_tims_calibration->second.value(6).toDouble(),
474 it_map_record_tims_calibration->second.value(7).toDouble(),
475 it_map_record_tims_calibration->second.value(8).toDouble(),
476 it_map_record_tims_calibration->second.value(9).toDouble(),
477 it_map_record_tims_calibration->second.value(10).toDouble(),
478 it_map_record_tims_calibration->second.value(11).toDouble());
479 }
480 else
481 {
482 throw ExceptionNotFound(
483 QObject::tr("ERROR TimsCalibration database id %1 not found")
484 .arg(frame_record.tims_calibration_id));
485 }
486
487 return tims_frame;
488}
489
490std::vector<std::size_t>
491TimsData::getTimsMS1FrameIdRange(double rt_begin, double rt_end) const
492{
493
494 qDebug() << " rt_begin=" << rt_begin << " rt_end=" << rt_end;
495 if(rt_begin < 0)
496 rt_begin = 0;
497 std::vector<std::size_t> tims_frameid_list;
498 QSqlDatabase qdb = openDatabaseConnection();
499 QSqlQuery q = qdb.exec(QString("SELECT Frames.Id FROM Frames WHERE "
500 "Frames.MsMsType=0 AND (Frames.Time>=%1) AND "
501 "(Frames.Time<=%2) ORDER BY Frames.Time;")
502 .arg(rt_begin)
503 .arg(rt_end));
504 if(q.lastError().isValid())
505 {
506
507 throw PappsoException(
508 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
509 "executing SQL "
510 "command %3:\n%4\n%5\n%6")
511 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
512 .arg(qdb.databaseName())
513 .arg(q.lastQuery())
514 .arg(qdb.lastError().databaseText())
515 .arg(qdb.lastError().driverText())
516 .arg(qdb.lastError().nativeErrorCode()));
517 }
518 while(q.next())
519 {
520
521 tims_frameid_list.push_back(q.value(0).toULongLong());
522 }
523 return tims_frameid_list;
524}
525
528{
529
530 qDebug() << " timsId=" << timsId
531 << " m_mapFramesRecord.size()=" << m_mapFramesRecord.size();
532
533 /*
534 for(auto pair_i : m_mapFramesRecord)
535 {
536
537 qDebug() << " pair_i=" << pair_i.first;
538 }
539 */
540
541 const TimsFrameRecord &frame_record = m_mapFramesRecord[timsId];
542 if(timsId > m_totalNumberOfScans)
543 {
544 throw ExceptionNotFound(
545 QObject::tr("ERROR Frames database id %1 not found").arg(timsId));
546 }
547
548 TimsFrameSPtr tims_frame;
549
550
551 // QMutexLocker lock(&m_mutex);
552 tims_frame =
554 // lock.unlock();
555
556 qDebug();
557 auto it_map_record =
559 if(it_map_record != m_mapMzCalibrationRecord.end())
560 {
561
562 double T1_frame = frame_record.frame_t1; // Frames.T1
563 double T2_frame = frame_record.frame_t2; // Frames.T2
564
565
566 tims_frame.get()->setMzCalibrationInterfaceSPtr(
568 T1_frame, T2_frame, it_map_record->second));
569 }
570 else
571 {
572 throw ExceptionNotFound(
573 QObject::tr("ERROR MzCalibration database id %1 not found")
574 .arg(frame_record.mz_calibration_id));
575 }
576
577 tims_frame.get()->setAccumulationTime(frame_record.accumulation_time);
578
579 tims_frame.get()->setTime(frame_record.frame_time);
580 tims_frame.get()->setMsMsType(frame_record.msms_type);
581
582 qDebug();
583 auto it_map_record_tims_calibration =
585 if(it_map_record_tims_calibration != m_mapTimsCalibrationRecord.end())
586 {
587
588 tims_frame.get()->setTimsCalibration(
589 it_map_record_tims_calibration->second.value(1).toInt(),
590 it_map_record_tims_calibration->second.value(2).toDouble(),
591 it_map_record_tims_calibration->second.value(3).toDouble(),
592 it_map_record_tims_calibration->second.value(4).toDouble(),
593 it_map_record_tims_calibration->second.value(5).toDouble(),
594 it_map_record_tims_calibration->second.value(6).toDouble(),
595 it_map_record_tims_calibration->second.value(7).toDouble(),
596 it_map_record_tims_calibration->second.value(8).toDouble(),
597 it_map_record_tims_calibration->second.value(9).toDouble(),
598 it_map_record_tims_calibration->second.value(10).toDouble(),
599 it_map_record_tims_calibration->second.value(11).toDouble());
600 }
601 else
602 {
603 throw ExceptionNotFound(
604 QObject::tr("ERROR TimsCalibration database id %1 not found")
605 .arg(frame_record.tims_calibration_id));
606 }
607 qDebug();
608 return tims_frame;
609}
610
611
613TimsData::getMassSpectrumCstSPtr(std::size_t timsId, std::size_t scanNum)
614{
615 qDebug() << " timsId=" << timsId << " scanNum=" << scanNum;
617
618 return frame->getMassSpectrumCstSPtr(scanNum);
619}
620
621
622std::size_t
624{
626}
627
628
629std::size_t
631{
633}
634
635
636std::size_t
638{
640}
641
642std::vector<std::size_t>
644 double mz_val,
645 double rt_sec,
646 double k0)
647{
648 std::vector<std::size_t> precursor_ids;
649 std::vector<std::vector<double>> ids;
650
651 QSqlDatabase qdb = openDatabaseConnection();
652 QSqlQuery q = qdb.exec(
653 QString(
654 "SELECT Frames.Time, Precursors.MonoisotopicMz, Precursors.Charge, "
655 "Precursors.Id, Frames.Id, PasefFrameMsMsInfo.ScanNumBegin, "
656 "PasefFrameMsMsInfo.scanNumEnd "
657 "FROM Frames "
658 "INNER JOIN PasefFrameMsMsInfo ON Frames.Id = PasefFrameMsMsInfo.Frame "
659 "INNER JOIN Precursors ON PasefFrameMsMsInfo.Precursor = Precursors.Id "
660 "WHERE Precursors.Charge == %1 "
661 "AND Precursors.MonoisotopicMz > %2 -0.01 "
662 "AND Precursors.MonoisotopicMz < %2 +0.01 "
663 "AND Frames.Time >= %3 -1 "
664 "AND Frames.Time < %3 +1; ")
665 .arg(charge)
666 .arg(mz_val)
667 .arg(rt_sec));
668 if(q.lastError().isValid())
669 {
670
671 throw PappsoException(
672 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
673 "executing SQL "
674 "command %3:\n%4\n%5\n%6")
675 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
676 .arg(qdb.databaseName())
677 .arg(q.lastQuery())
678 .arg(qdb.lastError().databaseText())
679 .arg(qdb.lastError().driverText())
680 .arg(qdb.lastError().nativeErrorCode()));
681 }
682 while(q.next())
683 {
684 // qInfo() << q.value(0).toDouble() << q.value(1).toDouble()
685 // << q.value(2).toDouble() << q.value(3).toDouble();
686
687 std::vector<double> sql_values;
688 sql_values.push_back(q.value(4).toDouble()); // frame id
689 sql_values.push_back(q.value(3).toDouble()); // precursor id
690 sql_values.push_back(q.value(5).toDouble()); // scan num begin
691 sql_values.push_back(q.value(6).toDouble()); // scan num end
692 sql_values.push_back(q.value(1).toDouble()); // mz_value
693
694 ids.push_back(sql_values);
695
696
697 if(std::find(precursor_ids.begin(),
698 precursor_ids.end(),
699 q.value(3).toDouble()) == precursor_ids.end())
700 {
701 precursor_ids.push_back(q.value(3).toDouble());
702 }
703 }
704
705 if(precursor_ids.size() > 1)
706 {
707 // std::vector<std::size_t> precursor_ids_ko =
708 // getMatchPrecursorIdByKo(ids, values[3]);
709 if(precursor_ids.size() > 1)
710 {
711 precursor_ids = getClosestPrecursorIdByMz(ids, k0);
712 }
713 return precursor_ids;
714 }
715 else
716 {
717 return precursor_ids;
718 }
719}
720
721std::vector<std::size_t>
722TimsData::getMatchPrecursorIdByKo(std::vector<std::vector<double>> ids,
723 double ko_value)
724{
725 std::vector<std::size_t> precursor_id;
726 for(std::vector<double> index : ids)
727 {
728 auto coordinate = getScanCoordinateFromRawIndex(index[0]);
729
730 TimsFrameBaseCstSPtr tims_frame;
731 tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
732
733 double bko = tims_frame.get()->getOneOverK0Transformation(index[2]);
734 double eko = tims_frame.get()->getOneOverK0Transformation(index[3]);
735
736 // qInfo() << "diff" << (bko + eko) / 2;
737 double mean_ko = (bko + eko) / 2;
738
739 if(mean_ko > ko_value - 0.1 && mean_ko < ko_value + 0.1)
740 {
741 precursor_id.push_back(index[1]);
742 }
743 }
744 return precursor_id;
745}
746
747std::vector<std::size_t>
748TimsData::getClosestPrecursorIdByMz(std::vector<std::vector<double>> ids,
749 double mz_value)
750{
751 std::vector<std::size_t> best_precursor;
752 double best_value = 1;
753 int count = 1;
754 int best_val_position = 0;
755
756 for(std::vector<double> values : ids)
757 {
758 double new_val = abs(mz_value - values[4]);
759 if(new_val < best_value)
760 {
761 best_value = new_val;
762 best_val_position = count;
763 }
764 count++;
765 }
766 best_precursor.push_back(ids[best_val_position][1]);
767 return best_precursor;
768}
769
770
771unsigned int
772TimsData::getMsLevelBySpectrumIndex(std::size_t spectrum_index)
773{
774 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
775 auto tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
776 return tims_frame.get()->getMsLevel();
777}
778
779
780void
782 const MsRunIdCstSPtr &msrun_id,
783 QualifiedMassSpectrum &mass_spectrum,
784 std::size_t spectrum_index,
785 bool want_binary_data)
786{
787 try
788 {
789 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
790 TimsFrameBaseCstSPtr tims_frame;
791 if(want_binary_data)
792 {
793 tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
794 }
795 else
796 {
797 tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
798 }
799 MassSpectrumId spectrum_id;
800
801 spectrum_id.setSpectrumIndex(spectrum_index);
802 spectrum_id.setMsRunId(msrun_id);
803 spectrum_id.setNativeId(QString("frame=%1 scan=%2 index=%3")
804 .arg(coordinate.first)
805 .arg(coordinate.second)
806 .arg(spectrum_index));
807
808 mass_spectrum.setMassSpectrumId(spectrum_id);
809
810 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
811 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
812
813 mass_spectrum.setDtInMilliSeconds(
814 tims_frame.get()->getDriftTime(coordinate.second));
815 // 1/K0
816 mass_spectrum.setParameterValue(
818 tims_frame.get()->getOneOverK0Transformation(coordinate.second));
819
820 mass_spectrum.setEmptyMassSpectrum(true);
821 if(want_binary_data)
822 {
823 mass_spectrum.setMassSpectrumSPtr(
824 tims_frame.get()->getMassSpectrumSPtr(coordinate.second));
825 if(mass_spectrum.size() > 0)
826 {
827 mass_spectrum.setEmptyMassSpectrum(false);
828 }
829 }
830 else
831 {
832 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
833 //{
834 mass_spectrum.setEmptyMassSpectrum(false);
835 // }
836 }
837 if(tims_frame.get()->getMsLevel() > 1)
838 {
839
840 auto spectrum_descr = getSpectrumDescrWithScanCoordinate(coordinate);
841 if(spectrum_descr.precursor_id > 0)
842 {
843
844 mass_spectrum.appendPrecursorIonData(
845 spectrum_descr.precursor_ion_data);
846
847
848 MassSpectrumId spectrum_id;
849 std::size_t prec_spectrum_index = getRawIndexFromCoordinate(
850 spectrum_descr.parent_frame, coordinate.second);
851
852 mass_spectrum.setPrecursorSpectrumIndex(prec_spectrum_index);
853 mass_spectrum.setPrecursorNativeId(
854 QString("frame=%1 scan=%2 index=%3")
855 .arg(spectrum_descr.parent_frame)
856 .arg(coordinate.second)
857 .arg(prec_spectrum_index));
858
859 mass_spectrum.setParameterValue(
861 spectrum_descr.isolationMz);
862 mass_spectrum.setParameterValue(
864 spectrum_descr.isolationWidth);
865
866 mass_spectrum.setParameterValue(
868 spectrum_descr.collisionEnergy);
869 mass_spectrum.setParameterValue(
871 (quint64)spectrum_descr.precursor_id);
872 }
873 }
874 }
875 catch(PappsoException &error)
876 {
878 QObject::tr("Error TimsData::getQualifiedMassSpectrumByRawIndex "
879 "spectrum_index=%1 :\n%2")
880 .arg(spectrum_index)
881 .arg(error.qwhat()));
882 }
883}
884
885
886Trace
888{
889 // In the Frames table, each frame has a record describing the
890 // SummedIntensities for all the mobility spectra.
891
892
893 MapTrace rt_tic_map_trace;
894
895 using Pair = std::pair<double, double>;
896 using Map = std::map<double, double>;
897 using Iterator = Map::iterator;
898
899
900 QSqlDatabase qdb = openDatabaseConnection();
901 QSqlQuery q =
902 qdb.exec(QString("SELECT Time, SummedIntensities "
903 "FROM Frames WHERE MsMsType = 0 "
904 "ORDER BY Time;"));
905
906 if(q.lastError().isValid())
907 {
908
909 throw PappsoException(
910 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
911 "executing SQL "
912 "command %3:\n%4\n%5\n%6")
913 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
914 .arg(qdb.databaseName())
915 .arg(q.lastQuery())
916 .arg(qdb.lastError().databaseText())
917 .arg(qdb.lastError().driverText())
918 .arg(qdb.lastError().nativeErrorCode()));
919 }
920
921 while(q.next())
922 {
923
924 bool ok = false;
925
926 int cumulated_results = 2;
927
928 double rt = q.value(0).toDouble(&ok);
929 cumulated_results -= ok;
930
931 double sumY = q.value(1).toDouble(&ok);
932 cumulated_results -= ok;
933
934 if(cumulated_results)
935 {
936 throw PappsoException(
937 QObject::tr(
938 "ERROR in TIMS sqlite database file: could not read either the "
939 "retention time or the summed intensities (%1, database name "
940 "%2, "
941 "executing SQL "
942 "command %3:\n%4\n%5\n%6")
943 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
944 .arg(qdb.databaseName())
945 .arg(q.lastQuery())
946 .arg(qdb.lastError().databaseText())
947 .arg(qdb.lastError().driverText())
948 .arg(qdb.lastError().nativeErrorCode()));
949 }
950
951 // Try to insert value sumY at key rt.
952 std::pair<Iterator, bool> res = rt_tic_map_trace.insert(Pair(rt, sumY));
953
954 if(!res.second)
955 {
956 // One other same rt value was seen already (like in ion mobility
957 // mass spectrometry, for example). Only increment the y value.
958
959 res.first->second += sumY;
960 }
961 }
962
963 // qDebug().noquote() << "The TIC chromatogram:\n"
964 //<< rt_tic_map_trace.toTrace().toString();
965
966 return rt_tic_map_trace.toTrace();
967}
968
969
970void
972 const MsRunIdCstSPtr &msrun_id,
973 QualifiedMassSpectrum &mass_spectrum,
974 const SpectrumDescr &spectrum_descr,
975 bool want_binary_data)
976{
977
978 qDebug() << " ms2_index=" << spectrum_descr.ms2_index
979 << " precursor_index=" << spectrum_descr.precursor_id;
980
981 TracePlusCombiner combiner;
982 MapTrace combiner_result;
983
984 try
985 {
986 mass_spectrum.setMsLevel(1);
987 mass_spectrum.setPrecursorSpectrumIndex(0);
988 mass_spectrum.setEmptyMassSpectrum(true);
989
990 MassSpectrumId spectrum_id;
991 spectrum_id.setSpectrumIndex(spectrum_descr.ms1_index);
992 spectrum_id.setNativeId(
993 QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
994 .arg(spectrum_descr.parent_frame)
995 .arg(spectrum_descr.scan_mobility_start)
996 .arg(spectrum_descr.scan_mobility_end)
997 .arg(spectrum_descr.precursor_id)
998 .arg(spectrum_descr.ms1_index));
999
1000 spectrum_id.setMsRunId(msrun_id);
1001
1002 mass_spectrum.setMassSpectrumId(spectrum_id);
1003
1004
1005 TimsFrameBaseCstSPtr tims_frame;
1006 if(want_binary_data)
1007 {
1008 qDebug() << "bindec";
1009 tims_frame = getTimsFrameCstSPtrCached(spectrum_descr.parent_frame);
1010 }
1011 else
1012 {
1013 tims_frame =
1015 }
1016 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1017
1018 mass_spectrum.setParameterValue(
1020 tims_frame.get()->getOneOverK0Transformation(
1021 spectrum_descr.scan_mobility_start));
1022
1023 mass_spectrum.setParameterValue(
1025 tims_frame.get()->getOneOverK0Transformation(
1026 spectrum_descr.scan_mobility_end));
1027
1028
1029 if(want_binary_data)
1030 {
1031 combiner.combine(combiner_result,
1032 tims_frame.get()->cumulateScanToTrace(
1033 spectrum_descr.scan_mobility_start,
1034 spectrum_descr.scan_mobility_end));
1035
1036 pappso::Trace trace(combiner_result);
1037 qDebug();
1038
1039 if(trace.size() > 0)
1040 {
1041 if(mcsp_ms1Filter != nullptr)
1042 {
1043 mcsp_ms1Filter->filter(trace);
1044 }
1045
1046 qDebug();
1047 mass_spectrum.setMassSpectrumSPtr(
1048 MassSpectrum(trace).makeMassSpectrumSPtr());
1049 mass_spectrum.setEmptyMassSpectrum(false);
1050 }
1051 else
1052 {
1053 mass_spectrum.setMassSpectrumSPtr(nullptr);
1054 mass_spectrum.setEmptyMassSpectrum(true);
1055 }
1056 }
1057 qDebug();
1058 }
1059
1060 catch(PappsoException &error)
1061 {
1062 throw error;
1063 }
1064 catch(std::exception &error)
1065 {
1066 qDebug() << QString("Failure %1 ").arg(error.what());
1067 }
1068}
1069
1070
1073{
1074 QMutexLocker locker(&m_mutex);
1075 for(auto &tims_frame : m_timsFrameBaseCache)
1076 {
1077 if(tims_frame.get()->getId() == timsId)
1078 {
1079 m_timsFrameBaseCache.push_back(tims_frame);
1081 m_timsFrameBaseCache.pop_front();
1082 return tims_frame;
1083 }
1084 }
1085
1088 m_timsFrameBaseCache.pop_front();
1089 return m_timsFrameBaseCache.back();
1090}
1091
1094{
1095 qDebug();
1096 QMutexLocker locker(&m_mutex);
1097 for(auto &tims_frame : m_timsFrameCache)
1098 {
1099 if(tims_frame.get()->getId() == timsId)
1100 {
1101 m_timsFrameCache.push_back(tims_frame);
1102 if(m_timsFrameCache.size() > m_cacheSize)
1103 m_timsFrameCache.pop_front();
1104 return tims_frame;
1105 }
1106 }
1107 pappso::TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1108
1109 // locker.relock();
1110 qDebug();
1111
1112 m_timsFrameCache.push_back(frame_sptr);
1113 if(m_timsFrameCache.size() > m_cacheSize)
1114 m_timsFrameCache.pop_front();
1115 qDebug();
1116 return m_timsFrameCache.back();
1117
1118
1119 /*
1120// the frame is not in the cache
1121if(std::find(m_someoneIsLoadingFrameId.begin(),
1122 m_someoneIsLoadingFrameId.end(),
1123 timsId) == m_someoneIsLoadingFrameId.end())
1124 {
1125 // not found, we are alone on this frame
1126 m_someoneIsLoadingFrameId.push_back(timsId);
1127 qDebug();
1128 //locker.unlock();
1129 pappso::TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1130
1131 // locker.relock();
1132 qDebug();
1133 m_someoneIsLoadingFrameId.erase(
1134 std::find(m_someoneIsLoadingFrameId.begin(),
1135 m_someoneIsLoadingFrameId.end(),
1136 timsId));
1137
1138 m_timsFrameCache.push_back(frame_sptr);
1139 if(m_timsFrameCache.size() > m_cacheSize)
1140 m_timsFrameCache.pop_front();
1141 qDebug();
1142 return m_timsFrameCache.back();
1143 }
1144else
1145 {
1146 // this frame is loading by someone else, we have to wait
1147 qDebug();
1148 // locker.unlock();
1149 // std::size_t another_frame_id = timsId;
1150 while(true)
1151 {
1152 QThread::usleep(1);
1153 // locker.relock();
1154
1155 for(auto &tims_frame : m_timsFrameCache)
1156 {
1157 if(tims_frame.get()->getId() == timsId)
1158 {
1159 m_timsFrameCache.push_back(tims_frame);
1160 return tims_frame;
1161 }
1162 }
1163 // locker.unlock();
1164}
1165} // namespace pappso
1166*/
1167}
1168
1169void
1171{
1172 mcsp_ms2Filter = filter;
1173}
1174void
1176{
1177 mcsp_ms1Filter = filter;
1178}
1179
1182 PrecisionPtr precision_ptr)
1183{
1184
1185 qDebug();
1186 XicCoordTims xic_coord_tims_struct;
1187
1188 try
1189 {
1190 if(m_mapXicCoordRecord.size() == 0)
1191 {
1192 QMutexLocker lock(&m_mutex);
1193 // Go get records!
1194
1195 // We proceed in this way:
1196
1197 // 1. For each Precursor reference to the Precursors table's ID
1198 // found in the PasefFrameMsMsInfo table, store the precursor ID for
1199 // step 2.
1200
1201 // 2. From the Precursors table's ID from step 1, get the
1202 // MonoisotopicMz.
1203
1204 // 3. From the PasefFrameMsMsInfo table, for the Precursors table's
1205 // ID reference, get a reference to the Frames table's ID. Thanks to
1206 // the Frames ID, look for the Time value (acquisition retention
1207 // time) for the MS/MS spectrum. The Time value in the Frames tables
1208 // always corresponds to a Frame of MsMsType 8 (that is, MS/MS),
1209 // which is expected since we are looking into MS/MS data.
1210
1211 // 4. From the PasefFrameMsMsInfo table, associate the values
1212 // ScanNumBegin and ScanNumEnd, the mobility bins in which the
1213 // precursor was found.
1214
1215
1216 QSqlDatabase qdb = openDatabaseConnection();
1217 QSqlQuery q = qdb.exec(
1218 QString("SELECT Precursors.id, "
1219 "min(Frames.Time), "
1220 "min(PasefFrameMsMsInfo.ScanNumBegin), "
1221 "max(PasefFrameMsMsInfo.ScanNumEnd), "
1222 "Precursors.MonoisotopicMz "
1223 "FROM "
1224 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1225 "PasefFrameMsMsInfo.Precursor=Precursors.Id INNER JOIN "
1226 "Frames ON PasefFrameMsMsInfo.Frame=Frames.Id "
1227 "GROUP BY Precursors.id;"));
1228 if(q.lastError().isValid())
1229 {
1230 qDebug();
1231 throw PappsoException(
1232 QObject::tr(
1233 "ERROR in TIMS sqlite database file %1, executing SQL "
1234 "command %2:\n%3\n%4\n%5")
1235 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1236 .arg(q.lastQuery())
1237 .arg(qdb.lastError().databaseText())
1238 .arg(qdb.lastError().driverText())
1239 .arg(qdb.lastError().nativeErrorCode()));
1240 }
1241
1242 q.last(); // strange bug : get the last sql record and get back,
1243 // otherwise it will not retrieve all records.
1244 q.first();
1245 // std::size_t i = 0;
1246 do
1247 {
1248 QSqlRecord record = q.record();
1249 m_mapXicCoordRecord.insert(std::pair<std::size_t, QSqlRecord>(
1250 (std::size_t)record.value(0).toULongLong(), record));
1251 }
1252 while(q.next());
1253 }
1254
1255
1256 auto it_map_xiccoord = m_mapXicCoordRecord.find(precursor_id);
1257 if(it_map_xiccoord == m_mapXicCoordRecord.end())
1258 {
1259
1260 throw ExceptionNotFound(
1261 QObject::tr("ERROR Precursors database id %1 not found")
1262 .arg(precursor_id));
1263 }
1264
1265 auto &q = it_map_xiccoord->second;
1266 xic_coord_tims_struct.mzRange =
1267 MzRange(q.value(4).toDouble(), precision_ptr);
1268 xic_coord_tims_struct.scanNumBegin = q.value(2).toUInt();
1269 xic_coord_tims_struct.scanNumEnd = q.value(3).toUInt();
1270 xic_coord_tims_struct.rtTarget = q.value(1).toDouble();
1271 // xic_structure.charge = q.value(5).toUInt();
1272 xic_coord_tims_struct.xicSptr = std::make_shared<Xic>();
1273 }
1274 catch(PappsoException &error)
1275 {
1276 throw error;
1277 }
1278 catch(std::exception &error)
1279 {
1280 qDebug() << QString("Failure %1 ").arg(error.what());
1281 }
1282 return xic_coord_tims_struct;
1283}
1284
1285
1286std::map<quint32, quint32>
1287TimsData::getRawMs2ByPrecursorId(std::size_t precursor_index)
1288{
1289 qDebug();
1290 std::map<quint32, quint32> raw_spectrum;
1291 try
1292 {
1293 QSqlDatabase qdb = openDatabaseConnection();
1294
1295 qdb = openDatabaseConnection();
1296 QSqlQuery q =
1297 qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
1298 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1299 "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
1300 "Precursors.Id=%1;")
1301 .arg(precursor_index));
1302 if(q.lastError().isValid())
1303 {
1304 qDebug();
1305 throw PappsoException(
1306 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1307 "command %2:\n%3\n%4\n%5")
1308 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1309 .arg(q.lastQuery())
1310 .arg(qdb.lastError().databaseText())
1311 .arg(qdb.lastError().driverText())
1312 .arg(qdb.lastError().nativeErrorCode()));
1313 }
1314 qDebug();
1315 // m_mutex.unlock();
1316 if(q.size() == 0)
1317 {
1318
1319 throw ExceptionNotFound(
1320 QObject::tr(
1321 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1322 "id=%1 not found")
1323 .arg(precursor_index));
1324 }
1325 else
1326 {
1327 // qDebug() << " q.size()="<< q.size();
1328 qDebug();
1329 bool first = true;
1330 std::size_t scan_mobility_start = 0;
1331 std::size_t scan_mobility_end = 0;
1332 std::vector<std::size_t> tims_frame_list;
1333
1334 while(q.next())
1335 {
1336 tims_frame_list.push_back(q.value(0).toLongLong());
1337 if(first)
1338 {
1339
1340 scan_mobility_start = q.value(1).toLongLong();
1341 scan_mobility_end = q.value(2).toLongLong();
1342
1343 first = false;
1344 }
1345 }
1346 // QMutexLocker locker(&m_mutex_spectrum);
1347 qDebug();
1348 pappso::TimsFrameCstSPtr tims_frame, previous_frame;
1349 // TracePlusCombiner combiner;
1350 // MapTrace combiner_result;
1351 for(std::size_t tims_id : tims_frame_list)
1352 {
1353 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1354 qDebug();
1355 /*combiner.combine(combiner_result,
1356 tims_frame.get()->cumulateScanToTrace(
1357 scan_mobility_start, scan_mobility_end));*/
1358 if(previous_frame.get() != nullptr)
1359 {
1360 if(previous_frame.get()->hasSameCalibrationData(
1361 *tims_frame.get()))
1362 {
1363 }
1364 else
1365 {
1366 throw ExceptionNotFound(
1367 QObject::tr(
1368 "ERROR in %1 %2, different calibration data "
1369 "between frame id %3 and frame id %4")
1370 .arg(__FILE__)
1371 .arg(__FUNCTION__)
1372 .arg(previous_frame.get()->getId())
1373 .arg(tims_frame.get()->getId()));
1374 }
1375 }
1376 tims_frame.get()->cumulateScansInRawMap(
1377 raw_spectrum, scan_mobility_start, scan_mobility_end);
1378 qDebug();
1379
1380 previous_frame = tims_frame;
1381 }
1382 qDebug() << " precursor_index=" << precursor_index
1383 << " num_rows=" << tims_frame_list.size()
1384 << " sql=" << q.lastQuery() << " "
1385 << (std::size_t)QThread::currentThreadId();
1386 if(first == true)
1387 {
1388 throw ExceptionNotFound(
1389 QObject::tr(
1390 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1391 "id=%1 not found")
1392 .arg(precursor_index));
1393 }
1394 qDebug();
1395 }
1396 }
1397
1398 catch(PappsoException &error)
1399 {
1400 throw PappsoException(QObject::tr("ERROR in %1 (precursor_index=%2):\n%3")
1401 .arg(__FUNCTION__)
1402 .arg(precursor_index)
1403 .arg(error.qwhat()));
1404 }
1405 catch(std::exception &error)
1406 {
1407 qDebug() << QString("Failure %1 ").arg(error.what());
1408 }
1409 return raw_spectrum;
1410 qDebug();
1411}
1412
1413
1414void
1416 const MsRunIdCstSPtr &msrun_id,
1417 QualifiedMassSpectrum &mass_spectrum,
1418 const SpectrumDescr &spectrum_descr,
1419 bool want_binary_data)
1420{
1421 try
1422 {
1423 qDebug();
1424 MassSpectrumId spectrum_id;
1425
1426 spectrum_id.setSpectrumIndex(spectrum_descr.ms2_index);
1427 spectrum_id.setNativeId(QString("precursor=%1 idxms2=%2")
1428 .arg(spectrum_descr.precursor_id)
1429 .arg(spectrum_descr.ms2_index));
1430 spectrum_id.setMsRunId(msrun_id);
1431
1432 mass_spectrum.setMassSpectrumId(spectrum_id);
1433
1434 mass_spectrum.setMsLevel(2);
1435 qDebug() << "spectrum_descr.precursor_id=" << spectrum_descr.precursor_id
1436 << " spectrum_descr.ms1_index=" << spectrum_descr.ms1_index
1437 << " spectrum_descr.ms2_index=" << spectrum_descr.ms2_index;
1438 mass_spectrum.setPrecursorSpectrumIndex(spectrum_descr.ms1_index);
1439
1440 mass_spectrum.setEmptyMassSpectrum(true);
1441
1442 qDebug();
1443
1444
1445 mass_spectrum.appendPrecursorIonData(spectrum_descr.precursor_ion_data);
1446
1447 mass_spectrum.setPrecursorNativeId(
1448 QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
1449 .arg(spectrum_descr.parent_frame)
1450 .arg(spectrum_descr.scan_mobility_start)
1451 .arg(spectrum_descr.scan_mobility_end)
1452 .arg(spectrum_descr.precursor_id)
1453 .arg(spectrum_descr.ms1_index));
1454
1455 mass_spectrum.setParameterValue(
1457 spectrum_descr.isolationMz);
1458 mass_spectrum.setParameterValue(
1460 spectrum_descr.isolationWidth);
1461
1462 mass_spectrum.setParameterValue(
1464 spectrum_descr.collisionEnergy);
1465 mass_spectrum.setParameterValue(
1467 (quint64)spectrum_descr.precursor_id);
1468
1469 // QMutexLocker locker(&m_mutex_spectrum);
1470 qDebug();
1471 pappso::TimsFrameBaseCstSPtr tims_frame, previous_frame;
1472 // TracePlusCombiner combiner;
1473 // MapTrace combiner_result;
1474 std::map<quint32, quint32> raw_spectrum;
1475 bool first = true;
1476 for(std::size_t tims_id : spectrum_descr.tims_frame_list)
1477 {
1478 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1479 << " tims_id=" << tims_id
1480 << (std::size_t)QThread::currentThreadId();
1481 ;
1482 if(want_binary_data)
1483 {
1484 qDebug() << "bindec";
1485 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1486 }
1487 else
1488 {
1489 tims_frame = getTimsFrameBaseCstSPtrCached(tims_id);
1490 }
1491 qDebug() << (std::size_t)QThread::currentThreadId();
1492 ;
1493 if(first)
1494 {
1495 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1496
1497 mass_spectrum.setParameterValue(
1499 tims_frame.get()->getOneOverK0Transformation(
1500 spectrum_descr.scan_mobility_start));
1501
1502 mass_spectrum.setParameterValue(
1504 tims_frame.get()->getOneOverK0Transformation(
1505 spectrum_descr.scan_mobility_end));
1506
1507 first = false;
1508 }
1509
1510
1511 if(want_binary_data)
1512 {
1513 qDebug();
1514 /*combiner.combine(combiner_result,
1515 tims_frame.get()->cumulateScanToTrace(
1516 scan_mobility_start, scan_mobility_end));*/
1517 if(previous_frame.get() != nullptr)
1518 {
1519 if(previous_frame.get()->hasSameCalibrationData(
1520 *tims_frame.get()))
1521 {
1522 }
1523 else
1524 {
1525 throw ExceptionNotFound(
1526 QObject::tr(
1527 "ERROR in %1 %2, different calibration data "
1528 "between frame id %3 and frame id %4")
1529 .arg(__FILE__)
1530 .arg(__FUNCTION__)
1531 .arg(previous_frame.get()->getId())
1532 .arg(tims_frame.get()->getId()));
1533 }
1534 }
1535 qDebug() << (std::size_t)QThread::currentThreadId();
1536 ;
1537 tims_frame.get()->cumulateScansInRawMap(
1538 raw_spectrum,
1539 spectrum_descr.scan_mobility_start,
1540 spectrum_descr.scan_mobility_end);
1541 qDebug() << (std::size_t)QThread::currentThreadId();
1542 ;
1543 }
1544 previous_frame = tims_frame;
1545 }
1546 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1547 << " num_rows=" << spectrum_descr.tims_frame_list.size()
1548 << (std::size_t)QThread::currentThreadId();
1549 if(first == true)
1550 {
1551 throw ExceptionNotFound(
1552 QObject::tr(
1553 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1554 "id=%1 not found")
1555 .arg(spectrum_descr.precursor_id));
1556 }
1557 if(want_binary_data)
1558 {
1559 qDebug() << " precursor_index=" << spectrum_descr.precursor_id;
1560 // peak_pick.filter(trace);
1561 pappso::Trace trace;
1563 {
1564 trace =
1565 tims_frame.get()->getTraceFromCumulatedScansBuiltinCentroid(
1566 raw_spectrum);
1567 }
1568 else
1569 {
1570 // no builtin centroid:
1571
1572 trace =
1573 tims_frame.get()->getTraceFromCumulatedScans(raw_spectrum);
1574 }
1575
1576 if(trace.size() > 0)
1577 {
1578 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1579 << " " << trace.size() << " "
1580 << (std::size_t)QThread::currentThreadId();
1581
1582 if(mcsp_ms2Filter != nullptr)
1583 {
1584 // FilterTriangle filter;
1585 // filter.setTriangleSlope(50, 0.02);
1586 // filter.filter(trace);
1587 // trace.filter(pappso::FilterHighPass(10));
1588 mcsp_ms2Filter->filter(trace);
1589 }
1590
1591 // FilterScaleFactorY filter_scale((double)1 /
1592 // (double)tims_frame_list.size());
1593 // filter_scale.filter(trace);
1594 qDebug() << " precursor_index=" << spectrum_descr.precursor_id;
1595 mass_spectrum.setMassSpectrumSPtr(
1596 MassSpectrum(trace).makeMassSpectrumSPtr());
1597 mass_spectrum.setEmptyMassSpectrum(false);
1598 }
1599 else
1600 {
1601 mass_spectrum.setMassSpectrumSPtr(nullptr);
1602 mass_spectrum.setEmptyMassSpectrum(true);
1603 }
1604
1605 qDebug();
1606 }
1607 qDebug();
1608 }
1609
1610 catch(PappsoException &error)
1611 {
1612 throw PappsoException(
1613 QObject::tr("ERROR in %1 (ms2_index=%2 precursor_index=%3):\n%4")
1614 .arg(__FUNCTION__)
1615 .arg(spectrum_descr.ms2_index)
1616 .arg(spectrum_descr.precursor_id)
1617 .arg(error.qwhat()));
1618 }
1619 catch(std::exception &error)
1620 {
1621 qDebug() << QString("Failure %1 ").arg(error.what());
1622 }
1623 qDebug();
1624}
1625
1626void
1628 const MsRunIdCstSPtr &msrun_id,
1630 unsigned int ms_level)
1631{
1632 qDebug() << " ms_level=" << ms_level;
1633 if(!m_hasPrecursorTable)
1634 {
1635 throw PappsoException(
1636 QObject::tr("unable to read spectrum list : this data file does not "
1637 "contain MS2 data, no precursor found."));
1638 }
1639
1640 QSqlDatabase qdb = openDatabaseConnection();
1641 QSqlQuery qprecursor_list = qdb.exec(QString(
1642 "SELECT PasefFrameMsMsInfo.Frame, " // 0
1643 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
1644 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
1645 "PasefFrameMsMsInfo.IsolationMz, " // 3
1646 "PasefFrameMsMsInfo.IsolationWidth, " // 4
1647 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
1648 "PasefFrameMsMsInfo.Precursor, " // 6
1649 "Precursors.Id, " // 7
1650 "Precursors.LargestPeakMz, " // 8
1651 "Precursors.AverageMz, " // 9
1652 "Precursors.MonoisotopicMz, " // 10
1653 "Precursors.Charge, " // 11
1654 "Precursors.ScanNumber, " // 12
1655 "Precursors.Intensity, " // 13
1656 "Precursors.Parent " // 14
1657 "FROM PasefFrameMsMsInfo "
1658 "INNER JOIN Precursors ON "
1659 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
1660 "ORDER BY PasefFrameMsMsInfo.Precursor, PasefFrameMsMsInfo.Frame ;"));
1661 if(qprecursor_list.lastError().isValid())
1662 {
1663
1664 throw PappsoException(
1665 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1666 "command %2:\n%3\n%4\n%5")
1667 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1668 .arg(qprecursor_list.lastQuery())
1669 .arg(qdb.lastError().databaseText())
1670 .arg(qdb.lastError().driverText())
1671 .arg(qdb.lastError().nativeErrorCode()));
1672 }
1673
1674
1675 qDebug() << "qprecursor_list.size()=" << qprecursor_list.size();
1676 qDebug() << QObject::tr(
1677 "TIMS sqlite database file %1, executing SQL "
1678 "command %2:\n%3\n%4\n%5")
1679 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1680 .arg(qprecursor_list.lastQuery())
1681 .arg(qdb.lastError().databaseText())
1682 .arg(qdb.lastError().driverText())
1683 .arg(qdb.lastError().nativeErrorCode());
1684
1685 qDebug() << "qprecursor_list.isActive()=" << qprecursor_list.isActive();
1686 qDebug() << "qprecursor_list.isSelect()=" << qprecursor_list.isSelect();
1687 bool first = true;
1688 SpectrumDescr spectrum_descr;
1689 /*
1690std::size_t i = 0;
1691while(qprecursor_list.next())
1692 {
1693 qDebug() << "i=" << i;
1694 i++;
1695 }*/
1696 qprecursor_list.last(); // strange bug : get the last sql record and get
1697 // back, unless it will not retrieve all records.
1698
1699 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
1700 qprecursor_list.first();
1701 std::vector<pappso::TimsData::SpectrumDescr> spectrum_description_list;
1702 spectrum_descr.precursor_id = 0;
1703 // std::size_t i = 0;
1704
1705 do
1706 {
1707
1708 if(spectrum_descr.precursor_id !=
1709 (std::size_t)qprecursor_list.value(6).toLongLong())
1710 {
1711 // new precursor
1712 if(spectrum_descr.precursor_id > 0)
1713 {
1714 spectrum_description_list.push_back(spectrum_descr);
1715 }
1716
1717 spectrum_descr.tims_frame_list.clear();
1718 first = true;
1719 }
1720 qDebug() << " qprecursor_list.value(6).toLongLong() ="
1721 << qprecursor_list.value(6).toLongLong();
1722 spectrum_descr.precursor_id =
1723 (std::size_t)qprecursor_list.value(6).toLongLong();
1724 qDebug() << " spectrum_descr.precursor_id ="
1725 << spectrum_descr.precursor_id;
1726 qDebug() << " cumul tims frame:" << qprecursor_list.value(0).toLongLong();
1727 spectrum_descr.tims_frame_list.push_back(
1728 qprecursor_list.value(0).toLongLong());
1729 qDebug() << " first =" << first;
1730 if(first)
1731 {
1732 qDebug();
1733 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1734 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1735 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1736 spectrum_descr.precursor_ion_data =
1737 PrecursorIonData(qprecursor_list.value(10).toDouble(),
1738 qprecursor_list.value(11).toInt(),
1739 qprecursor_list.value(13).toDouble());
1740
1741 // spectrum_descr.precursor_id = q.value(6).toLongLong();
1742 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1743 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1744
1745 spectrum_descr.scan_mobility_start =
1746 qprecursor_list.value(1).toLongLong();
1747 spectrum_descr.scan_mobility_end =
1748 qprecursor_list.value(2).toLongLong();
1749
1750 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
1751 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
1752 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
1753 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
1754
1755
1756 first = false;
1757 }
1758 // qDebug() << "qprecursor_list.executedQuery()="
1759 // << qprecursor_list.executedQuery();
1760 // qDebug() << "qprecursor_list.last()=" << qprecursor_list.last();
1761 // i++;
1762 }
1763 while(qprecursor_list.next());
1764
1765 // last One
1766
1767 // new precursor
1768 if(spectrum_descr.precursor_id > 0)
1769 {
1770 spectrum_description_list.push_back(spectrum_descr);
1771 }
1772
1773
1774 QString local_filepath = m_timsDataDirectory.absoluteFilePath("analysis.tdf");
1775
1776 if(m_isMonoThread)
1777 {
1778 for(SpectrumDescr &spectrum_descr : spectrum_description_list)
1779 {
1780
1781 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1782 ms2ReaderGenerateMS1MS2Spectrum(
1783 msrun_id, mass_spectrum_list, handler, spectrum_descr, ms_level);
1784
1785 for(auto &qualified_spectrum : mass_spectrum_list)
1786 {
1787 handler.setQualifiedMassSpectrum(qualified_spectrum);
1788 }
1789
1790 if(handler.shouldStop())
1791 {
1792 qDebug() << "The operation was cancelled. Breaking the loop.";
1794 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
1795 .arg(local_filepath));
1796 }
1797 }
1798 }
1799 else
1800 {
1801
1802
1803 TimsData *itself = this;
1804 pappso::SpectrumCollectionHandlerInterface *pointer_handler = &handler;
1805
1806
1807 std::function<std::vector<QualifiedMassSpectrum>(
1809 map_function_generate_spectrum =
1810 [itself, msrun_id, pointer_handler, ms_level](
1811 const pappso::TimsData::SpectrumDescr &spectrum_descr)
1812 -> std::vector<QualifiedMassSpectrum> {
1813 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1814 itself->ms2ReaderGenerateMS1MS2Spectrum(msrun_id,
1815 mass_spectrum_list,
1816 *pointer_handler,
1817 spectrum_descr,
1818 ms_level);
1819
1820
1821 return mass_spectrum_list;
1822 };
1823
1824 std::function<void(
1825 std::size_t,
1826 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list)>
1827 reduce_function_spectrum_list =
1828 [pointer_handler, local_filepath](
1829 std::size_t res,
1830 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list) {
1831 for(auto &qualified_spectrum : qualified_spectrum_list)
1832 {
1833 pointer_handler->setQualifiedMassSpectrum(qualified_spectrum);
1834 }
1835
1836 if(pointer_handler->shouldStop())
1837 {
1838 qDebug() << "The operation was cancelled. Breaking the loop.";
1840 QObject::tr("reading TimsTOF job on %1 cancelled by the user")
1841 .arg(local_filepath));
1842 }
1843 res++;
1844 };
1845
1846
1847 QFuture<std::size_t> res;
1848 res = QtConcurrent::mappedReduced<std::size_t>(
1849 spectrum_description_list.begin(),
1850 spectrum_description_list.end(),
1851 map_function_generate_spectrum,
1852 reduce_function_spectrum_list,
1853 QtConcurrent::OrderedReduce);
1854 res.waitForFinished();
1855 }
1856 handler.loadingEnded();
1857 mpa_timsBinDec->closeLinearRead();
1858}
1859
1860
1861void
1863 const MsRunIdCstSPtr &msrun_id,
1864 std::vector<QualifiedMassSpectrum> &qualified_mass_spectrum_list,
1866 const pappso::TimsData::SpectrumDescr &spectrum_descr,
1867 unsigned int ms_level)
1868{
1869
1870 qDebug() << " ms_level=" << ms_level;
1871 // The handler will receive the index of the mass spectrum in the
1872 // current run via the mass spectrum id member datum.
1873 if((ms_level == 0) || (ms_level == 1))
1874 {
1875 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1876 getQualifiedMs1MassSpectrumByPrecursorId(
1877 msrun_id,
1878 qualified_mass_spectrum_list.back(),
1879 spectrum_descr,
1880 handler.needMsLevelPeakList(1));
1881 }
1882 if((ms_level == 0) || (ms_level == 2))
1883 {
1884 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1885 getQualifiedMs2MassSpectrumByPrecursorId(
1886 msrun_id,
1887 qualified_mass_spectrum_list.back(),
1888 spectrum_descr,
1889 handler.needMsLevelPeakList(2));
1890 }
1891 qDebug();
1892}
1893
1894
1897{
1898
1899 SpectrumDescr spectrum_descr;
1900 QSqlDatabase qdb = openDatabaseConnection();
1901 QSqlQuery q = qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
1902 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
1903 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
1904 "PasefFrameMsMsInfo.IsolationMz, " // 3
1905 "PasefFrameMsMsInfo.IsolationWidth, " // 4
1906 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
1907 "PasefFrameMsMsInfo.Precursor, " // 6
1908 "Precursors.Id, " // 7
1909 "Precursors.LargestPeakMz, " // 8
1910 "Precursors.AverageMz, " // 9
1911 "Precursors.MonoisotopicMz, " // 10
1912 "Precursors.Charge, " // 11
1913 "Precursors.ScanNumber, " // 12
1914 "Precursors.Intensity, " // 13
1915 "Precursors.Parent " // 14
1916 "FROM PasefFrameMsMsInfo "
1917 "INNER JOIN Precursors ON "
1918 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
1919 "WHERE Precursors.Id=%1;")
1920 .arg(precursor_id));
1921 if(q.lastError().isValid())
1922 {
1923
1924 throw PappsoException(
1925 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1926 "command %2:\n%3\n%4\n%5")
1927 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1928 .arg(q.lastQuery())
1929 .arg(qdb.lastError().databaseText())
1930 .arg(qdb.lastError().driverText())
1931 .arg(qdb.lastError().nativeErrorCode()));
1932 }
1933
1934
1935 bool first = true;
1936 while(q.next())
1937 {
1938
1939 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
1940 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
1941 if(first)
1942 {
1943 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1944 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1945 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1946 spectrum_descr.precursor_ion_data =
1947 PrecursorIonData(q.value(10).toDouble(),
1948 q.value(11).toInt(),
1949 q.value(13).toDouble());
1950
1951 spectrum_descr.precursor_id = q.value(6).toLongLong();
1952 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1953 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1954
1955 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
1956 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
1957
1958 spectrum_descr.isolationMz = q.value(3).toDouble();
1959 spectrum_descr.isolationWidth = q.value(4).toDouble();
1960 spectrum_descr.collisionEnergy = q.value(5).toFloat();
1961 spectrum_descr.parent_frame = q.value(14).toLongLong();
1962
1963
1964 first = false;
1965 }
1966 }
1967 if(spectrum_descr.precursor_id == 0)
1968 {
1969 throw ExceptionNotFound(
1970 QObject::tr("ERROR in %1 %2 : precursor id (%3) NOT FOUND ")
1971 .arg(__FILE__)
1972 .arg(__FUNCTION__)
1973 .arg(precursor_id));
1974 }
1975 return spectrum_descr;
1976}
1977
1978std::vector<double>
1980{
1981 std::vector<double> timeline;
1982 timeline.reserve(m_mapFramesRecord.size());
1983 for(const TimsFrameRecord &frame_record : m_mapFramesRecord)
1984 {
1985 if(frame_record.mz_calibration_id != 0)
1986 {
1987 timeline.push_back(frame_record.frame_time);
1988 }
1989 }
1990 return timeline;
1991}
1992
1995 const std::pair<std::size_t, std::size_t> &scan_coordinate)
1996{
1997
1998 SpectrumDescr spectrum_descr;
1999 QSqlDatabase qdb = openDatabaseConnection();
2000 QSqlQuery q =
2001 qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
2002 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2003 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2004 "PasefFrameMsMsInfo.IsolationMz, " // 3
2005 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2006 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2007 "PasefFrameMsMsInfo.Precursor, " // 6
2008 "Precursors.Id, " // 7
2009 "Precursors.LargestPeakMz, " // 8
2010 "Precursors.AverageMz, " // 9
2011 "Precursors.MonoisotopicMz, " // 10
2012 "Precursors.Charge, " // 11
2013 "Precursors.ScanNumber, " // 12
2014 "Precursors.Intensity, " // 13
2015 "Precursors.Parent " // 14
2016 "FROM PasefFrameMsMsInfo "
2017 "INNER JOIN Precursors ON "
2018 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2019 "WHERE "
2020 "PasefFrameMsMsInfo.Frame=%1 and "
2021 "(PasefFrameMsMsInfo.ScanNumBegin "
2022 "<= %2 and PasefFrameMsMsInfo.ScanNumEnd >= %2);")
2023 .arg(scan_coordinate.first)
2024 .arg(scan_coordinate.second));
2025 if(q.lastError().isValid())
2026 {
2027
2028 throw PappsoException(
2029 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2030 "command %2:\n%3\n%4\n%5")
2031 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2032 .arg(q.lastQuery())
2033 .arg(qdb.lastError().databaseText())
2034 .arg(qdb.lastError().driverText())
2035 .arg(qdb.lastError().nativeErrorCode()));
2036 }
2037
2038 if(q.next())
2039 {
2040
2041 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
2042 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
2043 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2044 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2045 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2046 spectrum_descr.precursor_ion_data = PrecursorIonData(
2047 q.value(10).toDouble(), q.value(11).toInt(), q.value(13).toDouble());
2048
2049 spectrum_descr.precursor_id = q.value(6).toLongLong();
2050 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2051 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2052
2053 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
2054 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
2055
2056 spectrum_descr.isolationMz = q.value(3).toDouble();
2057 spectrum_descr.isolationWidth = q.value(4).toDouble();
2058 spectrum_descr.collisionEnergy = q.value(5).toFloat();
2059 spectrum_descr.parent_frame = q.value(14).toLongLong();
2060 }
2061 return spectrum_descr;
2062}
2063
2064
2065void
2067 pappso::TimsData::SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
2068{
2069
2070 spectrum_descr.tims_frame_list.clear();
2071 spectrum_descr.tims_frame_list.push_back(
2072 qprecursor_list.value(0).toLongLong());
2073 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2074 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2075 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2076 spectrum_descr.precursor_ion_data =
2077 PrecursorIonData(qprecursor_list.value(10).toDouble(),
2078 qprecursor_list.value(11).toInt(),
2079 qprecursor_list.value(13).toDouble());
2080
2081 spectrum_descr.precursor_id = qprecursor_list.value(6).toLongLong();
2082 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2083 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2084
2085 spectrum_descr.scan_mobility_start = qprecursor_list.value(1).toLongLong();
2086 spectrum_descr.scan_mobility_end = qprecursor_list.value(2).toLongLong();
2087
2088 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
2089 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
2090 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
2091 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
2092}
2093
2094
2095void
2097 const pappso::MsRunIdCstSPtr &msrun_id,
2099 unsigned int ms_level)
2100{
2101
2102 if(!m_hasPrecursorTable)
2103 {
2104 throw PappsoException(
2105 QObject::tr("unable to read spectrum list : this data file does not "
2106 "contain MS2 data, no precursor found."));
2107 }
2108
2109 // We'll need it to perform the looping in the spectrum list.
2110 std::size_t spectrum_list_size = getTotalNumberOfScans();
2111
2112 // qDebug() << "The spectrum list has size:" << spectrum_list_size;
2113
2114 // Inform the handler of the spectrum list so that it can handle feedback to
2115 // the user.
2116 handler.spectrumListHasSize(spectrum_list_size);
2117
2118 QSqlDatabase qdb = openDatabaseConnection();
2119 QSqlQuery qprecursor_list = qdb.exec(QString(
2120 "SELECT DISTINCT "
2121 "PasefFrameMsMsInfo.Frame, " // 0
2122 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2123 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2124 "PasefFrameMsMsInfo.IsolationMz, " // 3
2125 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2126 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2127 "PasefFrameMsMsInfo.Precursor, " // 6
2128 "Precursors.Id, " // 7
2129 "Precursors.LargestPeakMz, " // 8
2130 "Precursors.AverageMz, " // 9
2131 "Precursors.MonoisotopicMz, " // 10
2132 "Precursors.Charge, " // 11
2133 "Precursors.ScanNumber, " // 12
2134 "Precursors.Intensity, " // 13
2135 "Precursors.Parent " // 14
2136 "FROM PasefFrameMsMsInfo "
2137 "INNER JOIN Precursors ON "
2138 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2139 "ORDER BY PasefFrameMsMsInfo.Frame, PasefFrameMsMsInfo.ScanNumBegin ;"));
2140 if(qprecursor_list.lastError().isValid())
2141 {
2142 throw PappsoException(
2143 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2144 "command %2:\n%3\n%4\n%5")
2145 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2146 .arg(qprecursor_list.lastQuery())
2147 .arg(qdb.lastError().databaseText())
2148 .arg(qdb.lastError().driverText())
2149 .arg(qdb.lastError().nativeErrorCode()));
2150 }
2151
2152
2153 std::size_t i = 0; // iterate on each Spectrum
2154
2155 qprecursor_list.last(); // strange bug : get the last sql record and get
2156 // back, unless it will not retrieve all records.
2157
2158 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
2159 qprecursor_list.first();
2160
2161 TimsFrameBaseCstSPtr tims_frame;
2162 SpectrumDescr spectrum_descr;
2163
2164 for(FrameIdDescr &current_frame : m_frameIdDescrList)
2165 {
2166
2167 // If the user of this reader instance wants to stop reading the
2168 // spectra, then break this loop.
2169 if(handler.shouldStop())
2170 {
2171 qDebug() << "The operation was cancelled. Breaking the loop.";
2173 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
2174 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf")));
2175 }
2176
2177 tims_frame = getTimsFrameBaseCstSPtrCached(current_frame.m_frameId);
2178 unsigned int tims_ms_level = tims_frame.get()->getMsLevel();
2179
2180 if((ms_level != 0) && (ms_level != tims_ms_level))
2181 { // bypass
2182 i += current_frame.m_size;
2183 }
2184 else
2185 {
2186 bool want_binary_data = handler.needMsLevelPeakList(tims_ms_level);
2187 qDebug() << "want_binary_data=" << want_binary_data;
2188 if(want_binary_data)
2189 {
2190 qDebug() << "bindec";
2191 tims_frame = getTimsFrameCstSPtrCached(current_frame.m_frameId);
2192 }
2193
2194 bool possible_precursor = false;
2195 if(tims_ms_level == 2)
2196 {
2197 // seek the precursor record:
2198 while(qprecursor_list.value(0).toULongLong() <
2199 current_frame.m_frameId)
2200 {
2201 qprecursor_list.next();
2202
2203 if(qprecursor_list.value(0).toULongLong() ==
2204 current_frame.m_frameId)
2205 {
2206 possible_precursor = true;
2207 }
2208 fillSpectrumDescriptionWithSqlRecord(spectrum_descr,
2209 qprecursor_list);
2210 }
2211 }
2212
2213 for(std::size_t scan_num = 0; scan_num < current_frame.m_size;
2214 scan_num++)
2215 {
2216 bool has_a_precursor = false;
2217 if(possible_precursor)
2218 {
2219 if(spectrum_descr.scan_mobility_end < scan_num)
2220 {
2221 // seek the precursor record:
2222 while(qprecursor_list.value(0).toULongLong() <
2223 current_frame.m_frameId)
2224 {
2225 qprecursor_list.next();
2226
2227 if(qprecursor_list.value(0).toULongLong() !=
2228 current_frame.m_frameId)
2229 {
2230 possible_precursor = false;
2231 }
2232 fillSpectrumDescriptionWithSqlRecord(spectrum_descr,
2233 qprecursor_list);
2234 }
2235 }
2236
2237 if(possible_precursor &&
2238 (spectrum_descr.scan_mobility_start < scan_num))
2239 {
2240 // we are in
2241 has_a_precursor = true;
2242 }
2243 } // end to determine if we are in a precursor for this
2244 // spectrum
2245
2246 QualifiedMassSpectrum mass_spectrum;
2247
2248
2249 MassSpectrumId spectrum_id;
2250
2251 spectrum_id.setSpectrumIndex(i);
2252 spectrum_id.setMsRunId(msrun_id);
2253 spectrum_id.setNativeId(QString("frame=%1 scan=%2 index=%3")
2254 .arg(current_frame.m_frameId)
2255 .arg(scan_num)
2256 .arg(i));
2257
2258 mass_spectrum.setMassSpectrumId(spectrum_id);
2259
2260 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
2261 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
2262
2263 mass_spectrum.setDtInMilliSeconds(
2264 tims_frame.get()->getDriftTime(scan_num));
2265 // 1/K0
2266 mass_spectrum.setParameterValue(
2268 tims_frame.get()->getOneOverK0Transformation(scan_num));
2269
2270 mass_spectrum.setEmptyMassSpectrum(true);
2271 if(want_binary_data)
2272 {
2273 try
2274 {
2275 mass_spectrum.setMassSpectrumSPtr(
2276 tims_frame.get()->getMassSpectrumSPtr(scan_num));
2277 }
2278 catch(PappsoException &error)
2279 {
2280 throw PappsoException(
2281 QObject::tr(
2282 "ERROR in %1 (scan_num=%2 spectrum_index=%3):\n%4")
2283 .arg(__FUNCTION__)
2284 .arg(scan_num)
2285 .arg(spectrum_id.getSpectrumIndex())
2286 .arg(error.qwhat()));
2287 }
2288 if(mass_spectrum.size() > 0)
2289 {
2290 mass_spectrum.setEmptyMassSpectrum(false);
2291 }
2292 }
2293 else
2294 {
2295 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
2296 //{
2297 mass_spectrum.setEmptyMassSpectrum(false);
2298 // }
2299 }
2300 if(has_a_precursor)
2301 {
2302 if(spectrum_descr.precursor_id > 0)
2303 {
2304
2305 mass_spectrum.appendPrecursorIonData(
2306 spectrum_descr.precursor_ion_data);
2307
2308 std::size_t prec_spectrum_index =
2309 getRawIndexFromCoordinate(spectrum_descr.parent_frame,
2310 scan_num);
2311
2312 mass_spectrum.setPrecursorSpectrumIndex(
2313 prec_spectrum_index);
2314 mass_spectrum.setPrecursorNativeId(
2315 QString("frame=%1 scan=%2 index=%3")
2316 .arg(spectrum_descr.parent_frame)
2317 .arg(scan_num)
2318 .arg(prec_spectrum_index));
2319
2320 mass_spectrum.setParameterValue(
2322 spectrum_descr.isolationMz);
2323 mass_spectrum.setParameterValue(
2325 spectrum_descr.isolationWidth);
2326
2327 mass_spectrum.setParameterValue(
2329 spectrum_descr.collisionEnergy);
2330 mass_spectrum.setParameterValue(
2332 (quint64)spectrum_descr.precursor_id);
2333 }
2334 }
2335
2336 handler.setQualifiedMassSpectrum(mass_spectrum);
2337 i++;
2338 }
2339 }
2340 }
2341}
2342
2343std::map<quint32, quint32>
2344TimsData::getRawMsBySpectrumIndex(std::size_t spectrum_index)
2345{
2346
2347 qDebug() << " spectrum_index=" << spectrum_index;
2348 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
2349 TimsFrameBaseCstSPtr tims_frame;
2350 tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
2351
2352 std::map<quint32, quint32> raw_spectrum;
2353 tims_frame.get()->cumulateScansInRawMap(
2354 raw_spectrum, coordinate.second, coordinate.second);
2355 return raw_spectrum;
2356}
2357
2358
2359const std::vector<FrameIdDescr> &
2361{
2362 return m_frameIdDescrList;
2363}
2364
2365
2366} // namespace pappso
Trace toTrace() const
Definition: maptrace.cpp:219
void setNativeId(const QString &native_id)
void setMsRunId(MsRunIdCstSPtr other)
std::size_t getSpectrumIndex() const
void setSpectrumIndex(std::size_t index)
Class to represent a mass spectrum.
Definition: massspectrum.h:71
MzCalibrationInterfaceSPtr getInstance(double T1_frame, double T2_frame, const QSqlRecord &mzcalibration_record)
const char * what() const noexcept override
virtual const QString & qwhat() const
Class representing a fully specified mass spectrum.
void setPrecursorNativeId(const QString &native_id)
Set the scan native id of the precursor ion.
void setDtInMilliSeconds(pappso_double rt)
Set the drift time in milliseconds.
void appendPrecursorIonData(const PrecursorIonData &precursor_ion_data)
void setMassSpectrumId(const MassSpectrumId &iD)
Set the MassSpectrumId.
void setMsLevel(uint ms_level)
Set the mass spectrum level.
void setPrecursorSpectrumIndex(std::size_t precursor_scan_num)
Set the scan number of the precursor ion.
void setParameterValue(QualifiedMassSpectrumParameter parameter, const QVariant &value)
void setMassSpectrumSPtr(MassSpectrumSPtr massSpectrum)
Set the MassSpectrumSPtr.
void setRtInSeconds(pappso_double rt)
Set the retention time in seconds.
void setEmptyMassSpectrum(bool is_empty_mass_spectrum)
interface to collect spectrums from the MsRunReader class
Definition: msrunreader.h:56
virtual bool needMsLevelPeakList(unsigned int ms_level) const final
tells if we need the peak list (if we want the binary data) for each spectrum, given an MS level
Definition: msrunreader.cpp:70
virtual void spectrumListHasSize(std::size_t size)
Definition: msrunreader.cpp:53
virtual void setQualifiedMassSpectrum(const QualifiedMassSpectrum &spectrum)=0
TimsFrameSPtr getTimsFrameSPtrByOffset(std::size_t frameId, const std::vector< pappso::TimsFrameRecord > &frame_record_list)
Definition: timsbindec.cpp:147
QSqlDatabase openDatabaseConnection() const
Definition: timsdata.cpp:233
TimsFrameCstSPtr getTimsFrameCstSPtr(std::size_t timsId)
get a Tims frame with his database ID
Definition: timsdata.cpp:527
std::vector< FrameIdDescr > m_frameIdDescrList
store every frame id and corresponding sizes
Definition: timsdata.h:332
void ms2ReaderSpectrumCollectionByMsLevel(const MsRunIdCstSPtr &msrun_id, SpectrumCollectionHandlerInterface &handler, unsigned int ms_level)
function to visit an MsRunReader and get each Spectrum in a spectrum collection handler by Ms Levels
Definition: timsdata.cpp:1627
TimsFrameCstSPtr getTimsFrameCstSPtrCached(std::size_t timsId)
get a Tims frame with his database ID but look in the cache first
Definition: timsdata.cpp:1093
pappso::MassSpectrumCstSPtr getMassSpectrumCstSPtrByRawIndex(std::size_t raw_index)
get a mass spectrum given its spectrum index
Definition: timsdata.cpp:398
void getQualifiedMs1MassSpectrumByPrecursorId(const MsRunIdCstSPtr &msrun_id, QualifiedMassSpectrum &mass_spectrum, const SpectrumDescr &spectrum_descr, bool want_binary_data)
Definition: timsdata.cpp:971
virtual ~TimsData()
Definition: timsdata.cpp:268
SpectrumDescr getSpectrumDescrWithPrecursorId(std::size_t precursor_id)
get an intermediate structure describing a spectrum
Definition: timsdata.cpp:1896
const std::vector< FrameIdDescr > & getFrameIdDescrList() const
Definition: timsdata.cpp:2360
std::size_t getTotalNumberOfFrames() const
Get total number of frames.
Definition: timsdata.cpp:623
void getQualifiedMs2MassSpectrumByPrecursorId(const MsRunIdCstSPtr &msrun_id, QualifiedMassSpectrum &mass_spectrum, const SpectrumDescr &spectrum_descr, bool want_binary_data)
Definition: timsdata.cpp:1415
TimsData(QDir timsDataDirectory)
build using the tims data directory
Definition: timsdata.cpp:46
std::map< quint32, quint32 > getRawMs2ByPrecursorId(std::size_t precursor_index)
get cumulated raw signal for a given precursor only to use to see the raw signal
Definition: timsdata.cpp:1287
std::size_t m_totalNumberOfFrames
Definition: timsdata.h:309
Trace getTicChromatogram() const
Definition: timsdata.cpp:887
TimsFrameBaseCstSPtr getTimsFrameBaseCstSPtrCached(std::size_t timsId)
Definition: timsdata.cpp:1072
std::size_t m_totalNumberOfScans
Definition: timsdata.h:307
std::deque< TimsFrameCstSPtr > m_timsFrameCache
Definition: timsdata.h:311
pappso::MassSpectrumCstSPtr getMassSpectrumCstSPtr(std::size_t timsId, std::size_t scanNum)
get a mass spectrum given the tims frame database id and scan number within tims frame
Definition: timsdata.cpp:613
std::size_t m_cacheSize
Definition: timsdata.h:310
std::pair< std::size_t, std::size_t > getScanCoordinateFromRawIndex(std::size_t spectrum_index) const
Definition: timsdata.cpp:339
std::vector< TimsFrameRecord > m_mapFramesRecord
Definition: timsdata.h:324
std::map< int, QSqlRecord > m_mapMzCalibrationRecord
Definition: timsdata.h:322
std::vector< std::size_t > getPrecursorsFromMzRtCharge(int charge, double mz_val, double rt_sec, double k0)
guess possible precursor ids given a charge, m/z, retention time and k0
Definition: timsdata.cpp:643
void fillSpectrumDescriptionWithSqlRecord(SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
Definition: timsdata.cpp:2066
std::map< int, QSqlRecord > m_mapTimsCalibrationRecord
Definition: timsdata.h:323
QMutex m_mutex
Definition: timsdata.h:350
bool m_builtinMs2Centroid
enable builtin centroid on raw tims integers by default
Definition: timsdata.h:319
void setMs2BuiltinCentroid(bool centroid)
enable or disable simple centroid filter on raw tims data for MS2
Definition: timsdata.cpp:282
std::vector< std::size_t > getClosestPrecursorIdByMz(std::vector< std::vector< double > > ids, double mz_value)
Definition: timsdata.cpp:748
void fillFrameIdDescrList()
private function to fill m_frameIdDescrList
Definition: timsdata.cpp:294
TimsFrameBaseCstSPtr getTimsFrameBaseCstSPtr(std::size_t timsId)
get a Tims frame base (no binary data file access) with his database ID
Definition: timsdata.cpp:419
bool m_hasPrecursorTable
Definition: timsdata.h:348
void rawReaderSpectrumCollectionByMsLevel(const MsRunIdCstSPtr &msrun_id, SpectrumCollectionHandlerInterface &handler, unsigned int ms_level)
function to visit an MsRunReader and get each raw Spectrum in a spectrum collection handler by Ms Lev...
Definition: timsdata.cpp:2096
QDir m_timsDataDirectory
Definition: timsdata.h:304
std::size_t getTotalNumberOfPrecursors() const
get the number of precursors analyzes by PASEF
Definition: timsdata.cpp:637
MzCalibrationStore * mpa_mzCalibrationStore
Definition: timsdata.h:327
std::vector< std::size_t > getTimsMS1FrameIdRange(double rt_begin, double rt_end) const
Definition: timsdata.cpp:491
virtual std::vector< double > getRetentionTimeLine() const
retention timeline get retention times along the MSrun in seconds
Definition: timsdata.cpp:1979
unsigned int getMsLevelBySpectrumIndex(std::size_t spectrum_index)
Definition: timsdata.cpp:772
bool getMs2BuiltinCentroid() const
tells if simple centroid filter on raw tims data for MS2 is enabled or not
Definition: timsdata.cpp:288
SpectrumDescr getSpectrumDescrWithScanCoordinate(const std::pair< std::size_t, std::size_t > &scan_coordinate)
Definition: timsdata.cpp:1994
std::map< quint32, quint32 > getRawMsBySpectrumIndex(std::size_t spectrum_index)
get raw signal for a spectrum index only to use to see the raw signal
Definition: timsdata.cpp:2344
std::deque< TimsFrameBaseCstSPtr > m_timsFrameBaseCache
Definition: timsdata.h:312
std::map< std::size_t, std::size_t > m_thousandIndexToFrameIdDescrListIndex
index to find quickly a frameId in the description list with the raw index of spectrum modulo 1000 @k...
Definition: timsdata.h:339
void ms2ReaderGenerateMS1MS2Spectrum(const MsRunIdCstSPtr &msrun_id, std::vector< QualifiedMassSpectrum > &qualified_mass_spectrum_list, SpectrumCollectionHandlerInterface &handler, const SpectrumDescr &spectrum_descr, unsigned int ms_level)
Definition: timsdata.cpp:1862
TimsBinDec * mpa_timsBinDec
Definition: timsdata.h:305
void getQualifiedMassSpectrumByRawIndex(const MsRunIdCstSPtr &msrun_id, QualifiedMassSpectrum &mass_spectrum, std::size_t spectrum_index, bool want_binary_data)
Definition: timsdata.cpp:781
void setMs1FilterCstSPtr(pappso::FilterInterfaceCstSPtr &filter)
filter interface to apply just after raw MS1 specturm extraction the filter can be a list of filters ...
Definition: timsdata.cpp:1175
void setMs2FilterCstSPtr(pappso::FilterInterfaceCstSPtr &filter)
filter interface to apply just after raw MS2 specturm extraction the filter can be a list of filters ...
Definition: timsdata.cpp:1170
pappso::FilterInterfaceCstSPtr mcsp_ms1Filter
Definition: timsdata.h:315
bool m_isMonoThread
Definition: timsdata.h:346
std::size_t getTotalNumberOfScans() const
get the total number of scans
Definition: timsdata.cpp:630
std::vector< std::size_t > getMatchPrecursorIdByKo(std::vector< std::vector< double > > ids, double ko_value)
Definition: timsdata.cpp:722
std::size_t getRawIndexFromCoordinate(std::size_t frame_id, std::size_t scan_num) const
Definition: timsdata.cpp:375
pappso::FilterInterfaceCstSPtr mcsp_ms2Filter
Definition: timsdata.h:314
void setMonoThread(bool is_mono_thread)
set only one is_mono_thread to true
Definition: timsdata.cpp:227
XicCoordTims getXicCoordTimsFromPrecursorId(std::size_t precursor_id, PrecisionPtr precision_ptr)
Definition: timsdata.cpp:1181
std::size_t m_totalNumberOfPrecursors
Definition: timsdata.h:308
virtual MapTrace & combine(MapTrace &map_trace, const Trace &trace) const override
A simple container of DataPoint instances.
Definition: trace.h:148
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition: aa.cpp:39
std::shared_ptr< const TimsFrameBase > TimsFrameBaseCstSPtr
Definition: timsframebase.h:41
std::shared_ptr< TimsFrame > TimsFrameSPtr
Definition: timsframe.h:41
std::shared_ptr< TimsFrameBase > TimsFrameBaseSPtr
Definition: timsframebase.h:40
std::shared_ptr< const MsRunId > MsRunIdCstSPtr
Definition: msrunid.h:46
std::shared_ptr< const MassSpectrum > MassSpectrumCstSPtr
Definition: massspectrum.h:55
@ CollisionEnergy
Bruker's Tims tof collision energy.
@ OneOverK0end
1/k0 of last acquisition for composite pasef MS/MS spectrum
@ IsolationWidth
isolation window width
@ BrukerPrecursorIndex
Bruker's Tims tof precursor index.
@ rt
Retention time.
std::shared_ptr< const FilterInterface > FilterInterfaceCstSPtr
std::shared_ptr< const TimsFrame > TimsFrameCstSPtr
Definition: timsframe.h:42
std::vector< std::size_t > tims_frame_list
Definition: timsdata.h:137
PrecursorIonData precursor_ion_data
Definition: timsdata.h:138
std::size_t tims_calibration_id
coordinates of the XIC to extract and the resulting XIC after extraction
Definition: xiccoordtims.h:51
std::size_t scanNumEnd
mobility index end
Definition: xiccoordtims.h:96
std::size_t scanNumBegin
mobility index begin
Definition: xiccoordtims.h:92
XicSPtr xicSptr
extracted xic
Definition: xiccoord.h:130
double rtTarget
the targeted retention time to extract around intended in seconds, and related to one msrun....
Definition: xiccoord.h:126
MzRange mzRange
the mass to extract
Definition: xiccoord.h:120
main Tims data handler