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