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
622
623std::size_t
625{
627}
628
629
630std::size_t
632{
634}
635
636
637std::size_t
639{
641}
642
643std::vector<std::size_t>
645 double mz_val,
646 double rt_sec,
647 double k0)
648{
649 std::vector<std::size_t> precursor_ids;
650 std::vector<std::vector<double>> ids;
651
652 QSqlDatabase qdb = openDatabaseConnection();
653 QSqlQuery q = qdb.exec(
654 QString(
655 "SELECT Frames.Time, Precursors.MonoisotopicMz, Precursors.Charge, "
656 "Precursors.Id, Frames.Id, PasefFrameMsMsInfo.ScanNumBegin, "
657 "PasefFrameMsMsInfo.scanNumEnd "
658 "FROM Frames "
659 "INNER JOIN PasefFrameMsMsInfo ON Frames.Id = PasefFrameMsMsInfo.Frame "
660 "INNER JOIN Precursors ON PasefFrameMsMsInfo.Precursor = Precursors.Id "
661 "WHERE Precursors.Charge == %1 "
662 "AND Precursors.MonoisotopicMz > %2 -0.01 "
663 "AND Precursors.MonoisotopicMz < %2 +0.01 "
664 "AND Frames.Time >= %3 -1 "
665 "AND Frames.Time < %3 +1; ")
666 .arg(charge)
667 .arg(mz_val)
668 .arg(rt_sec));
669 if(q.lastError().isValid())
670 {
671
672 throw PappsoException(
673 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
674 "executing SQL "
675 "command %3:\n%4\n%5\n%6")
676 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
677 .arg(qdb.databaseName())
678 .arg(q.lastQuery())
679 .arg(qdb.lastError().databaseText())
680 .arg(qdb.lastError().driverText())
681 .arg(qdb.lastError().nativeErrorCode()));
682 }
683 while(q.next())
684 {
685 // qInfo() << q.value(0).toDouble() << q.value(1).toDouble()
686 // << q.value(2).toDouble() << q.value(3).toDouble();
687
688 std::vector<double> sql_values;
689 sql_values.push_back(q.value(4).toDouble()); // frame id
690 sql_values.push_back(q.value(3).toDouble()); // precursor id
691 sql_values.push_back(q.value(5).toDouble()); // scan num begin
692 sql_values.push_back(q.value(6).toDouble()); // scan num end
693 sql_values.push_back(q.value(1).toDouble()); // mz_value
694
695 ids.push_back(sql_values);
696
697
698 if(std::find(precursor_ids.begin(),
699 precursor_ids.end(),
700 q.value(3).toDouble()) == precursor_ids.end())
701 {
702 precursor_ids.push_back(q.value(3).toDouble());
703 }
704 }
705
706 if(precursor_ids.size() > 1)
707 {
708 // std::vector<std::size_t> precursor_ids_ko =
709 // getMatchPrecursorIdByKo(ids, values[3]);
710 if(precursor_ids.size() > 1)
711 {
712 precursor_ids = getClosestPrecursorIdByMz(ids, k0);
713 }
714 return precursor_ids;
715 }
716 else
717 {
718 return precursor_ids;
719 }
720}
721
722std::vector<std::size_t>
723TimsData::getMatchPrecursorIdByKo(std::vector<std::vector<double>> ids,
724 double ko_value)
725{
726 std::vector<std::size_t> precursor_id;
727 for(std::vector<double> index : ids)
728 {
729 auto coordinate = getScanCoordinateFromRawIndex(index[0]);
730
731 TimsFrameBaseCstSPtr tims_frame;
732 tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
733
734 double bko = tims_frame.get()->getOneOverK0Transformation(index[2]);
735 double eko = tims_frame.get()->getOneOverK0Transformation(index[3]);
736
737 // qInfo() << "diff" << (bko + eko) / 2;
738 double mean_ko = (bko + eko) / 2;
739
740 if(mean_ko > ko_value - 0.1 && mean_ko < ko_value + 0.1)
741 {
742 precursor_id.push_back(index[1]);
743 }
744 }
745 return precursor_id;
746}
747
748std::vector<std::size_t>
749TimsData::getClosestPrecursorIdByMz(std::vector<std::vector<double>> ids,
750 double mz_value)
751{
752 std::vector<std::size_t> best_precursor;
753 double best_value = 1;
754 int count = 1;
755 int best_val_position = 0;
756
757 for(std::vector<double> values : ids)
758 {
759 double new_val = abs(mz_value - values[4]);
760 if(new_val < best_value)
761 {
762 best_value = new_val;
763 best_val_position = count;
764 }
765 count++;
766 }
767 best_precursor.push_back(ids[best_val_position][1]);
768 return best_precursor;
769}
770
771
772unsigned int
773TimsData::getMsLevelBySpectrumIndex(std::size_t spectrum_index)
774{
775 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
776 auto tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
777 return tims_frame.get()->getMsLevel();
778}
779
780
781void
783 const MsRunIdCstSPtr &msrun_id,
784 QualifiedMassSpectrum &mass_spectrum,
785 std::size_t spectrum_index,
786 bool want_binary_data)
787{
788 try
789 {
790 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
791 TimsFrameBaseCstSPtr tims_frame;
792 if(want_binary_data)
793 {
794 tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
795 }
796 else
797 {
798 tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
799 }
800 MassSpectrumId spectrum_id;
801
802 spectrum_id.setSpectrumIndex(spectrum_index);
803 spectrum_id.setMsRunId(msrun_id);
804 spectrum_id.setNativeId(QString("frame=%1 scan=%2 index=%3")
805 .arg(coordinate.first)
806 .arg(coordinate.second)
807 .arg(spectrum_index));
808
809 mass_spectrum.setMassSpectrumId(spectrum_id);
810
811 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
812 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
813
814 mass_spectrum.setDtInMilliSeconds(
815 tims_frame.get()->getDriftTime(coordinate.second));
816 // 1/K0
817 mass_spectrum.setParameterValue(
819 tims_frame.get()->getOneOverK0Transformation(coordinate.second));
820
821 mass_spectrum.setEmptyMassSpectrum(true);
822 if(want_binary_data)
823 {
824 mass_spectrum.setMassSpectrumSPtr(
825 tims_frame.get()->getMassSpectrumSPtr(coordinate.second));
826 if(mass_spectrum.size() > 0)
827 {
828 mass_spectrum.setEmptyMassSpectrum(false);
829 }
830 }
831 else
832 {
833 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
834 //{
835 mass_spectrum.setEmptyMassSpectrum(false);
836 // }
837 }
838 if(tims_frame.get()->getMsLevel() > 1)
839 {
840
841 auto spectrum_descr = getSpectrumDescrWithScanCoordinate(coordinate);
842 if(spectrum_descr.precursor_id > 0)
843 {
844
845 mass_spectrum.appendPrecursorIonData(
846 spectrum_descr.precursor_ion_data);
847
848
849 MassSpectrumId spectrum_id;
850 std::size_t prec_spectrum_index = getRawIndexFromCoordinate(
851 spectrum_descr.parent_frame, coordinate.second);
852
853 mass_spectrum.setPrecursorSpectrumIndex(prec_spectrum_index);
854 mass_spectrum.setPrecursorNativeId(
855 QString("frame=%1 scan=%2 index=%3")
856 .arg(spectrum_descr.parent_frame)
857 .arg(coordinate.second)
858 .arg(prec_spectrum_index));
859
860 mass_spectrum.setParameterValue(
862 spectrum_descr.isolationMz);
863 mass_spectrum.setParameterValue(
865 spectrum_descr.isolationWidth);
866
867 mass_spectrum.setParameterValue(
869 spectrum_descr.collisionEnergy);
870 mass_spectrum.setParameterValue(
872 (quint64)spectrum_descr.precursor_id);
873 }
874 }
875 }
876 catch(PappsoException &error)
877 {
879 QObject::tr("Error TimsData::getQualifiedMassSpectrumByRawIndex "
880 "spectrum_index=%1 :\n%2")
881 .arg(spectrum_index)
882 .arg(error.qwhat()));
883 }
884}
885
886
887Trace
889{
890 // In the Frames table, each frame has a record describing the
891 // SummedIntensities for all the mobility spectra.
892
893
894 MapTrace rt_tic_map_trace;
895
896 using Pair = std::pair<double, double>;
897 using Map = std::map<double, double>;
898 using Iterator = Map::iterator;
899
900
901 QSqlDatabase qdb = openDatabaseConnection();
902 QSqlQuery q =
903 qdb.exec(QString("SELECT Time, SummedIntensities "
904 "FROM Frames WHERE MsMsType = 0 "
905 "ORDER BY Time;"));
906
907 if(q.lastError().isValid())
908 {
909
910 throw PappsoException(
911 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
912 "executing SQL "
913 "command %3:\n%4\n%5\n%6")
914 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
915 .arg(qdb.databaseName())
916 .arg(q.lastQuery())
917 .arg(qdb.lastError().databaseText())
918 .arg(qdb.lastError().driverText())
919 .arg(qdb.lastError().nativeErrorCode()));
920 }
921
922 while(q.next())
923 {
924
925 bool ok = false;
926
927 int cumulated_results = 2;
928
929 double rt = q.value(0).toDouble(&ok);
930 cumulated_results -= ok;
931
932 double sumY = q.value(1).toDouble(&ok);
933 cumulated_results -= ok;
934
935 if(cumulated_results)
936 {
937 throw PappsoException(
938 QObject::tr(
939 "ERROR in TIMS sqlite database file: could not read either the "
940 "retention time or the summed intensities (%1, database name "
941 "%2, "
942 "executing SQL "
943 "command %3:\n%4\n%5\n%6")
944 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
945 .arg(qdb.databaseName())
946 .arg(q.lastQuery())
947 .arg(qdb.lastError().databaseText())
948 .arg(qdb.lastError().driverText())
949 .arg(qdb.lastError().nativeErrorCode()));
950 }
951
952 // Try to insert value sumY at key rt.
953 std::pair<Iterator, bool> res = rt_tic_map_trace.insert(Pair(rt, sumY));
954
955 if(!res.second)
956 {
957 // One other same rt value was seen already (like in ion mobility
958 // mass spectrometry, for example). Only increment the y value.
959
960 res.first->second += sumY;
961 }
962 }
963
964 // qDebug().noquote() << "The TIC chromatogram:\n"
965 //<< rt_tic_map_trace.toTrace().toString();
966
967 return rt_tic_map_trace.toTrace();
968}
969
970
971void
973 const MsRunIdCstSPtr &msrun_id,
974 QualifiedMassSpectrum &mass_spectrum,
975 const SpectrumDescr &spectrum_descr,
976 bool want_binary_data)
977{
978
979 qDebug() << " ms2_index=" << spectrum_descr.ms2_index
980 << " precursor_index=" << spectrum_descr.precursor_id;
981
982 TracePlusCombiner combiner;
983 MapTrace combiner_result;
984
985 try
986 {
987 mass_spectrum.setMsLevel(1);
988 mass_spectrum.setPrecursorSpectrumIndex(0);
989 mass_spectrum.setEmptyMassSpectrum(true);
990
991 MassSpectrumId spectrum_id;
992 spectrum_id.setSpectrumIndex(spectrum_descr.ms1_index);
993 spectrum_id.setNativeId(
994 QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
995 .arg(spectrum_descr.parent_frame)
996 .arg(spectrum_descr.scan_mobility_start)
997 .arg(spectrum_descr.scan_mobility_end)
998 .arg(spectrum_descr.precursor_id)
999 .arg(spectrum_descr.ms1_index));
1000
1001 spectrum_id.setMsRunId(msrun_id);
1002
1003 mass_spectrum.setMassSpectrumId(spectrum_id);
1004
1005
1006 TimsFrameBaseCstSPtr tims_frame;
1007 if(want_binary_data)
1008 {
1009 qDebug() << "bindec";
1010 tims_frame = getTimsFrameCstSPtrCached(spectrum_descr.parent_frame);
1011 }
1012 else
1013 {
1014 tims_frame =
1016 }
1017 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1018
1019 mass_spectrum.setParameterValue(
1021 tims_frame.get()->getOneOverK0Transformation(
1022 spectrum_descr.scan_mobility_start));
1023
1024 mass_spectrum.setParameterValue(
1026 tims_frame.get()->getOneOverK0Transformation(
1027 spectrum_descr.scan_mobility_end));
1028
1029
1030 if(want_binary_data)
1031 {
1032 combiner.combine(combiner_result,
1033 tims_frame.get()->cumulateScanToTrace(
1034 spectrum_descr.scan_mobility_start,
1035 spectrum_descr.scan_mobility_end));
1036
1037 pappso::Trace trace(combiner_result);
1038 qDebug();
1039
1040 if(trace.size() > 0)
1041 {
1042 if(mcsp_ms1Filter != nullptr)
1043 {
1044 mcsp_ms1Filter->filter(trace);
1045 }
1046
1047 qDebug();
1048 mass_spectrum.setMassSpectrumSPtr(
1049 MassSpectrum(trace).makeMassSpectrumSPtr());
1050 mass_spectrum.setEmptyMassSpectrum(false);
1051 }
1052 else
1053 {
1054 mass_spectrum.setMassSpectrumSPtr(nullptr);
1055 mass_spectrum.setEmptyMassSpectrum(true);
1056 }
1057 }
1058 qDebug();
1059 }
1060
1061 catch(PappsoException &error)
1062 {
1063 throw error;
1064 }
1065 catch(std::exception &error)
1066 {
1067 qDebug() << QString("Failure %1 ").arg(error.what());
1068 }
1069}
1070
1071
1074{
1075 QMutexLocker locker(&m_mutex);
1076 for(auto &tims_frame : m_timsFrameBaseCache)
1077 {
1078 if(tims_frame.get()->getId() == timsId)
1079 {
1080 m_timsFrameBaseCache.push_back(tims_frame);
1082 m_timsFrameBaseCache.pop_front();
1083 return tims_frame;
1084 }
1085 }
1086
1089 m_timsFrameBaseCache.pop_front();
1090 return m_timsFrameBaseCache.back();
1091}
1092
1095{
1096 qDebug();
1097 QMutexLocker locker(&m_mutex);
1098 for(auto &tims_frame : m_timsFrameCache)
1099 {
1100 if(tims_frame.get()->getId() == timsId)
1101 {
1102 m_timsFrameCache.push_back(tims_frame);
1103 if(m_timsFrameCache.size() > m_cacheSize)
1104 m_timsFrameCache.pop_front();
1105 return tims_frame;
1106 }
1107 }
1108 pappso::TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1109
1110 // locker.relock();
1111 qDebug();
1112
1113 m_timsFrameCache.push_back(frame_sptr);
1114 if(m_timsFrameCache.size() > m_cacheSize)
1115 m_timsFrameCache.pop_front();
1116 qDebug();
1117 return m_timsFrameCache.back();
1118
1119
1120 /*
1121// the frame is not in the cache
1122if(std::find(m_someoneIsLoadingFrameId.begin(),
1123 m_someoneIsLoadingFrameId.end(),
1124 timsId) == m_someoneIsLoadingFrameId.end())
1125 {
1126 // not found, we are alone on this frame
1127 m_someoneIsLoadingFrameId.push_back(timsId);
1128 qDebug();
1129 //locker.unlock();
1130 pappso::TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1131
1132 // locker.relock();
1133 qDebug();
1134 m_someoneIsLoadingFrameId.erase(
1135 std::find(m_someoneIsLoadingFrameId.begin(),
1136 m_someoneIsLoadingFrameId.end(),
1137 timsId));
1138
1139 m_timsFrameCache.push_back(frame_sptr);
1140 if(m_timsFrameCache.size() > m_cacheSize)
1141 m_timsFrameCache.pop_front();
1142 qDebug();
1143 return m_timsFrameCache.back();
1144 }
1145else
1146 {
1147 // this frame is loading by someone else, we have to wait
1148 qDebug();
1149 // locker.unlock();
1150 // std::size_t another_frame_id = timsId;
1151 while(true)
1152 {
1153 QThread::usleep(1);
1154 // locker.relock();
1155
1156 for(auto &tims_frame : m_timsFrameCache)
1157 {
1158 if(tims_frame.get()->getId() == timsId)
1159 {
1160 m_timsFrameCache.push_back(tims_frame);
1161 return tims_frame;
1162 }
1163 }
1164 // locker.unlock();
1165}
1166} // namespace pappso
1167*/
1168}
1169
1170void
1172{
1173 mcsp_ms2Filter = filter;
1174}
1175void
1177{
1178 mcsp_ms1Filter = filter;
1179}
1180
1183 PrecisionPtr precision_ptr)
1184{
1185
1186 qDebug();
1187 XicCoordTims xic_coord_tims_struct;
1188
1189 try
1190 {
1191 if(m_mapXicCoordRecord.size() == 0)
1192 {
1193 QMutexLocker lock(&m_mutex);
1194 // Go get records!
1195
1196 // We proceed in this way:
1197
1198 // 1. For each Precursor reference to the Precursors table's ID
1199 // found in the PasefFrameMsMsInfo table, store the precursor ID for
1200 // step 2.
1201
1202 // 2. From the Precursors table's ID from step 1, get the
1203 // MonoisotopicMz.
1204
1205 // 3. From the PasefFrameMsMsInfo table, for the Precursors table's
1206 // ID reference, get a reference to the Frames table's ID. Thanks to
1207 // the Frames ID, look for the Time value (acquisition retention
1208 // time) for the MS/MS spectrum. The Time value in the Frames tables
1209 // always corresponds to a Frame of MsMsType 8 (that is, MS/MS),
1210 // which is expected since we are looking into MS/MS data.
1211
1212 // 4. From the PasefFrameMsMsInfo table, associate the values
1213 // ScanNumBegin and ScanNumEnd, the mobility bins in which the
1214 // precursor was found.
1215
1216
1217 QSqlDatabase qdb = openDatabaseConnection();
1218 QSqlQuery q = qdb.exec(
1219 QString("SELECT Precursors.id, "
1220 "min(Frames.Time), "
1221 "min(PasefFrameMsMsInfo.ScanNumBegin), "
1222 "max(PasefFrameMsMsInfo.ScanNumEnd), "
1223 "Precursors.MonoisotopicMz "
1224 "FROM "
1225 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1226 "PasefFrameMsMsInfo.Precursor=Precursors.Id INNER JOIN "
1227 "Frames ON PasefFrameMsMsInfo.Frame=Frames.Id "
1228 "GROUP BY Precursors.id;"));
1229 if(q.lastError().isValid())
1230 {
1231 qDebug();
1232 throw PappsoException(
1233 QObject::tr(
1234 "ERROR in TIMS sqlite database file %1, executing SQL "
1235 "command %2:\n%3\n%4\n%5")
1236 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1237 .arg(q.lastQuery())
1238 .arg(qdb.lastError().databaseText())
1239 .arg(qdb.lastError().driverText())
1240 .arg(qdb.lastError().nativeErrorCode()));
1241 }
1242
1243 q.last(); // strange bug : get the last sql record and get back,
1244 // otherwise it will not retrieve all records.
1245 q.first();
1246 // std::size_t i = 0;
1247 do
1248 {
1249 QSqlRecord record = q.record();
1250 m_mapXicCoordRecord.insert(std::pair<std::size_t, QSqlRecord>(
1251 (std::size_t)record.value(0).toULongLong(), record));
1252 }
1253 while(q.next());
1254 }
1255
1256
1257 auto it_map_xiccoord = m_mapXicCoordRecord.find(precursor_id);
1258 if(it_map_xiccoord == m_mapXicCoordRecord.end())
1259 {
1260
1261 throw ExceptionNotFound(
1262 QObject::tr("ERROR Precursors database id %1 not found")
1263 .arg(precursor_id));
1264 }
1265
1266 auto &q = it_map_xiccoord->second;
1267 xic_coord_tims_struct.mzRange =
1268 MzRange(q.value(4).toDouble(), precision_ptr);
1269 xic_coord_tims_struct.scanNumBegin = q.value(2).toUInt();
1270 xic_coord_tims_struct.scanNumEnd = q.value(3).toUInt();
1271 xic_coord_tims_struct.rtTarget = q.value(1).toDouble();
1272 // xic_structure.charge = q.value(5).toUInt();
1273 xic_coord_tims_struct.xicSptr = std::make_shared<Xic>();
1274 }
1275 catch(PappsoException &error)
1276 {
1277 throw error;
1278 }
1279 catch(std::exception &error)
1280 {
1281 qDebug() << QString("Failure %1 ").arg(error.what());
1282 }
1283 return xic_coord_tims_struct;
1284}
1285
1286
1287std::map<quint32, quint32>
1288TimsData::getRawMs2ByPrecursorId(std::size_t precursor_index)
1289{
1290 qDebug();
1291 std::map<quint32, quint32> raw_spectrum;
1292 try
1293 {
1294 QSqlDatabase qdb = openDatabaseConnection();
1295
1296 qdb = openDatabaseConnection();
1297 QSqlQuery q =
1298 qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
1299 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1300 "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
1301 "Precursors.Id=%1;")
1302 .arg(precursor_index));
1303 if(q.lastError().isValid())
1304 {
1305 qDebug();
1306 throw PappsoException(
1307 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1308 "command %2:\n%3\n%4\n%5")
1309 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1310 .arg(q.lastQuery())
1311 .arg(qdb.lastError().databaseText())
1312 .arg(qdb.lastError().driverText())
1313 .arg(qdb.lastError().nativeErrorCode()));
1314 }
1315 qDebug();
1316 // m_mutex.unlock();
1317 if(q.size() == 0)
1318 {
1319
1320 throw ExceptionNotFound(
1321 QObject::tr(
1322 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1323 "id=%1 not found")
1324 .arg(precursor_index));
1325 }
1326 else
1327 {
1328 // qDebug() << " q.size()="<< q.size();
1329 qDebug();
1330 bool first = true;
1331 std::size_t scan_mobility_start = 0;
1332 std::size_t scan_mobility_end = 0;
1333 std::vector<std::size_t> tims_frame_list;
1334
1335 while(q.next())
1336 {
1337 tims_frame_list.push_back(q.value(0).toLongLong());
1338 if(first)
1339 {
1340
1341 scan_mobility_start = q.value(1).toLongLong();
1342 scan_mobility_end = q.value(2).toLongLong();
1343
1344 first = false;
1345 }
1346 }
1347 // QMutexLocker locker(&m_mutex_spectrum);
1348 qDebug();
1349 pappso::TimsFrameCstSPtr tims_frame, previous_frame;
1350 // TracePlusCombiner combiner;
1351 // MapTrace combiner_result;
1352 for(std::size_t tims_id : tims_frame_list)
1353 {
1354 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1355 qDebug();
1356 /*combiner.combine(combiner_result,
1357 tims_frame.get()->cumulateScanToTrace(
1358 scan_mobility_start, scan_mobility_end));*/
1359 if(previous_frame.get() != nullptr)
1360 {
1361 if(previous_frame.get()->hasSameCalibrationData(
1362 *tims_frame.get()))
1363 {
1364 }
1365 else
1366 {
1367 throw ExceptionNotFound(
1368 QObject::tr(
1369 "ERROR in %1 %2, different calibration data "
1370 "between frame id %3 and frame id %4")
1371 .arg(__FILE__)
1372 .arg(__FUNCTION__)
1373 .arg(previous_frame.get()->getId())
1374 .arg(tims_frame.get()->getId()));
1375 }
1376 }
1377 tims_frame.get()->cumulateScansInRawMap(
1378 raw_spectrum, scan_mobility_start, scan_mobility_end);
1379 qDebug();
1380
1381 previous_frame = tims_frame;
1382 }
1383 qDebug() << " precursor_index=" << precursor_index
1384 << " num_rows=" << tims_frame_list.size()
1385 << " sql=" << q.lastQuery() << " "
1386 << (std::size_t)QThread::currentThreadId();
1387 if(first == true)
1388 {
1389 throw ExceptionNotFound(
1390 QObject::tr(
1391 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1392 "id=%1 not found")
1393 .arg(precursor_index));
1394 }
1395 qDebug();
1396 }
1397 }
1398
1399 catch(PappsoException &error)
1400 {
1401 throw PappsoException(QObject::tr("ERROR in %1 (precursor_index=%2):\n%3")
1402 .arg(__FUNCTION__)
1403 .arg(precursor_index)
1404 .arg(error.qwhat()));
1405 }
1406 catch(std::exception &error)
1407 {
1408 qDebug() << QString("Failure %1 ").arg(error.what());
1409 }
1410 return raw_spectrum;
1411 qDebug();
1412}
1413
1414
1415void
1417 const MsRunIdCstSPtr &msrun_id,
1418 QualifiedMassSpectrum &mass_spectrum,
1419 const SpectrumDescr &spectrum_descr,
1420 bool want_binary_data)
1421{
1422 try
1423 {
1424 qDebug();
1425 MassSpectrumId spectrum_id;
1426
1427 spectrum_id.setSpectrumIndex(spectrum_descr.ms2_index);
1428 spectrum_id.setNativeId(QString("precursor=%1 idxms2=%2")
1429 .arg(spectrum_descr.precursor_id)
1430 .arg(spectrum_descr.ms2_index));
1431 spectrum_id.setMsRunId(msrun_id);
1432
1433 mass_spectrum.setMassSpectrumId(spectrum_id);
1434
1435 mass_spectrum.setMsLevel(2);
1436 qDebug() << "spectrum_descr.precursor_id=" << spectrum_descr.precursor_id
1437 << " spectrum_descr.ms1_index=" << spectrum_descr.ms1_index
1438 << " spectrum_descr.ms2_index=" << spectrum_descr.ms2_index;
1439 mass_spectrum.setPrecursorSpectrumIndex(spectrum_descr.ms1_index);
1440
1441 mass_spectrum.setEmptyMassSpectrum(true);
1442
1443 qDebug();
1444
1445
1446 mass_spectrum.appendPrecursorIonData(spectrum_descr.precursor_ion_data);
1447
1448 mass_spectrum.setPrecursorNativeId(
1449 QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
1450 .arg(spectrum_descr.parent_frame)
1451 .arg(spectrum_descr.scan_mobility_start)
1452 .arg(spectrum_descr.scan_mobility_end)
1453 .arg(spectrum_descr.precursor_id)
1454 .arg(spectrum_descr.ms1_index));
1455
1456 mass_spectrum.setParameterValue(
1458 spectrum_descr.isolationMz);
1459 mass_spectrum.setParameterValue(
1461 spectrum_descr.isolationWidth);
1462
1463 mass_spectrum.setParameterValue(
1465 spectrum_descr.collisionEnergy);
1466 mass_spectrum.setParameterValue(
1468 (quint64)spectrum_descr.precursor_id);
1469
1470 // QMutexLocker locker(&m_mutex_spectrum);
1471 qDebug();
1472 pappso::TimsFrameBaseCstSPtr tims_frame, previous_frame;
1473 // TracePlusCombiner combiner;
1474 // MapTrace combiner_result;
1475 std::map<quint32, quint32> raw_spectrum;
1476 bool first = true;
1477 for(std::size_t tims_id : spectrum_descr.tims_frame_list)
1478 {
1479 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1480 << " tims_id=" << tims_id
1481 << (std::size_t)QThread::currentThreadId();
1482 ;
1483 if(want_binary_data)
1484 {
1485 qDebug() << "bindec";
1486 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1487 }
1488 else
1489 {
1490 tims_frame = getTimsFrameBaseCstSPtrCached(tims_id);
1491 }
1492 qDebug() << (std::size_t)QThread::currentThreadId();
1493 ;
1494 if(first)
1495 {
1496 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1497
1498 mass_spectrum.setParameterValue(
1500 tims_frame.get()->getOneOverK0Transformation(
1501 spectrum_descr.scan_mobility_start));
1502
1503 mass_spectrum.setParameterValue(
1505 tims_frame.get()->getOneOverK0Transformation(
1506 spectrum_descr.scan_mobility_end));
1507
1508 first = false;
1509 }
1510
1511
1512 if(want_binary_data)
1513 {
1514 qDebug();
1515 /*combiner.combine(combiner_result,
1516 tims_frame.get()->cumulateScanToTrace(
1517 scan_mobility_start, scan_mobility_end));*/
1518 if(previous_frame.get() != nullptr)
1519 {
1520 if(previous_frame.get()->hasSameCalibrationData(
1521 *tims_frame.get()))
1522 {
1523 }
1524 else
1525 {
1526 throw ExceptionNotFound(
1527 QObject::tr(
1528 "ERROR in %1 %2, different calibration data "
1529 "between frame id %3 and frame id %4")
1530 .arg(__FILE__)
1531 .arg(__FUNCTION__)
1532 .arg(previous_frame.get()->getId())
1533 .arg(tims_frame.get()->getId()));
1534 }
1535 }
1536 qDebug() << (std::size_t)QThread::currentThreadId();
1537 ;
1538 tims_frame.get()->cumulateScansInRawMap(
1539 raw_spectrum,
1540 spectrum_descr.scan_mobility_start,
1541 spectrum_descr.scan_mobility_end);
1542 qDebug() << (std::size_t)QThread::currentThreadId();
1543 ;
1544 }
1545 previous_frame = tims_frame;
1546 }
1547 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1548 << " num_rows=" << spectrum_descr.tims_frame_list.size()
1549 << (std::size_t)QThread::currentThreadId();
1550 if(first == true)
1551 {
1552 throw ExceptionNotFound(
1553 QObject::tr(
1554 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1555 "id=%1 not found")
1556 .arg(spectrum_descr.precursor_id));
1557 }
1558 if(want_binary_data)
1559 {
1560 qDebug() << " precursor_index=" << spectrum_descr.precursor_id;
1561 // peak_pick.filter(trace);
1562 pappso::Trace trace;
1564 {
1565 trace =
1566 tims_frame.get()->getTraceFromCumulatedScansBuiltinCentroid(
1567 raw_spectrum);
1568 }
1569 else
1570 {
1571 // no builtin centroid:
1572
1573 trace =
1574 tims_frame.get()->getTraceFromCumulatedScans(raw_spectrum);
1575 }
1576
1577 if(trace.size() > 0)
1578 {
1579 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1580 << " " << trace.size() << " "
1581 << (std::size_t)QThread::currentThreadId();
1582
1583 if(mcsp_ms2Filter != nullptr)
1584 {
1585 // FilterTriangle filter;
1586 // filter.setTriangleSlope(50, 0.02);
1587 // filter.filter(trace);
1588 // trace.filter(pappso::FilterHighPass(10));
1589 mcsp_ms2Filter->filter(trace);
1590 }
1591
1592 // FilterScaleFactorY filter_scale((double)1 /
1593 // (double)tims_frame_list.size());
1594 // filter_scale.filter(trace);
1595 qDebug() << " precursor_index=" << spectrum_descr.precursor_id;
1596 mass_spectrum.setMassSpectrumSPtr(
1597 MassSpectrum(trace).makeMassSpectrumSPtr());
1598 mass_spectrum.setEmptyMassSpectrum(false);
1599 }
1600 else
1601 {
1602 mass_spectrum.setMassSpectrumSPtr(nullptr);
1603 mass_spectrum.setEmptyMassSpectrum(true);
1604 }
1605
1606 qDebug();
1607 }
1608 qDebug();
1609 }
1610
1611 catch(PappsoException &error)
1612 {
1613 throw PappsoException(
1614 QObject::tr("ERROR in %1 (ms2_index=%2 precursor_index=%3):\n%4")
1615 .arg(__FUNCTION__)
1616 .arg(spectrum_descr.ms2_index)
1617 .arg(spectrum_descr.precursor_id)
1618 .arg(error.qwhat()));
1619 }
1620 catch(std::exception &error)
1621 {
1622 qDebug() << QString("Failure %1 ").arg(error.what());
1623 }
1624 qDebug();
1625}
1626
1627void
1629 const MsRunIdCstSPtr &msrun_id,
1631 unsigned int ms_level)
1632{
1633 qDebug() << " ms_level=" << ms_level;
1634 if(!m_hasPrecursorTable)
1635 {
1636 throw PappsoException(
1637 QObject::tr("unable to read spectrum list : this data file does not "
1638 "contain MS2 data, no precursor found."));
1639 }
1640
1641 QSqlDatabase qdb = openDatabaseConnection();
1642 QSqlQuery qprecursor_list = qdb.exec(QString(
1643 "SELECT PasefFrameMsMsInfo.Frame, " // 0
1644 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
1645 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
1646 "PasefFrameMsMsInfo.IsolationMz, " // 3
1647 "PasefFrameMsMsInfo.IsolationWidth, " // 4
1648 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
1649 "PasefFrameMsMsInfo.Precursor, " // 6
1650 "Precursors.Id, " // 7
1651 "Precursors.LargestPeakMz, " // 8
1652 "Precursors.AverageMz, " // 9
1653 "Precursors.MonoisotopicMz, " // 10
1654 "Precursors.Charge, " // 11
1655 "Precursors.ScanNumber, " // 12
1656 "Precursors.Intensity, " // 13
1657 "Precursors.Parent " // 14
1658 "FROM PasefFrameMsMsInfo "
1659 "INNER JOIN Precursors ON "
1660 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
1661 "ORDER BY PasefFrameMsMsInfo.Precursor, PasefFrameMsMsInfo.Frame ;"));
1662 if(qprecursor_list.lastError().isValid())
1663 {
1664
1665 throw PappsoException(
1666 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1667 "command %2:\n%3\n%4\n%5")
1668 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1669 .arg(qprecursor_list.lastQuery())
1670 .arg(qdb.lastError().databaseText())
1671 .arg(qdb.lastError().driverText())
1672 .arg(qdb.lastError().nativeErrorCode()));
1673 }
1674
1675
1676 qDebug() << "qprecursor_list.size()=" << qprecursor_list.size();
1677 qDebug() << QObject::tr(
1678 "TIMS sqlite database file %1, executing SQL "
1679 "command %2:\n%3\n%4\n%5")
1680 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1681 .arg(qprecursor_list.lastQuery())
1682 .arg(qdb.lastError().databaseText())
1683 .arg(qdb.lastError().driverText())
1684 .arg(qdb.lastError().nativeErrorCode());
1685
1686 qDebug() << "qprecursor_list.isActive()=" << qprecursor_list.isActive();
1687 qDebug() << "qprecursor_list.isSelect()=" << qprecursor_list.isSelect();
1688 bool first = true;
1689 SpectrumDescr spectrum_descr;
1690 /*
1691std::size_t i = 0;
1692while(qprecursor_list.next())
1693 {
1694 qDebug() << "i=" << i;
1695 i++;
1696 }*/
1697 qprecursor_list.last(); // strange bug : get the last sql record and get
1698 // back, unless it will not retrieve all records.
1699
1700 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
1701 qprecursor_list.first();
1702 std::vector<pappso::TimsData::SpectrumDescr> spectrum_description_list;
1703 spectrum_descr.precursor_id = 0;
1704 // std::size_t i = 0;
1705
1706 do
1707 {
1708
1709 if(spectrum_descr.precursor_id !=
1710 (std::size_t)qprecursor_list.value(6).toLongLong())
1711 {
1712 // new precursor
1713 if(spectrum_descr.precursor_id > 0)
1714 {
1715 spectrum_description_list.push_back(spectrum_descr);
1716 }
1717
1718 spectrum_descr.tims_frame_list.clear();
1719 first = true;
1720 }
1721 qDebug() << " qprecursor_list.value(6).toLongLong() ="
1722 << qprecursor_list.value(6).toLongLong();
1723 spectrum_descr.precursor_id =
1724 (std::size_t)qprecursor_list.value(6).toLongLong();
1725 qDebug() << " spectrum_descr.precursor_id ="
1726 << spectrum_descr.precursor_id;
1727 qDebug() << " cumul tims frame:" << qprecursor_list.value(0).toLongLong();
1728 spectrum_descr.tims_frame_list.push_back(
1729 qprecursor_list.value(0).toLongLong());
1730 qDebug() << " first =" << first;
1731 if(first)
1732 {
1733 qDebug();
1734 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1735 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1736 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1737 spectrum_descr.precursor_ion_data =
1738 PrecursorIonData(qprecursor_list.value(10).toDouble(),
1739 qprecursor_list.value(11).toInt(),
1740 qprecursor_list.value(13).toDouble());
1741
1742 // spectrum_descr.precursor_id = q.value(6).toLongLong();
1743 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1744 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1745
1746 spectrum_descr.scan_mobility_start =
1747 qprecursor_list.value(1).toLongLong();
1748 spectrum_descr.scan_mobility_end =
1749 qprecursor_list.value(2).toLongLong();
1750
1751 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
1752 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
1753 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
1754 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
1755
1756
1757 first = false;
1758 }
1759 // qDebug() << "qprecursor_list.executedQuery()="
1760 // << qprecursor_list.executedQuery();
1761 // qDebug() << "qprecursor_list.last()=" << qprecursor_list.last();
1762 // i++;
1763 }
1764 while(qprecursor_list.next());
1765
1766 // last One
1767
1768 // new precursor
1769 if(spectrum_descr.precursor_id > 0)
1770 {
1771 spectrum_description_list.push_back(spectrum_descr);
1772 }
1773
1774
1775 QString local_filepath = m_timsDataDirectory.absoluteFilePath("analysis.tdf");
1776
1777 if(m_isMonoThread)
1778 {
1779 for(SpectrumDescr &spectrum_descr : spectrum_description_list)
1780 {
1781
1782 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1783 ms2ReaderGenerateMS1MS2Spectrum(
1784 msrun_id, mass_spectrum_list, handler, spectrum_descr, ms_level);
1785
1786 for(auto &qualified_spectrum : mass_spectrum_list)
1787 {
1788 handler.setQualifiedMassSpectrum(qualified_spectrum);
1789 }
1790
1791 if(handler.shouldStop())
1792 {
1793 qDebug() << "The operation was cancelled. Breaking the loop.";
1795 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
1796 .arg(local_filepath));
1797 }
1798 }
1799 }
1800 else
1801 {
1802
1803
1804 TimsData *itself = this;
1805 pappso::SpectrumCollectionHandlerInterface *pointer_handler = &handler;
1806
1807
1808 std::function<std::vector<QualifiedMassSpectrum>(
1810 map_function_generate_spectrum =
1811 [itself, msrun_id, pointer_handler, ms_level](
1812 const pappso::TimsData::SpectrumDescr &spectrum_descr)
1813 -> std::vector<QualifiedMassSpectrum> {
1814 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1815 itself->ms2ReaderGenerateMS1MS2Spectrum(msrun_id,
1816 mass_spectrum_list,
1817 *pointer_handler,
1818 spectrum_descr,
1819 ms_level);
1820
1821
1822 return mass_spectrum_list;
1823 };
1824
1825 std::function<void(
1826 std::size_t,
1827 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list)>
1828 reduce_function_spectrum_list =
1829 [pointer_handler, local_filepath](
1830 std::size_t res,
1831 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list) {
1832 for(auto &qualified_spectrum : qualified_spectrum_list)
1833 {
1834 pointer_handler->setQualifiedMassSpectrum(qualified_spectrum);
1835 }
1836
1837 if(pointer_handler->shouldStop())
1838 {
1839 qDebug() << "The operation was cancelled. Breaking the loop.";
1841 QObject::tr("reading TimsTOF job on %1 cancelled by the user")
1842 .arg(local_filepath));
1843 }
1844 res++;
1845 };
1846
1847
1848 QFuture<std::size_t> res;
1849 res = QtConcurrent::mappedReduced<std::size_t>(
1850 spectrum_description_list.begin(),
1851 spectrum_description_list.end(),
1852 map_function_generate_spectrum,
1853 reduce_function_spectrum_list,
1854 QtConcurrent::OrderedReduce);
1855 res.waitForFinished();
1856 }
1857 handler.loadingEnded();
1858 mpa_timsBinDec->closeLinearRead();
1859}
1860
1861
1862void
1864 const MsRunIdCstSPtr &msrun_id,
1865 std::vector<QualifiedMassSpectrum> &qualified_mass_spectrum_list,
1867 const pappso::TimsData::SpectrumDescr &spectrum_descr,
1868 unsigned int ms_level)
1869{
1870
1871 qDebug() << " ms_level=" << ms_level;
1872 // The handler will receive the index of the mass spectrum in the
1873 // current run via the mass spectrum id member datum.
1874 if((ms_level == 0) || (ms_level == 1))
1875 {
1876 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1877 getQualifiedMs1MassSpectrumByPrecursorId(
1878 msrun_id,
1879 qualified_mass_spectrum_list.back(),
1880 spectrum_descr,
1881 handler.needMsLevelPeakList(1));
1882 }
1883 if((ms_level == 0) || (ms_level == 2))
1884 {
1885 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1886 getQualifiedMs2MassSpectrumByPrecursorId(
1887 msrun_id,
1888 qualified_mass_spectrum_list.back(),
1889 spectrum_descr,
1890 handler.needMsLevelPeakList(2));
1891 }
1892 qDebug();
1893}
1894
1895
1898{
1899
1900 SpectrumDescr spectrum_descr;
1901 QSqlDatabase qdb = openDatabaseConnection();
1902 QSqlQuery q = qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
1903 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
1904 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
1905 "PasefFrameMsMsInfo.IsolationMz, " // 3
1906 "PasefFrameMsMsInfo.IsolationWidth, " // 4
1907 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
1908 "PasefFrameMsMsInfo.Precursor, " // 6
1909 "Precursors.Id, " // 7
1910 "Precursors.LargestPeakMz, " // 8
1911 "Precursors.AverageMz, " // 9
1912 "Precursors.MonoisotopicMz, " // 10
1913 "Precursors.Charge, " // 11
1914 "Precursors.ScanNumber, " // 12
1915 "Precursors.Intensity, " // 13
1916 "Precursors.Parent " // 14
1917 "FROM PasefFrameMsMsInfo "
1918 "INNER JOIN Precursors ON "
1919 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
1920 "WHERE Precursors.Id=%1;")
1921 .arg(precursor_id));
1922 if(q.lastError().isValid())
1923 {
1924
1925 throw PappsoException(
1926 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1927 "command %2:\n%3\n%4\n%5")
1928 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1929 .arg(q.lastQuery())
1930 .arg(qdb.lastError().databaseText())
1931 .arg(qdb.lastError().driverText())
1932 .arg(qdb.lastError().nativeErrorCode()));
1933 }
1934
1935
1936 bool first = true;
1937 while(q.next())
1938 {
1939
1940 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
1941 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
1942 if(first)
1943 {
1944 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1945 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1946 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1947 spectrum_descr.precursor_ion_data =
1948 PrecursorIonData(q.value(10).toDouble(),
1949 q.value(11).toInt(),
1950 q.value(13).toDouble());
1951
1952 spectrum_descr.precursor_id = q.value(6).toLongLong();
1953 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1954 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1955
1956 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
1957 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
1958
1959 spectrum_descr.isolationMz = q.value(3).toDouble();
1960 spectrum_descr.isolationWidth = q.value(4).toDouble();
1961 spectrum_descr.collisionEnergy = q.value(5).toFloat();
1962 spectrum_descr.parent_frame = q.value(14).toLongLong();
1963
1964
1965 first = false;
1966 }
1967 }
1968 if(spectrum_descr.precursor_id == 0)
1969 {
1970 throw ExceptionNotFound(
1971 QObject::tr("ERROR in %1 %2 : precursor id (%3) NOT FOUND ")
1972 .arg(__FILE__)
1973 .arg(__FUNCTION__)
1974 .arg(precursor_id));
1975 }
1976 return spectrum_descr;
1977}
1978
1979std::vector<double>
1981{
1982 std::vector<double> timeline;
1983 timeline.reserve(m_mapFramesRecord.size());
1984 for(const TimsFrameRecord &frame_record : m_mapFramesRecord)
1985 {
1986 if(frame_record.mz_calibration_id != 0)
1987 {
1988 timeline.push_back(frame_record.frame_time);
1989 }
1990 }
1991 return timeline;
1992}
1993
1996 const std::pair<std::size_t, std::size_t> &scan_coordinate)
1997{
1998
1999 SpectrumDescr spectrum_descr;
2000 QSqlDatabase qdb = openDatabaseConnection();
2001 QSqlQuery q =
2002 qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
2003 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2004 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2005 "PasefFrameMsMsInfo.IsolationMz, " // 3
2006 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2007 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2008 "PasefFrameMsMsInfo.Precursor, " // 6
2009 "Precursors.Id, " // 7
2010 "Precursors.LargestPeakMz, " // 8
2011 "Precursors.AverageMz, " // 9
2012 "Precursors.MonoisotopicMz, " // 10
2013 "Precursors.Charge, " // 11
2014 "Precursors.ScanNumber, " // 12
2015 "Precursors.Intensity, " // 13
2016 "Precursors.Parent " // 14
2017 "FROM PasefFrameMsMsInfo "
2018 "INNER JOIN Precursors ON "
2019 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2020 "WHERE "
2021 "PasefFrameMsMsInfo.Frame=%1 and "
2022 "(PasefFrameMsMsInfo.ScanNumBegin "
2023 "<= %2 and PasefFrameMsMsInfo.ScanNumEnd >= %2);")
2024 .arg(scan_coordinate.first)
2025 .arg(scan_coordinate.second));
2026 if(q.lastError().isValid())
2027 {
2028
2029 throw PappsoException(
2030 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2031 "command %2:\n%3\n%4\n%5")
2032 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2033 .arg(q.lastQuery())
2034 .arg(qdb.lastError().databaseText())
2035 .arg(qdb.lastError().driverText())
2036 .arg(qdb.lastError().nativeErrorCode()));
2037 }
2038
2039 if(q.next())
2040 {
2041
2042 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
2043 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
2044 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2045 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2046 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2047 spectrum_descr.precursor_ion_data = PrecursorIonData(
2048 q.value(10).toDouble(), q.value(11).toInt(), q.value(13).toDouble());
2049
2050 spectrum_descr.precursor_id = q.value(6).toLongLong();
2051 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2052 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2053
2054 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
2055 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
2056
2057 spectrum_descr.isolationMz = q.value(3).toDouble();
2058 spectrum_descr.isolationWidth = q.value(4).toDouble();
2059 spectrum_descr.collisionEnergy = q.value(5).toFloat();
2060 spectrum_descr.parent_frame = q.value(14).toLongLong();
2061 }
2062 return spectrum_descr;
2063}
2064
2065
2066void
2068 pappso::TimsData::SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
2069{
2070
2071 spectrum_descr.tims_frame_list.clear();
2072 spectrum_descr.tims_frame_list.push_back(
2073 qprecursor_list.value(0).toLongLong());
2074 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2075 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2076 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2077 spectrum_descr.precursor_ion_data =
2078 PrecursorIonData(qprecursor_list.value(10).toDouble(),
2079 qprecursor_list.value(11).toInt(),
2080 qprecursor_list.value(13).toDouble());
2081
2082 spectrum_descr.precursor_id = qprecursor_list.value(6).toLongLong();
2083 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2084 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2085
2086 spectrum_descr.scan_mobility_start = qprecursor_list.value(1).toLongLong();
2087 spectrum_descr.scan_mobility_end = qprecursor_list.value(2).toLongLong();
2088
2089 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
2090 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
2091 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
2092 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
2093}
2094
2095
2096void
2098 const pappso::MsRunIdCstSPtr &msrun_id,
2100 unsigned int ms_level)
2101{
2102
2103 if(!m_hasPrecursorTable)
2104 {
2105 throw PappsoException(
2106 QObject::tr("unable to read spectrum list : this data file does not "
2107 "contain MS2 data, no precursor found."));
2108 }
2109
2110 // We'll need it to perform the looping in the spectrum list.
2111 std::size_t spectrum_list_size = getTotalNumberOfScans();
2112
2113 // qDebug() << "The spectrum list has size:" << spectrum_list_size;
2114
2115 // Inform the handler of the spectrum list so that it can handle feedback to
2116 // the user.
2117 handler.spectrumListHasSize(spectrum_list_size);
2118
2119 QSqlDatabase qdb = openDatabaseConnection();
2120 QSqlQuery qprecursor_list = qdb.exec(QString(
2121 "SELECT DISTINCT "
2122 "PasefFrameMsMsInfo.Frame, " // 0
2123 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2124 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2125 "PasefFrameMsMsInfo.IsolationMz, " // 3
2126 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2127 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2128 "PasefFrameMsMsInfo.Precursor, " // 6
2129 "Precursors.Id, " // 7
2130 "Precursors.LargestPeakMz, " // 8
2131 "Precursors.AverageMz, " // 9
2132 "Precursors.MonoisotopicMz, " // 10
2133 "Precursors.Charge, " // 11
2134 "Precursors.ScanNumber, " // 12
2135 "Precursors.Intensity, " // 13
2136 "Precursors.Parent " // 14
2137 "FROM PasefFrameMsMsInfo "
2138 "INNER JOIN Precursors ON "
2139 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2140 "ORDER BY PasefFrameMsMsInfo.Frame, PasefFrameMsMsInfo.ScanNumBegin ;"));
2141 if(qprecursor_list.lastError().isValid())
2142 {
2143 throw PappsoException(
2144 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2145 "command %2:\n%3\n%4\n%5")
2146 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2147 .arg(qprecursor_list.lastQuery())
2148 .arg(qdb.lastError().databaseText())
2149 .arg(qdb.lastError().driverText())
2150 .arg(qdb.lastError().nativeErrorCode()));
2151 }
2152
2153
2154 std::size_t i = 0; // iterate on each Spectrum
2155
2156 qprecursor_list.last(); // strange bug : get the last sql record and get
2157 // back, unless it will not retrieve all records.
2158
2159 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
2160 qprecursor_list.first();
2161
2162 TimsFrameBaseCstSPtr tims_frame;
2163 SpectrumDescr spectrum_descr;
2164
2165 for(FrameIdDescr &current_frame : m_frameIdDescrList)
2166 {
2167
2168 // If the user of this reader instance wants to stop reading the
2169 // spectra, then break this loop.
2170 if(handler.shouldStop())
2171 {
2172 qDebug() << "The operation was cancelled. Breaking the loop.";
2174 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
2175 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf")));
2176 }
2177
2178 tims_frame = getTimsFrameBaseCstSPtrCached(current_frame.m_frameId);
2179 unsigned int tims_ms_level = tims_frame.get()->getMsLevel();
2180
2181 if((ms_level != 0) && (ms_level != tims_ms_level))
2182 { // bypass
2183 i += current_frame.m_size;
2184 }
2185 else
2186 {
2187 bool want_binary_data = handler.needMsLevelPeakList(tims_ms_level);
2188 qDebug() << "want_binary_data=" << want_binary_data;
2189 if(want_binary_data)
2190 {
2191 qDebug() << "bindec";
2192 tims_frame = getTimsFrameCstSPtrCached(current_frame.m_frameId);
2193 }
2194
2195 bool possible_precursor = false;
2196 if(tims_ms_level == 2)
2197 {
2198 // seek the precursor record:
2199 while(qprecursor_list.value(0).toULongLong() <
2200 current_frame.m_frameId)
2201 {
2202 qprecursor_list.next();
2203
2204 if(qprecursor_list.value(0).toULongLong() ==
2205 current_frame.m_frameId)
2206 {
2207 possible_precursor = true;
2208 }
2209 fillSpectrumDescriptionWithSqlRecord(spectrum_descr,
2210 qprecursor_list);
2211 }
2212 }
2213
2214 for(std::size_t scan_num = 0; scan_num < current_frame.m_size;
2215 scan_num++)
2216 {
2217 bool has_a_precursor = false;
2218 if(possible_precursor)
2219 {
2220 if(spectrum_descr.scan_mobility_end < scan_num)
2221 {
2222 // seek the precursor record:
2223 while(qprecursor_list.value(0).toULongLong() <
2224 current_frame.m_frameId)
2225 {
2226 qprecursor_list.next();
2227
2228 if(qprecursor_list.value(0).toULongLong() !=
2229 current_frame.m_frameId)
2230 {
2231 possible_precursor = false;
2232 }
2233 fillSpectrumDescriptionWithSqlRecord(spectrum_descr,
2234 qprecursor_list);
2235 }
2236 }
2237
2238 if(possible_precursor &&
2239 (spectrum_descr.scan_mobility_start < scan_num))
2240 {
2241 // we are in
2242 has_a_precursor = true;
2243 }
2244 } // end to determine if we are in a precursor for this
2245 // spectrum
2246
2247 QualifiedMassSpectrum mass_spectrum;
2248
2249
2250 MassSpectrumId spectrum_id;
2251
2252 spectrum_id.setSpectrumIndex(i);
2253 spectrum_id.setMsRunId(msrun_id);
2254 spectrum_id.setNativeId(QString("frame=%1 scan=%2 index=%3")
2255 .arg(current_frame.m_frameId)
2256 .arg(scan_num)
2257 .arg(i));
2258
2259 mass_spectrum.setMassSpectrumId(spectrum_id);
2260
2261 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
2262 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
2263
2264 mass_spectrum.setDtInMilliSeconds(
2265 tims_frame.get()->getDriftTime(scan_num));
2266 // 1/K0
2267 mass_spectrum.setParameterValue(
2269 tims_frame.get()->getOneOverK0Transformation(scan_num));
2270
2271 mass_spectrum.setEmptyMassSpectrum(true);
2272 if(want_binary_data)
2273 {
2274 try
2275 {
2276 mass_spectrum.setMassSpectrumSPtr(
2277 tims_frame.get()->getMassSpectrumSPtr(scan_num));
2278 }
2279 catch(PappsoException &error)
2280 {
2281 throw PappsoException(
2282 QObject::tr(
2283 "ERROR in %1 (scan_num=%2 spectrum_index=%3):\n%4")
2284 .arg(__FUNCTION__)
2285 .arg(scan_num)
2286 .arg(spectrum_id.getSpectrumIndex())
2287 .arg(error.qwhat()));
2288 }
2289 if(mass_spectrum.size() > 0)
2290 {
2291 mass_spectrum.setEmptyMassSpectrum(false);
2292 }
2293 }
2294 else
2295 {
2296 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
2297 //{
2298 mass_spectrum.setEmptyMassSpectrum(false);
2299 // }
2300 }
2301 if(has_a_precursor)
2302 {
2303 if(spectrum_descr.precursor_id > 0)
2304 {
2305
2306 mass_spectrum.appendPrecursorIonData(
2307 spectrum_descr.precursor_ion_data);
2308
2309 std::size_t prec_spectrum_index =
2310 getRawIndexFromCoordinate(spectrum_descr.parent_frame,
2311 scan_num);
2312
2313 mass_spectrum.setPrecursorSpectrumIndex(
2314 prec_spectrum_index);
2315 mass_spectrum.setPrecursorNativeId(
2316 QString("frame=%1 scan=%2 index=%3")
2317 .arg(spectrum_descr.parent_frame)
2318 .arg(scan_num)
2319 .arg(prec_spectrum_index));
2320
2321 mass_spectrum.setParameterValue(
2323 spectrum_descr.isolationMz);
2324 mass_spectrum.setParameterValue(
2326 spectrum_descr.isolationWidth);
2327
2328 mass_spectrum.setParameterValue(
2330 spectrum_descr.collisionEnergy);
2331 mass_spectrum.setParameterValue(
2333 (quint64)spectrum_descr.precursor_id);
2334 }
2335 }
2336
2337 handler.setQualifiedMassSpectrum(mass_spectrum);
2338 i++;
2339 }
2340 }
2341 }
2342}
2343
2344std::map<quint32, quint32>
2345TimsData::getRawMsBySpectrumIndex(std::size_t spectrum_index)
2346{
2347
2348 qDebug() << " spectrum_index=" << spectrum_index;
2349 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
2350 TimsFrameBaseCstSPtr tims_frame;
2351 tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
2352
2353 std::map<quint32, quint32> raw_spectrum;
2354 tims_frame.get()->cumulateScansInRawMap(
2355 raw_spectrum, coordinate.second, coordinate.second);
2356 return raw_spectrum;
2357}
2358
2359
2360const std::vector<FrameIdDescr> &
2362{
2363 return m_frameIdDescrList;
2364}
2365
2366
2367} // 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: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:1628
TimsFrameCstSPtr getTimsFrameCstSPtrCached(std::size_t timsId)
get a Tims frame with his database ID but look in the cache first
Definition: timsdata.cpp:1094
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:972
virtual ~TimsData()
Definition: timsdata.cpp:269
SpectrumDescr getSpectrumDescrWithPrecursorId(std::size_t precursor_id)
get an intermediate structure describing a spectrum
Definition: timsdata.cpp:1897
const std::vector< FrameIdDescr > & getFrameIdDescrList() const
Definition: timsdata.cpp:2361
std::size_t getTotalNumberOfFrames() const
Get total number of frames.
Definition: timsdata.cpp:624
void getQualifiedMs2MassSpectrumByPrecursorId(const MsRunIdCstSPtr &msrun_id, QualifiedMassSpectrum &mass_spectrum, const SpectrumDescr &spectrum_descr, bool want_binary_data)
Definition: timsdata.cpp:1416
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:1288
std::size_t m_totalNumberOfFrames
Definition: timsdata.h:309
Trace getTicChromatogram() const
Definition: timsdata.cpp:888
TimsFrameBaseCstSPtr getTimsFrameBaseCstSPtrCached(std::size_t timsId)
Definition: timsdata.cpp:1073
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:614
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:340
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:644
void fillSpectrumDescriptionWithSqlRecord(SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
Definition: timsdata.cpp:2067
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:283
std::vector< std::size_t > getClosestPrecursorIdByMz(std::vector< std::vector< double > > ids, double mz_value)
Definition: timsdata.cpp:749
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: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:2097
QDir m_timsDataDirectory
Definition: timsdata.h:304
std::size_t getTotalNumberOfPrecursors() const
get the number of precursors analyzes by PASEF
Definition: timsdata.cpp:638
MzCalibrationStore * mpa_mzCalibrationStore
Definition: timsdata.h:327
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:1980
unsigned int getMsLevelBySpectrumIndex(std::size_t spectrum_index)
Definition: timsdata.cpp:773
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:1995
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:2345
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:1863
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:782
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:1176
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:1171
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:631
std::vector< std::size_t > getMatchPrecursorIdByKo(std::vector< std::vector< double > > ids, double ko_value)
Definition: timsdata.cpp:723
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:314
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:1182
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: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: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: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