libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
timsdata.cpp
Go to the documentation of this file.
1/**
2 * \file pappsomspp/vendors/tims/timsdata.cpp
3 * \date 27/08/2019
4 * \author Olivier Langella
5 * \brief main Tims data handler
6 */
7
8/*******************************************************************************
9 * Copyright (c) 2019 Olivier Langella <Olivier.Langella@u-psud.fr>.
10 *
11 * This file is part of the PAPPSOms++ library.
12 *
13 * PAPPSOms++ is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * PAPPSOms++ is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with PAPPSOms++. If not, see <http://www.gnu.org/licenses/>.
25 *
26 ******************************************************************************/
27
28#include "timsdata.h"
29#include "../../exception/exceptionnotfound.h"
30#include "../../exception/exceptioninterrupted.h"
31#include "../../processing/combiners/tracepluscombiner.h"
32#include "../../processing/filters/filtertriangle.h"
33#include "../../processing/filters/filtersuitestring.h"
34#include <QDebug>
35#include <QSqlError>
36#include <QSqlQuery>
37#include <QSqlRecord>
38#include <QMutexLocker>
39#include <QThread>
40#include <set>
41#include <QtConcurrent>
42
43namespace pappso
44{
45
46TimsData::TimsData(QDir timsDataDirectory)
47 : m_timsDataDirectory(timsDataDirectory)
48{
49
50 qDebug() << "Start of construction of TimsData";
52 if(!m_timsDataDirectory.exists())
53 {
54 throw PappsoException(
55 QObject::tr("ERROR TIMS data directory %1 not found")
56 .arg(m_timsDataDirectory.absolutePath()));
57 }
58
59 if(!QFileInfo(m_timsDataDirectory.absoluteFilePath("analysis.tdf")).exists())
60 {
61
62 throw PappsoException(
63 QObject::tr("ERROR TIMS data directory, %1 sqlite file not found")
64 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf")));
65 }
66
67 // Open the database
68 QSqlDatabase qdb = openDatabaseConnection();
69
70
71 QSqlQuery q(qdb);
72 if(!q.exec("select Key, Value from GlobalMetadata where "
73 "Key='TimsCompressionType';"))
74 {
75
76 qDebug();
77 throw PappsoException(
78 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
79 "command %2:\n%3\n%4\n%5")
80 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
81 .arg(q.lastQuery())
82 .arg(q.lastError().databaseText())
83 .arg(q.lastError().driverText())
84 .arg(q.lastError().nativeErrorCode()));
85 }
86
87
88 int compression_type = 0;
89 if(q.next())
90 {
91 compression_type = q.value(1).toInt();
92 }
93 qDebug() << " compression_type=" << compression_type;
95 QFileInfo(m_timsDataDirectory.absoluteFilePath("analysis.tdf_bin")),
96 compression_type);
97
98 qDebug();
99
100 // get number of precursors
102 if(!q.exec("SELECT COUNT( DISTINCT Id) FROM Precursors;"))
103 {
104 m_hasPrecursorTable = false;
105 }
106 else
107 {
108 m_hasPrecursorTable = true;
109 if(q.next())
110 {
111 m_totalNumberOfPrecursors = q.value(0).toLongLong();
112 }
113 }
114
115
117
118 // get number of scans
119 if(!q.exec("SELECT SUM(NumScans),COUNT(Id) FROM Frames"))
120 {
121 qDebug();
122 throw PappsoException(
123 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
124 "command %2:\n%3\n%4\n%5")
125 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
126 .arg(q.lastQuery())
127 .arg(qdb.lastError().databaseText())
128 .arg(qdb.lastError().driverText())
129 .arg(qdb.lastError().nativeErrorCode()));
130 }
131 if(q.next())
132 {
133 m_totalNumberOfScans = q.value(0).toLongLong();
134 m_totalNumberOfFrames = q.value(1).toLongLong();
135 }
136
137 if(!q.exec("select * from MzCalibration;"))
138 {
139 qDebug();
140 throw PappsoException(
141 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
142 "command %2:\n%3\n%4\n%5")
143 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
144 .arg(q.lastQuery())
145 .arg(q.lastError().databaseText())
146 .arg(q.lastError().driverText())
147 .arg(q.lastError().nativeErrorCode()));
148 }
149
150 while(q.next())
151 {
152 QSqlRecord record = q.record();
154 std::pair<int, QSqlRecord>(record.value(0).toInt(), record));
155 }
156
157 // m_mapTimsCalibrationRecord
158
159 if(!q.exec("select * from TimsCalibration;"))
160 {
161 qDebug();
162 throw PappsoException(
163 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
164 "command %2:\n%3\n%4\n%5")
165 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
166 .arg(q.lastQuery())
167 .arg(q.lastError().databaseText())
168 .arg(q.lastError().driverText())
169 .arg(q.lastError().nativeErrorCode()));
170 }
171 while(q.next())
172 {
173 QSqlRecord record = q.record();
175 std::pair<int, QSqlRecord>(record.value(0).toInt(), record));
176 }
177
178
179 // store frames
180 if(!q.exec("select Frames.TimsId, Frames.AccumulationTime, " // 1
181 "Frames.MzCalibration, " // 2
182 "Frames.T1, Frames.T2, " // 4
183 "Frames.Time, Frames.MsMsType, Frames.TimsCalibration, " // 7
184 "Frames.Id " // 8
185 " FROM Frames;"))
186 {
187 qDebug();
188 throw PappsoException(
189 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
190 "command %2:\n%3\n%4\n%5")
191 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
192 .arg(q.lastQuery())
193 .arg(q.lastError().databaseText())
194 .arg(q.lastError().driverText())
195 .arg(q.lastError().nativeErrorCode()));
196 }
197
199 while(q.next())
200 {
201 QSqlRecord record = q.record();
202 TimsFrameRecord &frame_record =
203 m_mapFramesRecord[record.value(8).toULongLong()];
204
205 frame_record.frame_id = record.value(8).toULongLong();
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<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 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
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(
575 "ERROR MzCalibration database id %1 not found for frame_id=%2")
576 .arg(frame_record.mz_calibration_id)
577 .arg(timsId));
578 }
579
580 tims_frame.get()->setAccumulationTime(frame_record.accumulation_time);
581
582 tims_frame.get()->setTime(frame_record.frame_time);
583 tims_frame.get()->setMsMsType(frame_record.msms_type);
584
585 qDebug();
586 auto it_map_record_tims_calibration =
588 if(it_map_record_tims_calibration != m_mapTimsCalibrationRecord.end())
589 {
590
591 tims_frame.get()->setTimsCalibration(
592 it_map_record_tims_calibration->second.value(1).toInt(),
593 it_map_record_tims_calibration->second.value(2).toDouble(),
594 it_map_record_tims_calibration->second.value(3).toDouble(),
595 it_map_record_tims_calibration->second.value(4).toDouble(),
596 it_map_record_tims_calibration->second.value(5).toDouble(),
597 it_map_record_tims_calibration->second.value(6).toDouble(),
598 it_map_record_tims_calibration->second.value(7).toDouble(),
599 it_map_record_tims_calibration->second.value(8).toDouble(),
600 it_map_record_tims_calibration->second.value(9).toDouble(),
601 it_map_record_tims_calibration->second.value(10).toDouble(),
602 it_map_record_tims_calibration->second.value(11).toDouble());
603 }
604 else
605 {
606 throw ExceptionNotFound(
607 QObject::tr("ERROR TimsCalibration database id %1 not found")
608 .arg(frame_record.tims_calibration_id));
609 }
610 qDebug();
611 return tims_frame;
612}
613
614
616TimsData::getMassSpectrumCstSPtr(std::size_t timsId, std::size_t scanNum)
617{
618 qDebug() << " timsId=" << timsId << " scanNum=" << scanNum;
620
621 return frame->getMassSpectrumCstSPtr(scanNum);
622}
623
624
625std::size_t
630
631
632std::size_t
637
638
639std::size_t
644
645std::vector<std::size_t>
647 double mz_val,
648 double rt_sec,
649 double k0)
650{
651 std::vector<std::size_t> precursor_ids;
652 std::vector<std::vector<double>> ids;
653
654 QSqlDatabase qdb = openDatabaseConnection();
655 QSqlQuery q = qdb.exec(
656 QString(
657 "SELECT Frames.Time, Precursors.MonoisotopicMz, Precursors.Charge, "
658 "Precursors.Id, Frames.Id, PasefFrameMsMsInfo.ScanNumBegin, "
659 "PasefFrameMsMsInfo.scanNumEnd "
660 "FROM Frames "
661 "INNER JOIN PasefFrameMsMsInfo ON Frames.Id = PasefFrameMsMsInfo.Frame "
662 "INNER JOIN Precursors ON PasefFrameMsMsInfo.Precursor = Precursors.Id "
663 "WHERE Precursors.Charge == %1 "
664 "AND Precursors.MonoisotopicMz > %2 -0.01 "
665 "AND Precursors.MonoisotopicMz < %2 +0.01 "
666 "AND Frames.Time >= %3 -1 "
667 "AND Frames.Time < %3 +1; ")
668 .arg(charge)
669 .arg(mz_val)
670 .arg(rt_sec));
671 if(q.lastError().isValid())
672 {
673
674 throw PappsoException(
675 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
676 "executing SQL "
677 "command %3:\n%4\n%5\n%6")
678 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
679 .arg(qdb.databaseName())
680 .arg(q.lastQuery())
681 .arg(qdb.lastError().databaseText())
682 .arg(qdb.lastError().driverText())
683 .arg(qdb.lastError().nativeErrorCode()));
684 }
685 while(q.next())
686 {
687 // qInfo() << q.value(0).toDouble() << q.value(1).toDouble()
688 // << q.value(2).toDouble() << q.value(3).toDouble();
689
690 std::vector<double> sql_values;
691 sql_values.push_back(q.value(4).toDouble()); // frame id
692 sql_values.push_back(q.value(3).toDouble()); // precursor id
693 sql_values.push_back(q.value(5).toDouble()); // scan num begin
694 sql_values.push_back(q.value(6).toDouble()); // scan num end
695 sql_values.push_back(q.value(1).toDouble()); // mz_value
696
697 ids.push_back(sql_values);
698
699
700 if(std::find(precursor_ids.begin(),
701 precursor_ids.end(),
702 q.value(3).toDouble()) == precursor_ids.end())
703 {
704 precursor_ids.push_back(q.value(3).toDouble());
705 }
706 }
707
708 if(precursor_ids.size() > 1)
709 {
710 // std::vector<std::size_t> precursor_ids_ko =
711 // getMatchPrecursorIdByKo(ids, values[3]);
712 if(precursor_ids.size() > 1)
713 {
714 precursor_ids = getClosestPrecursorIdByMz(ids, k0);
715 }
716 return precursor_ids;
717 }
718 else
719 {
720 return precursor_ids;
721 }
722}
723
724std::vector<std::size_t>
725TimsData::getMatchPrecursorIdByKo(std::vector<std::vector<double>> ids,
726 double ko_value)
727{
728 std::vector<std::size_t> precursor_id;
729 for(std::vector<double> index : ids)
730 {
731 auto coordinate = getScanCoordinateFromRawIndex(index[0]);
732
733 TimsFrameBaseCstSPtr tims_frame;
734 tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
735
736 double bko = tims_frame.get()->getOneOverK0Transformation(index[2]);
737 double eko = tims_frame.get()->getOneOverK0Transformation(index[3]);
738
739 // qInfo() << "diff" << (bko + eko) / 2;
740 double mean_ko = (bko + eko) / 2;
741
742 if(mean_ko > ko_value - 0.1 && mean_ko < ko_value + 0.1)
743 {
744 precursor_id.push_back(index[1]);
745 }
746 }
747 return precursor_id;
748}
749
750std::vector<std::size_t>
751TimsData::getClosestPrecursorIdByMz(std::vector<std::vector<double>> ids,
752 double mz_value)
753{
754 std::vector<std::size_t> best_precursor;
755 double best_value = 1;
756 int count = 1;
757 int best_val_position = 0;
758
759 for(std::vector<double> values : ids)
760 {
761 double new_val = abs(mz_value - values[4]);
762 if(new_val < best_value)
763 {
764 best_value = new_val;
765 best_val_position = count;
766 }
767 count++;
768 }
769 best_precursor.push_back(ids[best_val_position][1]);
770 return best_precursor;
771}
772
773
774unsigned int
775TimsData::getMsLevelBySpectrumIndex(std::size_t spectrum_index)
776{
777 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
778 auto tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
779 return tims_frame.get()->getMsLevel();
780}
781
782
783void
785 const MsRunIdCstSPtr &msrun_id,
786 QualifiedMassSpectrum &mass_spectrum,
787 std::size_t spectrum_index,
788 bool want_binary_data)
789{
790 try
791 {
792 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
793 TimsFrameBaseCstSPtr tims_frame;
794 if(want_binary_data)
795 {
796 tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
797 }
798 else
799 {
800 tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
801 }
802 MassSpectrumId spectrum_id;
803
804 spectrum_id.setSpectrumIndex(spectrum_index);
805 spectrum_id.setMsRunId(msrun_id);
806 spectrum_id.setNativeId(QString("frame=%1 scan=%2 index=%3")
807 .arg(coordinate.first)
808 .arg(coordinate.second)
809 .arg(spectrum_index));
810
811 mass_spectrum.setMassSpectrumId(spectrum_id);
812
813 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
814 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
815
816 mass_spectrum.setDtInMilliSeconds(
817 tims_frame.get()->getDriftTime(coordinate.second));
818 // 1/K0
819 mass_spectrum.setParameterValue(
821 tims_frame.get()->getOneOverK0Transformation(coordinate.second));
822
823 mass_spectrum.setEmptyMassSpectrum(true);
824 if(want_binary_data)
825 {
826 mass_spectrum.setMassSpectrumSPtr(
827 tims_frame.get()->getMassSpectrumSPtr(coordinate.second));
828 if(mass_spectrum.size() > 0)
829 {
830 mass_spectrum.setEmptyMassSpectrum(false);
831 }
832 }
833 else
834 {
835 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
836 //{
837 mass_spectrum.setEmptyMassSpectrum(false);
838 // }
839 }
840 if(tims_frame.get()->getMsLevel() > 1)
841 {
842
843 auto spectrum_descr = getSpectrumDescrWithScanCoordinate(coordinate);
844 if(spectrum_descr.precursor_id > 0)
845 {
846
847 mass_spectrum.appendPrecursorIonData(
848 spectrum_descr.precursor_ion_data);
849
850
851 MassSpectrumId spectrum_id;
852 std::size_t prec_spectrum_index = getRawIndexFromCoordinate(
853 spectrum_descr.parent_frame, coordinate.second);
854
855 mass_spectrum.setPrecursorSpectrumIndex(prec_spectrum_index);
856 mass_spectrum.setPrecursorNativeId(
857 QString("frame=%1 scan=%2 index=%3")
858 .arg(spectrum_descr.parent_frame)
859 .arg(coordinate.second)
860 .arg(prec_spectrum_index));
861
862 mass_spectrum.setParameterValue(
864 spectrum_descr.isolationMz);
865 mass_spectrum.setParameterValue(
867 spectrum_descr.isolationWidth);
868
869 mass_spectrum.setParameterValue(
871 spectrum_descr.collisionEnergy);
872 mass_spectrum.setParameterValue(
874 (quint64)spectrum_descr.precursor_id);
875 }
876 }
877 }
878 catch(PappsoException &error)
879 {
880 throw PappsoException(
881 QObject::tr("Error TimsData::getQualifiedMassSpectrumByRawIndex "
882 "spectrum_index=%1 :\n%2")
883 .arg(spectrum_index)
884 .arg(error.qwhat()));
885 }
886}
887
888
889Trace
891{
892 // In the Frames table, each frame has a record describing the
893 // SummedIntensities for all the mobility spectra.
894
895
896 MapTrace rt_tic_map_trace;
897
898 using Pair = std::pair<double, double>;
899 using Map = std::map<double, double>;
900 using Iterator = Map::iterator;
901
902
903 QSqlDatabase qdb = openDatabaseConnection();
904 QSqlQuery q =
905 qdb.exec(QString("SELECT Time, SummedIntensities "
906 "FROM Frames WHERE MsMsType = 0 "
907 "ORDER BY Time;"));
908
909 if(q.lastError().isValid())
910 {
911
912 throw PappsoException(
913 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
914 "executing SQL "
915 "command %3:\n%4\n%5\n%6")
916 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
917 .arg(qdb.databaseName())
918 .arg(q.lastQuery())
919 .arg(qdb.lastError().databaseText())
920 .arg(qdb.lastError().driverText())
921 .arg(qdb.lastError().nativeErrorCode()));
922 }
923
924 while(q.next())
925 {
926
927 bool ok = false;
928
929 int cumulated_results = 2;
930
931 double rt = q.value(0).toDouble(&ok);
932 cumulated_results -= ok;
933
934 double sumY = q.value(1).toDouble(&ok);
935 cumulated_results -= ok;
936
937 if(cumulated_results)
938 {
939 throw PappsoException(
940 QObject::tr(
941 "ERROR in TIMS sqlite database file: could not read either the "
942 "retention time or the summed intensities (%1, database name "
943 "%2, "
944 "executing SQL "
945 "command %3:\n%4\n%5\n%6")
946 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
947 .arg(qdb.databaseName())
948 .arg(q.lastQuery())
949 .arg(qdb.lastError().databaseText())
950 .arg(qdb.lastError().driverText())
951 .arg(qdb.lastError().nativeErrorCode()));
952 }
953
954 // Try to insert value sumY at key rt.
955 std::pair<Iterator, bool> res = rt_tic_map_trace.insert(Pair(rt, sumY));
956
957 if(!res.second)
958 {
959 // One other same rt value was seen already (like in ion mobility
960 // mass spectrometry, for example). Only increment the y value.
961
962 res.first->second += sumY;
963 }
964 }
965
966 // qDebug().noquote() << "The TIC chromatogram:\n"
967 //<< rt_tic_map_trace.toTrace().toString();
968
969 return rt_tic_map_trace.toTrace();
970}
971
972
973void
975 const MsRunIdCstSPtr &msrun_id,
976 QualifiedMassSpectrum &mass_spectrum,
977 const SpectrumDescr &spectrum_descr,
978 bool want_binary_data)
979{
980
981 qDebug() << " ms2_index=" << spectrum_descr.ms2_index
982 << " precursor_index=" << spectrum_descr.precursor_id;
983
984 TracePlusCombiner combiner;
985 MapTrace combiner_result;
986
987 try
988 {
989 mass_spectrum.setMsLevel(1);
990 mass_spectrum.setPrecursorSpectrumIndex(0);
991 mass_spectrum.setEmptyMassSpectrum(true);
992
993 MassSpectrumId spectrum_id;
994 spectrum_id.setSpectrumIndex(spectrum_descr.ms1_index);
995 spectrum_id.setNativeId(
996 QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
997 .arg(spectrum_descr.parent_frame)
998 .arg(spectrum_descr.scan_mobility_start)
999 .arg(spectrum_descr.scan_mobility_end)
1000 .arg(spectrum_descr.precursor_id)
1001 .arg(spectrum_descr.ms1_index));
1002
1003 spectrum_id.setMsRunId(msrun_id);
1004
1005 mass_spectrum.setMassSpectrumId(spectrum_id);
1006
1007
1008 TimsFrameBaseCstSPtr tims_frame;
1009 if(want_binary_data)
1010 {
1011 qDebug() << "bindec";
1012 tims_frame = getTimsFrameCstSPtrCached(spectrum_descr.parent_frame);
1013 }
1014 else
1015 {
1016 tims_frame =
1018 }
1019 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1020
1021 mass_spectrum.setParameterValue(
1023 tims_frame.get()->getOneOverK0Transformation(
1024 spectrum_descr.scan_mobility_start));
1025
1026 mass_spectrum.setParameterValue(
1028 tims_frame.get()->getOneOverK0Transformation(
1029 spectrum_descr.scan_mobility_end));
1030
1031
1032 if(want_binary_data)
1033 {
1034 combiner.combine(combiner_result,
1035 tims_frame.get()->cumulateScanToTrace(
1036 spectrum_descr.scan_mobility_start,
1037 spectrum_descr.scan_mobility_end));
1038
1039 Trace trace(combiner_result);
1040 qDebug();
1041
1042 if(trace.size() > 0)
1043 {
1044 if(mcsp_ms1Filter != nullptr)
1045 {
1046 mcsp_ms1Filter->filter(trace);
1047 }
1048
1049 qDebug();
1050 mass_spectrum.setMassSpectrumSPtr(
1051 MassSpectrum(trace).makeMassSpectrumSPtr());
1052 mass_spectrum.setEmptyMassSpectrum(false);
1053 }
1054 else
1055 {
1056 mass_spectrum.setMassSpectrumSPtr(nullptr);
1057 mass_spectrum.setEmptyMassSpectrum(true);
1058 }
1059 }
1060 qDebug();
1061 }
1062
1063 catch(PappsoException &error)
1064 {
1065 throw error;
1066 }
1067 catch(std::exception &error)
1068 {
1069 qDebug() << QString("Failure %1 ").arg(error.what());
1070 }
1071}
1072
1073
1076{
1077 QMutexLocker locker(&m_mutex);
1078 for(auto &tims_frame : m_timsFrameBaseCache)
1079 {
1080 if(tims_frame.get()->getId() == timsId)
1081 {
1082 m_timsFrameBaseCache.push_back(tims_frame);
1084 m_timsFrameBaseCache.pop_front();
1085 return tims_frame;
1086 }
1087 }
1088
1091 m_timsFrameBaseCache.pop_front();
1092 return m_timsFrameBaseCache.back();
1093}
1094
1097{
1098 qDebug();
1099 QMutexLocker locker(&m_mutex);
1100 for(auto &tims_frame : m_timsFrameCache)
1101 {
1102 if(tims_frame.get()->getId() == timsId)
1103 {
1104 m_timsFrameCache.push_back(tims_frame);
1105 if(m_timsFrameCache.size() > m_cacheSize)
1106 m_timsFrameCache.pop_front();
1107 return tims_frame;
1108 }
1109 }
1110 TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1111
1112 // locker.relock();
1113 qDebug();
1114
1115 m_timsFrameCache.push_back(frame_sptr);
1116 if(m_timsFrameCache.size() > m_cacheSize)
1117 m_timsFrameCache.pop_front();
1118 qDebug();
1119 return m_timsFrameCache.back();
1120
1121
1122 /*
1123// the frame is not in the cache
1124if(std::find(m_someoneIsLoadingFrameId.begin(),
1125 m_someoneIsLoadingFrameId.end(),
1126 timsId) == m_someoneIsLoadingFrameId.end())
1127 {
1128 // not found, we are alone on this frame
1129 m_someoneIsLoadingFrameId.push_back(timsId);
1130 qDebug();
1131 //locker.unlock();
1132 TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1133
1134 // locker.relock();
1135 qDebug();
1136 m_someoneIsLoadingFrameId.erase(
1137 std::find(m_someoneIsLoadingFrameId.begin(),
1138 m_someoneIsLoadingFrameId.end(),
1139 timsId));
1140
1141 m_timsFrameCache.push_back(frame_sptr);
1142 if(m_timsFrameCache.size() > m_cacheSize)
1143 m_timsFrameCache.pop_front();
1144 qDebug();
1145 return m_timsFrameCache.back();
1146 }
1147else
1148 {
1149 // this frame is loading by someone else, we have to wait
1150 qDebug();
1151 // locker.unlock();
1152 // std::size_t another_frame_id = timsId;
1153 while(true)
1154 {
1155 QThread::usleep(1);
1156 // locker.relock();
1157
1158 for(auto &tims_frame : m_timsFrameCache)
1159 {
1160 if(tims_frame.get()->getId() == timsId)
1161 {
1162 m_timsFrameCache.push_back(tims_frame);
1163 return tims_frame;
1164 }
1165 }
1166 // locker.unlock();
1167}
1168} // namespace pappso
1169*/
1170}
1171
1172void
1177void
1182
1185 PrecisionPtr precision_ptr)
1186{
1187
1188 qDebug();
1189 XicCoordTims xic_coord_tims_struct;
1190
1191 try
1192 {
1193 if(m_mapXicCoordRecord.size() == 0)
1194 {
1195 QMutexLocker lock(&m_mutex);
1196 // Go get records!
1197
1198 // We proceed in this way:
1199
1200 // 1. For each Precursor reference to the Precursors table's ID
1201 // found in the PasefFrameMsMsInfo table, store the precursor ID for
1202 // step 2.
1203
1204 // 2. From the Precursors table's ID from step 1, get the
1205 // MonoisotopicMz.
1206
1207 // 3. From the PasefFrameMsMsInfo table, for the Precursors table's
1208 // ID reference, get a reference to the Frames table's ID. Thanks to
1209 // the Frames ID, look for the Time value (acquisition retention
1210 // time) for the MS/MS spectrum. The Time value in the Frames tables
1211 // always corresponds to a Frame of MsMsType 8 (that is, MS/MS),
1212 // which is expected since we are looking into MS/MS data.
1213
1214 // 4. From the PasefFrameMsMsInfo table, associate the values
1215 // ScanNumBegin and ScanNumEnd, the mobility bins in which the
1216 // precursor was found.
1217
1218
1219 QSqlDatabase qdb = openDatabaseConnection();
1220 QSqlQuery q = qdb.exec(
1221 QString("SELECT Precursors.id, "
1222 "min(Frames.Time), "
1223 "min(PasefFrameMsMsInfo.ScanNumBegin), "
1224 "max(PasefFrameMsMsInfo.ScanNumEnd), "
1225 "Precursors.MonoisotopicMz "
1226 "FROM "
1227 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1228 "PasefFrameMsMsInfo.Precursor=Precursors.Id INNER JOIN "
1229 "Frames ON PasefFrameMsMsInfo.Frame=Frames.Id "
1230 "GROUP BY Precursors.id;"));
1231 if(q.lastError().isValid())
1232 {
1233 qDebug();
1234 throw PappsoException(
1235 QObject::tr(
1236 "ERROR in TIMS sqlite database file %1, executing SQL "
1237 "command %2:\n%3\n%4\n%5")
1238 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1239 .arg(q.lastQuery())
1240 .arg(qdb.lastError().databaseText())
1241 .arg(qdb.lastError().driverText())
1242 .arg(qdb.lastError().nativeErrorCode()));
1243 }
1244
1245 q.last(); // strange bug : get the last sql record and get back,
1246 // otherwise it will not retrieve all records.
1247 q.first();
1248 // std::size_t i = 0;
1249 do
1250 {
1251 QSqlRecord record = q.record();
1252 m_mapXicCoordRecord.insert(std::pair<std::size_t, QSqlRecord>(
1253 (std::size_t)record.value(0).toULongLong(), record));
1254 }
1255 while(q.next());
1256 }
1257
1258
1259 auto it_map_xiccoord = m_mapXicCoordRecord.find(precursor_id);
1260 if(it_map_xiccoord == m_mapXicCoordRecord.end())
1261 {
1262
1263 throw ExceptionNotFound(
1264 QObject::tr("ERROR Precursors database id %1 not found")
1265 .arg(precursor_id));
1266 }
1267
1268 auto &q = it_map_xiccoord->second;
1269 xic_coord_tims_struct.mzRange =
1270 MzRange(q.value(4).toDouble(), precision_ptr);
1271 xic_coord_tims_struct.scanNumBegin = q.value(2).toUInt();
1272 xic_coord_tims_struct.scanNumEnd = q.value(3).toUInt();
1273 xic_coord_tims_struct.rtTarget = q.value(1).toDouble();
1274 // xic_structure.charge = q.value(5).toUInt();
1275 xic_coord_tims_struct.xicSptr = std::make_shared<Xic>();
1276 }
1277 catch(PappsoException &error)
1278 {
1279 throw error;
1280 }
1281 catch(std::exception &error)
1282 {
1283 qDebug() << QString("Failure %1 ").arg(error.what());
1284 }
1285 return xic_coord_tims_struct;
1286}
1287
1288
1289std::map<quint32, quint32>
1290TimsData::getRawMs2ByPrecursorId(std::size_t precursor_index)
1291{
1292 qDebug();
1293 std::map<quint32, quint32> raw_spectrum;
1294 try
1295 {
1296 QSqlDatabase qdb = openDatabaseConnection();
1297
1298 qdb = openDatabaseConnection();
1299 QSqlQuery q =
1300 qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
1301 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1302 "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
1303 "Precursors.Id=%1;")
1304 .arg(precursor_index));
1305 if(q.lastError().isValid())
1306 {
1307 qDebug();
1308 throw PappsoException(
1309 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1310 "command %2:\n%3\n%4\n%5")
1311 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1312 .arg(q.lastQuery())
1313 .arg(qdb.lastError().databaseText())
1314 .arg(qdb.lastError().driverText())
1315 .arg(qdb.lastError().nativeErrorCode()));
1316 }
1317 qDebug();
1318 // m_mutex.unlock();
1319 if(q.size() == 0)
1320 {
1321
1322 throw ExceptionNotFound(
1323 QObject::tr(
1324 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1325 "id=%1 not found")
1326 .arg(precursor_index));
1327 }
1328 else
1329 {
1330 // qDebug() << " q.size()="<< q.size();
1331 qDebug();
1332 bool first = true;
1333 std::size_t scan_mobility_start = 0;
1334 std::size_t scan_mobility_end = 0;
1335 std::vector<std::size_t> tims_frame_list;
1336
1337 while(q.next())
1338 {
1339 tims_frame_list.push_back(q.value(0).toLongLong());
1340 if(first)
1341 {
1342
1343 scan_mobility_start = q.value(1).toLongLong();
1344 scan_mobility_end = q.value(2).toLongLong();
1345
1346 first = false;
1347 }
1348 }
1349 // QMutexLocker locker(&m_mutex_spectrum);
1350 qDebug();
1351 TimsFrameCstSPtr tims_frame, previous_frame;
1352 // TracePlusCombiner combiner;
1353 // MapTrace combiner_result;
1354 for(std::size_t tims_id : tims_frame_list)
1355 {
1356 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1357 qDebug();
1358 /*combiner.combine(combiner_result,
1359 tims_frame.get()->cumulateScanToTrace(
1360 scan_mobility_start, scan_mobility_end));*/
1361 if(previous_frame.get() != nullptr)
1362 {
1363 if(previous_frame.get()->hasSameCalibrationData(
1364 *tims_frame.get()))
1365 {
1366 }
1367 else
1368 {
1369 throw ExceptionNotFound(
1370 QObject::tr(
1371 "ERROR in %1 %2, different calibration data "
1372 "between frame id %3 and frame id %4")
1373 .arg(__FILE__)
1374 .arg(__FUNCTION__)
1375 .arg(previous_frame.get()->getId())
1376 .arg(tims_frame.get()->getId()));
1377 }
1378 }
1379 tims_frame.get()->cumulateScansInRawMap(
1380 raw_spectrum, scan_mobility_start, scan_mobility_end);
1381 qDebug();
1382
1383 previous_frame = tims_frame;
1384 }
1385 qDebug() << " precursor_index=" << precursor_index
1386 << " num_rows=" << tims_frame_list.size()
1387 << " sql=" << q.lastQuery() << " "
1388 << (std::size_t)QThread::currentThreadId();
1389 if(first == true)
1390 {
1391 throw ExceptionNotFound(
1392 QObject::tr(
1393 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1394 "id=%1 not found")
1395 .arg(precursor_index));
1396 }
1397 qDebug();
1398 }
1399 }
1400
1401 catch(PappsoException &error)
1402 {
1403 throw PappsoException(QObject::tr("ERROR in %1 (precursor_index=%2):\n%3")
1404 .arg(__FUNCTION__)
1405 .arg(precursor_index)
1406 .arg(error.qwhat()));
1407 }
1408 catch(std::exception &error)
1409 {
1410 qDebug() << QString("Failure %1 ").arg(error.what());
1411 }
1412 return raw_spectrum;
1413 qDebug();
1414}
1415
1416
1417void
1419 const MsRunIdCstSPtr &msrun_id,
1420 QualifiedMassSpectrum &mass_spectrum,
1421 const SpectrumDescr &spectrum_descr,
1422 bool want_binary_data)
1423{
1424 try
1425 {
1426 qDebug();
1427 MassSpectrumId spectrum_id;
1428
1429 spectrum_id.setSpectrumIndex(spectrum_descr.ms2_index);
1430 spectrum_id.setNativeId(QString("precursor=%1 idxms2=%2")
1431 .arg(spectrum_descr.precursor_id)
1432 .arg(spectrum_descr.ms2_index));
1433 spectrum_id.setMsRunId(msrun_id);
1434
1435 mass_spectrum.setMassSpectrumId(spectrum_id);
1436
1437 mass_spectrum.setMsLevel(2);
1438 qDebug() << "spectrum_descr.precursor_id=" << spectrum_descr.precursor_id
1439 << " spectrum_descr.ms1_index=" << spectrum_descr.ms1_index
1440 << " spectrum_descr.ms2_index=" << spectrum_descr.ms2_index;
1441 mass_spectrum.setPrecursorSpectrumIndex(spectrum_descr.ms1_index);
1442
1443 mass_spectrum.setEmptyMassSpectrum(true);
1444
1445 qDebug();
1446
1447
1448 mass_spectrum.appendPrecursorIonData(spectrum_descr.precursor_ion_data);
1449
1450 mass_spectrum.setPrecursorNativeId(
1451 QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
1452 .arg(spectrum_descr.parent_frame)
1453 .arg(spectrum_descr.scan_mobility_start)
1454 .arg(spectrum_descr.scan_mobility_end)
1455 .arg(spectrum_descr.precursor_id)
1456 .arg(spectrum_descr.ms1_index));
1457
1458 mass_spectrum.setParameterValue(
1460 spectrum_descr.isolationMz);
1461 mass_spectrum.setParameterValue(
1463 spectrum_descr.isolationWidth);
1464
1465 mass_spectrum.setParameterValue(
1467 spectrum_descr.collisionEnergy);
1468 mass_spectrum.setParameterValue(
1470 (quint64)spectrum_descr.precursor_id);
1471
1472 // QMutexLocker locker(&m_mutex_spectrum);
1473 qDebug();
1474 TimsFrameBaseCstSPtr tims_frame, previous_frame;
1475 // TracePlusCombiner combiner;
1476 // MapTrace combiner_result;
1477 std::map<quint32, quint32> raw_spectrum;
1478 bool first = true;
1479 for(std::size_t tims_id : spectrum_descr.tims_frame_list)
1480 {
1481 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1482 << " tims_id=" << tims_id
1483 << (std::size_t)QThread::currentThreadId();
1484 ;
1485 if(want_binary_data)
1486 {
1487 qDebug() << "bindec";
1488 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1489 }
1490 else
1491 {
1492 tims_frame = getTimsFrameBaseCstSPtrCached(tims_id);
1493 }
1494 qDebug() << (std::size_t)QThread::currentThreadId();
1495 ;
1496 if(first)
1497 {
1498 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1499
1500 mass_spectrum.setParameterValue(
1502 tims_frame.get()->getOneOverK0Transformation(
1503 spectrum_descr.scan_mobility_start));
1504
1505 mass_spectrum.setParameterValue(
1507 tims_frame.get()->getOneOverK0Transformation(
1508 spectrum_descr.scan_mobility_end));
1509
1510 first = false;
1511 }
1512
1513
1514 if(want_binary_data)
1515 {
1516 qDebug();
1517 /*combiner.combine(combiner_result,
1518 tims_frame.get()->cumulateScanToTrace(
1519 scan_mobility_start, scan_mobility_end));*/
1520 if(previous_frame.get() != nullptr)
1521 {
1522 if(previous_frame.get()->hasSameCalibrationData(
1523 *tims_frame.get()))
1524 {
1525 }
1526 else
1527 {
1528 throw ExceptionNotFound(
1529 QObject::tr(
1530 "ERROR in %1 %2, different calibration data "
1531 "between frame id %3 and frame id %4")
1532 .arg(__FILE__)
1533 .arg(__FUNCTION__)
1534 .arg(previous_frame.get()->getId())
1535 .arg(tims_frame.get()->getId()));
1536 }
1537 }
1538 qDebug() << (std::size_t)QThread::currentThreadId();
1539 ;
1540 tims_frame.get()->cumulateScansInRawMap(
1541 raw_spectrum,
1542 spectrum_descr.scan_mobility_start,
1543 spectrum_descr.scan_mobility_end);
1544 qDebug() << (std::size_t)QThread::currentThreadId();
1545 ;
1546 }
1547 previous_frame = tims_frame;
1548 }
1549 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1550 << " num_rows=" << spectrum_descr.tims_frame_list.size()
1551 << (std::size_t)QThread::currentThreadId();
1552 if(first == true)
1553 {
1554 throw ExceptionNotFound(
1555 QObject::tr(
1556 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1557 "id=%1 not found")
1558 .arg(spectrum_descr.precursor_id));
1559 }
1560 if(want_binary_data)
1561 {
1562 qDebug() << " precursor_index=" << spectrum_descr.precursor_id;
1563 // peak_pick.filter(trace);
1564 Trace trace;
1566 {
1567 trace =
1568 tims_frame.get()->getTraceFromCumulatedScansBuiltinCentroid(
1569 raw_spectrum);
1570 }
1571 else
1572 {
1573 // no builtin centroid:
1574
1575 trace =
1576 tims_frame.get()->getTraceFromCumulatedScans(raw_spectrum);
1577 }
1578
1579 if(trace.size() > 0)
1580 {
1581 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1582 << " " << trace.size() << " "
1583 << (std::size_t)QThread::currentThreadId();
1584
1585 if(mcsp_ms2Filter != nullptr)
1586 {
1587 // FilterTriangle filter;
1588 // filter.setTriangleSlope(50, 0.02);
1589 // filter.filter(trace);
1590 // trace.filter(FilterHighPass(10));
1591 mcsp_ms2Filter->filter(trace);
1592 }
1593
1594 // FilterScaleFactorY filter_scale((double)1 /
1595 // (double)tims_frame_list.size());
1596 // filter_scale.filter(trace);
1597 qDebug() << " precursor_index=" << spectrum_descr.precursor_id;
1598 mass_spectrum.setMassSpectrumSPtr(
1599 MassSpectrum(trace).makeMassSpectrumSPtr());
1600 mass_spectrum.setEmptyMassSpectrum(false);
1601 }
1602 else
1603 {
1604 mass_spectrum.setMassSpectrumSPtr(nullptr);
1605 mass_spectrum.setEmptyMassSpectrum(true);
1606 }
1607
1608 qDebug();
1609 }
1610 qDebug();
1611 }
1612
1613 catch(PappsoException &error)
1614 {
1615 throw PappsoException(
1616 QObject::tr("ERROR in %1 (ms2_index=%2 precursor_index=%3):\n%4")
1617 .arg(__FUNCTION__)
1618 .arg(spectrum_descr.ms2_index)
1619 .arg(spectrum_descr.precursor_id)
1620 .arg(error.qwhat()));
1621 }
1622 catch(std::exception &error)
1623 {
1624 qDebug() << QString("Failure %1 ").arg(error.what());
1625 }
1626 qDebug();
1627}
1628
1629void
1631 const MsRunIdCstSPtr &msrun_id,
1633 unsigned int ms_level)
1634{
1635 qDebug() << " ms_level=" << ms_level;
1637 {
1638 throw PappsoException(
1639 QObject::tr("unable to read spectrum list : this data file does not "
1640 "contain MS2 data, no precursor found."));
1641 }
1642
1643 QSqlDatabase qdb = openDatabaseConnection();
1644 QSqlQuery qprecursor_list = qdb.exec(QString(
1645 "SELECT PasefFrameMsMsInfo.Frame, " // 0
1646 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
1647 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
1648 "PasefFrameMsMsInfo.IsolationMz, " // 3
1649 "PasefFrameMsMsInfo.IsolationWidth, " // 4
1650 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
1651 "PasefFrameMsMsInfo.Precursor, " // 6
1652 "Precursors.Id, " // 7
1653 "Precursors.LargestPeakMz, " // 8
1654 "Precursors.AverageMz, " // 9
1655 "Precursors.MonoisotopicMz, " // 10
1656 "Precursors.Charge, " // 11
1657 "Precursors.ScanNumber, " // 12
1658 "Precursors.Intensity, " // 13
1659 "Precursors.Parent " // 14
1660 "FROM PasefFrameMsMsInfo "
1661 "INNER JOIN Precursors ON "
1662 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
1663 "ORDER BY PasefFrameMsMsInfo.Precursor, PasefFrameMsMsInfo.Frame ;"));
1664 if(qprecursor_list.lastError().isValid())
1665 {
1666
1667 throw PappsoException(
1668 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1669 "command %2:\n%3\n%4\n%5")
1670 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1671 .arg(qprecursor_list.lastQuery())
1672 .arg(qdb.lastError().databaseText())
1673 .arg(qdb.lastError().driverText())
1674 .arg(qdb.lastError().nativeErrorCode()));
1675 }
1676
1677
1678 qDebug() << "qprecursor_list.size()=" << qprecursor_list.size();
1679 qDebug() << QObject::tr(
1680 "TIMS sqlite database file %1, executing SQL "
1681 "command %2:\n%3\n%4\n%5")
1682 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1683 .arg(qprecursor_list.lastQuery())
1684 .arg(qdb.lastError().databaseText())
1685 .arg(qdb.lastError().driverText())
1686 .arg(qdb.lastError().nativeErrorCode());
1687
1688 qDebug() << "qprecursor_list.isActive()=" << qprecursor_list.isActive();
1689 qDebug() << "qprecursor_list.isSelect()=" << qprecursor_list.isSelect();
1690 bool first = true;
1691 SpectrumDescr spectrum_descr;
1692
1693 /*
1694std::size_t i = 0;
1695while(qprecursor_list.next())
1696 {
1697 qDebug() << "i=" << i;
1698 i++;
1699 }*/
1700
1701 qprecursor_list.last(); // strange bug : get the last sql record and get
1702 // back, otherwise it will not retrieve all records.
1703
1704 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
1705 qprecursor_list.first();
1706 std::vector<TimsData::SpectrumDescr> spectrum_description_list;
1707 spectrum_descr.precursor_id = 0;
1708 // std::size_t i = 0;
1709
1710 do
1711 {
1712
1713 if(spectrum_descr.precursor_id !=
1714 (std::size_t)qprecursor_list.value(6).toLongLong())
1715 {
1716 // new precursor
1717 if(spectrum_descr.precursor_id > 0)
1718 {
1719 spectrum_description_list.push_back(spectrum_descr);
1720 }
1721
1722 spectrum_descr.tims_frame_list.clear();
1723 first = true;
1724 }
1725 qDebug() << " qprecursor_list.value(6).toLongLong() ="
1726 << qprecursor_list.value(6).toLongLong();
1727 spectrum_descr.precursor_id =
1728 (std::size_t)qprecursor_list.value(6).toLongLong();
1729 qDebug() << " spectrum_descr.precursor_id ="
1730 << spectrum_descr.precursor_id;
1731 qDebug() << " cumul tims frame:" << qprecursor_list.value(0).toLongLong();
1732 spectrum_descr.tims_frame_list.push_back(
1733 qprecursor_list.value(0).toLongLong());
1734 qDebug() << " first =" << first;
1735 if(first)
1736 {
1737 qDebug();
1738 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1739 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1740 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1741 spectrum_descr.precursor_ion_data =
1742 PrecursorIonData(qprecursor_list.value(10).toDouble(),
1743 qprecursor_list.value(11).toInt(),
1744 qprecursor_list.value(13).toDouble());
1745
1746 // spectrum_descr.precursor_id = q.value(6).toLongLong();
1747 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1748 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1749
1750 spectrum_descr.scan_mobility_start =
1751 qprecursor_list.value(1).toLongLong();
1752 spectrum_descr.scan_mobility_end =
1753 qprecursor_list.value(2).toLongLong();
1754
1755 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
1756 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
1757 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
1758 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
1759
1760
1761 first = false;
1762 }
1763 // qDebug() << "qprecursor_list.executedQuery()="
1764 // << qprecursor_list.executedQuery();
1765 // qDebug() << "qprecursor_list.last()=" << qprecursor_list.last();
1766 // i++;
1767 }
1768 while(qprecursor_list.next());
1769
1770 // last One
1771
1772 // new precursor
1773 if(spectrum_descr.precursor_id > 0)
1774 {
1775 spectrum_description_list.push_back(spectrum_descr);
1776 }
1777
1778
1779 QString local_filepath = m_timsDataDirectory.absoluteFilePath("analysis.tdf");
1780
1781 if(m_isMonoThread)
1782 {
1783 for(SpectrumDescr &spectrum_descr : spectrum_description_list)
1784 {
1785
1786 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1788 msrun_id, mass_spectrum_list, handler, spectrum_descr, ms_level);
1789
1790 for(auto &qualified_spectrum : mass_spectrum_list)
1791 {
1792 handler.setQualifiedMassSpectrum(qualified_spectrum);
1793 }
1794
1795 if(handler.shouldStop())
1796 {
1797 qDebug() << "The operation was cancelled. Breaking the loop.";
1799 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
1800 .arg(local_filepath));
1801 }
1802 }
1803 }
1804 else
1805 {
1806
1807
1808 TimsData *itself = this;
1809 SpectrumCollectionHandlerInterface *pointer_handler = &handler;
1810
1811
1812 std::function<std::vector<QualifiedMassSpectrum>(
1813 const TimsData::SpectrumDescr &)>
1814 map_function_generate_spectrum =
1815 [itself, msrun_id, pointer_handler, ms_level](
1816 const TimsData::SpectrumDescr &spectrum_descr)
1817 -> std::vector<QualifiedMassSpectrum> {
1818 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1819 itself->ms2ReaderGenerateMS1MS2Spectrum(msrun_id,
1820 mass_spectrum_list,
1821 *pointer_handler,
1822 spectrum_descr,
1823 ms_level);
1824
1825
1826 return mass_spectrum_list;
1827 };
1828
1829 std::function<void(
1830 std::size_t,
1831 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list)>
1832 reduce_function_spectrum_list =
1833 [pointer_handler, local_filepath](
1834 std::size_t res,
1835 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list) {
1836 for(auto &qualified_spectrum : qualified_spectrum_list)
1837 {
1838 pointer_handler->setQualifiedMassSpectrum(qualified_spectrum);
1839 }
1840
1841 if(pointer_handler->shouldStop())
1842 {
1843 qDebug() << "The operation was cancelled. Breaking the loop.";
1845 QObject::tr("reading TimsTOF job on %1 cancelled by the user")
1846 .arg(local_filepath));
1847 }
1848 res++;
1849 };
1850
1851
1852 QFuture<std::size_t> res;
1853 res = QtConcurrent::mappedReduced<std::size_t>(
1854 spectrum_description_list.begin(),
1855 spectrum_description_list.end(),
1856 map_function_generate_spectrum,
1857 reduce_function_spectrum_list,
1858 QtConcurrent::OrderedReduce);
1859 res.waitForFinished();
1860 }
1861 handler.loadingEnded();
1863}
1864
1865
1866void
1868 const MsRunIdCstSPtr &msrun_id,
1869 std::vector<QualifiedMassSpectrum> &qualified_mass_spectrum_list,
1871 const TimsData::SpectrumDescr &spectrum_descr,
1872 unsigned int ms_level)
1873{
1874
1875 qDebug() << " ms_level=" << ms_level;
1876 // The handler will receive the index of the mass spectrum in the
1877 // current run via the mass spectrum id member datum.
1878 if((ms_level == 0) || (ms_level == 1))
1879 {
1880 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1882 msrun_id,
1883 qualified_mass_spectrum_list.back(),
1884 spectrum_descr,
1885 handler.needMsLevelPeakList(1));
1886 }
1887 if((ms_level == 0) || (ms_level == 2))
1888 {
1889 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1891 msrun_id,
1892 qualified_mass_spectrum_list.back(),
1893 spectrum_descr,
1894 handler.needMsLevelPeakList(2));
1895 }
1896 qDebug();
1897}
1898
1899
1902{
1903
1904 SpectrumDescr spectrum_descr;
1905 QSqlDatabase qdb = openDatabaseConnection();
1906 QSqlQuery q = qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
1907 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
1908 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
1909 "PasefFrameMsMsInfo.IsolationMz, " // 3
1910 "PasefFrameMsMsInfo.IsolationWidth, " // 4
1911 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
1912 "PasefFrameMsMsInfo.Precursor, " // 6
1913 "Precursors.Id, " // 7
1914 "Precursors.LargestPeakMz, " // 8
1915 "Precursors.AverageMz, " // 9
1916 "Precursors.MonoisotopicMz, " // 10
1917 "Precursors.Charge, " // 11
1918 "Precursors.ScanNumber, " // 12
1919 "Precursors.Intensity, " // 13
1920 "Precursors.Parent " // 14
1921 "FROM PasefFrameMsMsInfo "
1922 "INNER JOIN Precursors ON "
1923 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
1924 "WHERE Precursors.Id=%1;")
1925 .arg(precursor_id));
1926 if(q.lastError().isValid())
1927 {
1928
1929 throw PappsoException(
1930 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1931 "command %2:\n%3\n%4\n%5")
1932 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1933 .arg(q.lastQuery())
1934 .arg(qdb.lastError().databaseText())
1935 .arg(qdb.lastError().driverText())
1936 .arg(qdb.lastError().nativeErrorCode()));
1937 }
1938
1939
1940 bool first = true;
1941 while(q.next())
1942 {
1943
1944 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
1945 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
1946 if(first)
1947 {
1948 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1949 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1950 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1951 spectrum_descr.precursor_ion_data =
1952 PrecursorIonData(q.value(10).toDouble(),
1953 q.value(11).toInt(),
1954 q.value(13).toDouble());
1955
1956 spectrum_descr.precursor_id = q.value(6).toLongLong();
1957 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1958 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1959
1960 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
1961 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
1962
1963 spectrum_descr.isolationMz = q.value(3).toDouble();
1964 spectrum_descr.isolationWidth = q.value(4).toDouble();
1965 spectrum_descr.collisionEnergy = q.value(5).toFloat();
1966 spectrum_descr.parent_frame = q.value(14).toLongLong();
1967
1968
1969 first = false;
1970 }
1971 }
1972 if(spectrum_descr.precursor_id == 0)
1973 {
1974 throw ExceptionNotFound(
1975 QObject::tr("ERROR in %1 %2 : precursor id (%3) NOT FOUND ")
1976 .arg(__FILE__)
1977 .arg(__FUNCTION__)
1978 .arg(precursor_id));
1979 }
1980 return spectrum_descr;
1981}
1982
1983std::vector<double>
1985{
1986 std::vector<double> timeline;
1987 timeline.reserve(m_mapFramesRecord.size());
1988 for(const TimsFrameRecord &frame_record : m_mapFramesRecord)
1989 {
1990 if(frame_record.mz_calibration_id != 0)
1991 {
1992 timeline.push_back(frame_record.frame_time);
1993 }
1994 }
1995 return timeline;
1996}
1997
2000 const std::pair<std::size_t, std::size_t> &scan_coordinate)
2001{
2002
2003 SpectrumDescr spectrum_descr;
2004 QSqlDatabase qdb = openDatabaseConnection();
2005 QSqlQuery q =
2006 qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
2007 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2008 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2009 "PasefFrameMsMsInfo.IsolationMz, " // 3
2010 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2011 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2012 "PasefFrameMsMsInfo.Precursor, " // 6
2013 "Precursors.Id, " // 7
2014 "Precursors.LargestPeakMz, " // 8
2015 "Precursors.AverageMz, " // 9
2016 "Precursors.MonoisotopicMz, " // 10
2017 "Precursors.Charge, " // 11
2018 "Precursors.ScanNumber, " // 12
2019 "Precursors.Intensity, " // 13
2020 "Precursors.Parent " // 14
2021 "FROM PasefFrameMsMsInfo "
2022 "INNER JOIN Precursors ON "
2023 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2024 "WHERE "
2025 "PasefFrameMsMsInfo.Frame=%1 and "
2026 "(PasefFrameMsMsInfo.ScanNumBegin "
2027 "<= %2 and PasefFrameMsMsInfo.ScanNumEnd >= %2);")
2028 .arg(scan_coordinate.first)
2029 .arg(scan_coordinate.second));
2030 if(q.lastError().isValid())
2031 {
2032
2033 throw PappsoException(
2034 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2035 "command %2:\n%3\n%4\n%5")
2036 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2037 .arg(q.lastQuery())
2038 .arg(qdb.lastError().databaseText())
2039 .arg(qdb.lastError().driverText())
2040 .arg(qdb.lastError().nativeErrorCode()));
2041 }
2042
2043 if(q.next())
2044 {
2045
2046 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
2047 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
2048 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2049 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2050 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2051 spectrum_descr.precursor_ion_data = PrecursorIonData(
2052 q.value(10).toDouble(), q.value(11).toInt(), q.value(13).toDouble());
2053
2054 spectrum_descr.precursor_id = q.value(6).toLongLong();
2055 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2056 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2057
2058 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
2059 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
2060
2061 spectrum_descr.isolationMz = q.value(3).toDouble();
2062 spectrum_descr.isolationWidth = q.value(4).toDouble();
2063 spectrum_descr.collisionEnergy = q.value(5).toFloat();
2064 spectrum_descr.parent_frame = q.value(14).toLongLong();
2065 }
2066 return spectrum_descr;
2067}
2068
2069
2070void
2072 TimsData::SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
2073{
2074
2075 spectrum_descr.tims_frame_list.clear();
2076 spectrum_descr.tims_frame_list.push_back(
2077 qprecursor_list.value(0).toLongLong());
2078 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2079 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2080 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2081 spectrum_descr.precursor_ion_data =
2082 PrecursorIonData(qprecursor_list.value(10).toDouble(),
2083 qprecursor_list.value(11).toInt(),
2084 qprecursor_list.value(13).toDouble());
2085
2086 spectrum_descr.precursor_id = qprecursor_list.value(6).toLongLong();
2087 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2088 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2089
2090 spectrum_descr.scan_mobility_start = qprecursor_list.value(1).toLongLong();
2091 spectrum_descr.scan_mobility_end = qprecursor_list.value(2).toLongLong();
2092
2093 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
2094 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
2095 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
2096 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
2097}
2098
2099
2100void
2102 const MsRunIdCstSPtr &msrun_id,
2104 unsigned int ms_level)
2105{
2106
2108 {
2109 throw PappsoException(
2110 QObject::tr("unable to read spectrum list : this data file does not "
2111 "contain MS2 data, no precursor found."));
2112 }
2113
2114 // We'll need it to perform the looping in the spectrum list.
2115 std::size_t spectrum_list_size = getTotalNumberOfScans();
2116
2117 // qDebug() << "The spectrum list has size:" << spectrum_list_size;
2118
2119 // Inform the handler of the spectrum list so that it can handle feedback to
2120 // the user.
2121 handler.spectrumListHasSize(spectrum_list_size);
2122
2123 QSqlDatabase qdb = openDatabaseConnection();
2124 QSqlQuery qprecursor_list = qdb.exec(QString(
2125 "SELECT DISTINCT "
2126 "PasefFrameMsMsInfo.Frame, " // 0
2127 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2128 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2129 "PasefFrameMsMsInfo.IsolationMz, " // 3
2130 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2131 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2132 "PasefFrameMsMsInfo.Precursor, " // 6
2133 "Precursors.Id, " // 7
2134 "Precursors.LargestPeakMz, " // 8
2135 "Precursors.AverageMz, " // 9
2136 "Precursors.MonoisotopicMz, " // 10
2137 "Precursors.Charge, " // 11
2138 "Precursors.ScanNumber, " // 12
2139 "Precursors.Intensity, " // 13
2140 "Precursors.Parent " // 14
2141 "FROM PasefFrameMsMsInfo "
2142 "INNER JOIN Precursors ON "
2143 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2144 "ORDER BY PasefFrameMsMsInfo.Frame, PasefFrameMsMsInfo.ScanNumBegin ;"));
2145 if(qprecursor_list.lastError().isValid())
2146 {
2147 throw PappsoException(
2148 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2149 "command %2:\n%3\n%4\n%5")
2150 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2151 .arg(qprecursor_list.lastQuery())
2152 .arg(qdb.lastError().databaseText())
2153 .arg(qdb.lastError().driverText())
2154 .arg(qdb.lastError().nativeErrorCode()));
2155 }
2156
2157
2158 std::size_t i = 0; // iterate on each Spectrum
2159
2160 qprecursor_list.last(); // strange bug : get the last sql record and get
2161 // back, unless it will not retrieve all records.
2162
2163 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
2164 qprecursor_list.first();
2165
2166 TimsFrameBaseCstSPtr tims_frame;
2167 SpectrumDescr spectrum_descr;
2168
2169 for(FrameIdDescr &current_frame : m_frameIdDescrList)
2170 {
2171
2172 // If the user of this reader instance wants to stop reading the
2173 // spectra, then break this loop.
2174 if(handler.shouldStop())
2175 {
2176 qDebug() << "The operation was cancelled. Breaking the loop.";
2178 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
2179 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf")));
2180 }
2181
2182 tims_frame = getTimsFrameBaseCstSPtrCached(current_frame.m_frameId);
2183 unsigned int tims_ms_level = tims_frame.get()->getMsLevel();
2184
2185 if((ms_level != 0) && (ms_level != tims_ms_level))
2186 { // bypass
2187 i += current_frame.m_size;
2188 }
2189 else
2190 {
2191 bool want_binary_data = handler.needMsLevelPeakList(tims_ms_level);
2192 qDebug() << "want_binary_data=" << want_binary_data;
2193 if(want_binary_data)
2194 {
2195 qDebug() << "bindec";
2196 tims_frame = getTimsFrameCstSPtrCached(current_frame.m_frameId);
2197 }
2198
2199 bool possible_precursor = false;
2200 if(tims_ms_level == 2)
2201 {
2202 // seek the precursor record:
2203 while(qprecursor_list.value(0).toULongLong() <
2204 current_frame.m_frameId)
2205 {
2206 qprecursor_list.next();
2207
2208 if(qprecursor_list.value(0).toULongLong() ==
2209 current_frame.m_frameId)
2210 {
2211 possible_precursor = true;
2212 }
2214 qprecursor_list);
2215 }
2216 }
2217
2218 for(std::size_t scan_num = 0; scan_num < current_frame.m_size;
2219 scan_num++)
2220 {
2221 bool has_a_precursor = false;
2222 if(possible_precursor)
2223 {
2224 if(spectrum_descr.scan_mobility_end < scan_num)
2225 {
2226 // seek the precursor record:
2227 while(qprecursor_list.value(0).toULongLong() <
2228 current_frame.m_frameId)
2229 {
2230 qprecursor_list.next();
2231
2232 if(qprecursor_list.value(0).toULongLong() !=
2233 current_frame.m_frameId)
2234 {
2235 possible_precursor = false;
2236 }
2238 qprecursor_list);
2239 }
2240 }
2241
2242 if(possible_precursor &&
2243 (spectrum_descr.scan_mobility_start < scan_num))
2244 {
2245 // we are in
2246 has_a_precursor = true;
2247 }
2248 } // end to determine if we are in a precursor for this
2249 // spectrum
2250
2251 QualifiedMassSpectrum mass_spectrum;
2252
2253
2254 MassSpectrumId spectrum_id;
2255
2256 spectrum_id.setSpectrumIndex(i);
2257 spectrum_id.setMsRunId(msrun_id);
2258 spectrum_id.setNativeId(QString("frame=%1 scan=%2 index=%3")
2259 .arg(current_frame.m_frameId)
2260 .arg(scan_num)
2261 .arg(i));
2262
2263 mass_spectrum.setMassSpectrumId(spectrum_id);
2264
2265 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
2266 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
2267
2268 mass_spectrum.setDtInMilliSeconds(
2269 tims_frame.get()->getDriftTime(scan_num));
2270 // 1/K0
2271 mass_spectrum.setParameterValue(
2273 tims_frame.get()->getOneOverK0Transformation(scan_num));
2274
2275 mass_spectrum.setEmptyMassSpectrum(true);
2276 if(want_binary_data)
2277 {
2278 try
2279 {
2280 mass_spectrum.setMassSpectrumSPtr(
2281 tims_frame.get()->getMassSpectrumSPtr(scan_num));
2282 }
2283 catch(PappsoException &error)
2284 {
2285 throw PappsoException(
2286 QObject::tr(
2287 "ERROR in %1 (scan_num=%2 spectrum_index=%3):\n%4")
2288 .arg(__FUNCTION__)
2289 .arg(scan_num)
2290 .arg(spectrum_id.getSpectrumIndex())
2291 .arg(error.qwhat()));
2292 }
2293 if(mass_spectrum.size() > 0)
2294 {
2295 mass_spectrum.setEmptyMassSpectrum(false);
2296 }
2297 }
2298 else
2299 {
2300 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
2301 //{
2302 mass_spectrum.setEmptyMassSpectrum(false);
2303 // }
2304 }
2305 if(has_a_precursor)
2306 {
2307 if(spectrum_descr.precursor_id > 0)
2308 {
2309
2310 mass_spectrum.appendPrecursorIonData(
2311 spectrum_descr.precursor_ion_data);
2312
2313 std::size_t prec_spectrum_index =
2315 scan_num);
2316
2317 mass_spectrum.setPrecursorSpectrumIndex(
2318 prec_spectrum_index);
2319 mass_spectrum.setPrecursorNativeId(
2320 QString("frame=%1 scan=%2 index=%3")
2321 .arg(spectrum_descr.parent_frame)
2322 .arg(scan_num)
2323 .arg(prec_spectrum_index));
2324
2325 mass_spectrum.setParameterValue(
2327 spectrum_descr.isolationMz);
2328 mass_spectrum.setParameterValue(
2330 spectrum_descr.isolationWidth);
2331
2332 mass_spectrum.setParameterValue(
2334 spectrum_descr.collisionEnergy);
2335 mass_spectrum.setParameterValue(
2337 (quint64)spectrum_descr.precursor_id);
2338 }
2339 }
2340
2341 handler.setQualifiedMassSpectrum(mass_spectrum);
2342 i++;
2343 }
2344 }
2345 }
2346}
2347
2348std::map<quint32, quint32>
2349TimsData::getRawMsBySpectrumIndex(std::size_t spectrum_index)
2350{
2351
2352 qDebug() << " spectrum_index=" << spectrum_index;
2353 auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
2354 TimsFrameBaseCstSPtr tims_frame;
2355 tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
2356
2357 std::map<quint32, quint32> raw_spectrum;
2358 tims_frame.get()->cumulateScansInRawMap(
2359 raw_spectrum, coordinate.second, coordinate.second);
2360 return raw_spectrum;
2361}
2362
2363
2364const std::vector<FrameIdDescr> &
2366{
2367 return m_frameIdDescrList;
2368}
2369
2370const std::vector<TimsFrameRecord> &
2375
2376
2377} // 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.
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
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
virtual void setQualifiedMassSpectrum(const QualifiedMassSpectrum &spectrum)=0
TimsFrameSPtr getTimsFrameSPtrByOffset(std::size_t frameId, const std::vector< pappso::TimsFrameRecord > &frame_record_list)
void closeLinearRead()
close file access and flush cache
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
const std::vector< TimsFrameRecord > & getTimsFrameRecordList() const
std::vector< FrameIdDescr > m_frameIdDescrList
store every frame id and corresponding sizes
Definition timsdata.h:334
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
TimsFrameCstSPtr getTimsFrameCstSPtrCached(std::size_t timsId)
get a Tims frame with his database ID but look in the cache first
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:974
virtual ~TimsData()
Definition timsdata.cpp:269
const std::vector< FrameIdDescr > & getFrameIdDescrList() const
std::map< std::size_t, QSqlRecord > m_mapXicCoordRecord
Definition timsdata.h:327
std::size_t getTotalNumberOfFrames() const
Get total number of frames.
Definition timsdata.cpp:626
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:616
void getQualifiedMs2MassSpectrumByPrecursorId(const MsRunIdCstSPtr &msrun_id, QualifiedMassSpectrum &mass_spectrum, const SpectrumDescr &spectrum_descr, bool want_binary_data)
SpectrumDescr getSpectrumDescrWithPrecursorId(std::size_t precursor_id)
get an intermediate structure describing a spectrum
TimsData(QDir timsDataDirectory)
build using the tims data directory
Definition timsdata.cpp:46
std::map< quint32, quint32 > getRawMs2ByPrecursorId(std::size_t precursor_index)
get cumulated raw signal for a given precursorCMakeLists.txt.userCMakeLists.txt.userCMakeLists....
std::size_t m_totalNumberOfFrames
Definition timsdata.h:311
Trace getTicChromatogram() const
Definition timsdata.cpp:890
TimsFrameBaseCstSPtr getTimsFrameBaseCstSPtrCached(std::size_t timsId)
std::size_t m_totalNumberOfScans
Definition timsdata.h:309
std::deque< TimsFrameCstSPtr > m_timsFrameCache
Definition timsdata.h:313
std::size_t m_cacheSize
Definition timsdata.h:312
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:326
std::map< int, QSqlRecord > m_mapMzCalibrationRecord
Definition timsdata.h:324
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:646
void fillSpectrumDescriptionWithSqlRecord(SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
std::map< int, QSqlRecord > m_mapTimsCalibrationRecord
Definition timsdata.h:325
bool m_builtinMs2Centroid
enable builtin centroid on raw tims integers by default
Definition timsdata.h:321
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:751
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:350
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...
QDir m_timsDataDirectory
Definition timsdata.h:306
SpectrumDescr getSpectrumDescrWithScanCoordinate(const std::pair< std::size_t, std::size_t > &scan_coordinate)
std::size_t getTotalNumberOfPrecursors() const
get the number of precursors analyzed by PASEF
Definition timsdata.cpp:640
MzCalibrationStore * mpa_mzCalibrationStore
Definition timsdata.h:329
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
unsigned int getMsLevelBySpectrumIndex(std::size_t spectrum_index)
Definition timsdata.cpp:775
bool getMs2BuiltinCentroid() const
tells if simple centroid filter on raw tims data for MS2 is enabled or not
Definition timsdata.cpp:289
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
std::deque< TimsFrameBaseCstSPtr > m_timsFrameBaseCache
Definition timsdata.h:314
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:341
void ms2ReaderGenerateMS1MS2Spectrum(const MsRunIdCstSPtr &msrun_id, std::vector< QualifiedMassSpectrum > &qualified_mass_spectrum_list, SpectrumCollectionHandlerInterface &handler, const SpectrumDescr &spectrum_descr, unsigned int ms_level)
TimsBinDec * mpa_timsBinDec
Definition timsdata.h:307
void getQualifiedMassSpectrumByRawIndex(const MsRunIdCstSPtr &msrun_id, QualifiedMassSpectrum &mass_spectrum, std::size_t spectrum_index, bool want_binary_data)
Definition timsdata.cpp:784
XicCoordTims getXicCoordTimsFromPrecursorId(std::size_t precursor_id, PrecisionPtr precision_ptr)
void setMs1FilterCstSPtr(pappso::FilterInterfaceCstSPtr &filter)
filter interface to apply just after raw MS1 specturm extraction the filter can be a list of filters ...
void setMs2FilterCstSPtr(pappso::FilterInterfaceCstSPtr &filter)
filter interface to apply just after raw MS2 specturm extraction the filter can be a list of filters ...
pappso::FilterInterfaceCstSPtr mcsp_ms1Filter
Definition timsdata.h:317
std::size_t getTotalNumberOfScans() const
get the total number of scans
Definition timsdata.cpp:633
std::vector< std::size_t > getMatchPrecursorIdByKo(std::vector< std::vector< double > > ids, double ko_value)
Definition timsdata.cpp:725
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:316
void setMonoThread(bool is_mono_thread)
set only one is_mono_thread to true
Definition timsdata.cpp:228
std::size_t m_totalNumberOfPrecursors
Definition timsdata.h:310
virtual MapTrace & combine(MapTrace &map_trace, const Trace &trace) const override
A simple container of DataPoint instances.
Definition trace.h:148
virtual Trace & filter(const FilterInterface &filter) final
apply a filter on this trace
Definition trace.cpp:1210
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
std::shared_ptr< TimsFrame > TimsFrameSPtr
Definition timsframe.h:41
std::shared_ptr< TimsFrameBase > TimsFrameBaseSPtr
std::shared_ptr< const MsRunId > MsRunIdCstSPtr
Definition msrunid.h:46
std::shared_ptr< const MassSpectrum > MassSpectrumCstSPtr
@ 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
coordinates of the XIC to extract and the resulting XIC after extraction
std::size_t scanNumEnd
mobility index end
std::size_t scanNumBegin
mobility index begin
XicSPtr xicSptr
extracted xic
Definition xiccoord.h:130
double rtTarget
the targeted retention time to extract around intended in seconds, and related to one msrun....
Definition xiccoord.h:126
MzRange mzRange
the mass to extract
Definition xiccoord.h:120
main Tims data handler