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_id=%1 scan_index=%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(
807 QString("frame_id=%1 scan_index=%2 global_scan_index=%3")
808 .arg(coordinate.first)
809 .arg(coordinate.second)
810 .arg(spectrum_index));
811
812 mass_spectrum.setMassSpectrumId(spectrum_id);
813
814 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
815 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
816
817 mass_spectrum.setDtInMilliSeconds(
818 tims_frame.get()->getDriftTime(coordinate.second));
819 // 1/K0
820 mass_spectrum.setParameterValue(
822 tims_frame.get()->getOneOverK0Transformation(coordinate.second));
823
824 mass_spectrum.setEmptyMassSpectrum(true);
825 if(want_binary_data)
826 {
827 mass_spectrum.setMassSpectrumSPtr(
828 tims_frame.get()->getMassSpectrumSPtr(coordinate.second));
829 if(mass_spectrum.size() > 0)
830 {
831 mass_spectrum.setEmptyMassSpectrum(false);
832 }
833 }
834 else
835 {
836 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
837 //{
838 mass_spectrum.setEmptyMassSpectrum(false);
839 // }
840 }
841 if(tims_frame.get()->getMsLevel() > 1)
842 {
843
844 auto spectrum_descr = getSpectrumDescrWithScanCoordinate(coordinate);
845 if(spectrum_descr.precursor_id > 0)
846 {
847
848 mass_spectrum.appendPrecursorIonData(
849 spectrum_descr.precursor_ion_data);
850
851
852 MassSpectrumId spectrum_id;
853 std::size_t prec_spectrum_index = getRawIndexFromCoordinate(
854 spectrum_descr.parent_frame, coordinate.second);
855
856 mass_spectrum.setPrecursorSpectrumIndex(prec_spectrum_index);
857 mass_spectrum.setPrecursorNativeId(
858 QString("frame_id=%1 scan_index=%2 global_scan_index=%3")
859 .arg(spectrum_descr.parent_frame)
860 .arg(coordinate.second)
861 .arg(prec_spectrum_index));
862
863 mass_spectrum.setParameterValue(
865 spectrum_descr.isolationMz);
866 mass_spectrum.setParameterValue(
868 spectrum_descr.isolationWidth);
869
870 mass_spectrum.setParameterValue(
872 spectrum_descr.collisionEnergy);
873 mass_spectrum.setParameterValue(
875 (quint64)spectrum_descr.precursor_id);
876 }
877 }
878 }
879 catch(PappsoException &error)
880 {
881 throw PappsoException(
882 QObject::tr("Error TimsData::getQualifiedMassSpectrumByRawIndex "
883 "spectrum_index=%1 :\n%2")
884 .arg(spectrum_index)
885 .arg(error.qwhat()));
886 }
887}
888
889
890Trace
892{
893 // In the Frames table, each frame has a record describing the
894 // SummedIntensities for all the mobility spectra.
895
896
897 MapTrace rt_tic_map_trace;
898
899 using Pair = std::pair<double, double>;
900 using Map = std::map<double, double>;
901 using Iterator = Map::iterator;
902
903
904 QSqlDatabase qdb = openDatabaseConnection();
905 QSqlQuery q =
906 qdb.exec(QString("SELECT Time, SummedIntensities "
907 "FROM Frames WHERE MsMsType = 0 "
908 "ORDER BY Time;"));
909
910 if(q.lastError().isValid())
911 {
912
913 throw PappsoException(
914 QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
915 "executing SQL "
916 "command %3:\n%4\n%5\n%6")
917 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
918 .arg(qdb.databaseName())
919 .arg(q.lastQuery())
920 .arg(qdb.lastError().databaseText())
921 .arg(qdb.lastError().driverText())
922 .arg(qdb.lastError().nativeErrorCode()));
923 }
924
925 while(q.next())
926 {
927
928 bool ok = false;
929
930 int cumulated_results = 2;
931
932 double rt = q.value(0).toDouble(&ok);
933 cumulated_results -= ok;
934
935 double sumY = q.value(1).toDouble(&ok);
936 cumulated_results -= ok;
937
938 if(cumulated_results)
939 {
940 throw PappsoException(
941 QObject::tr(
942 "ERROR in TIMS sqlite database file: could not read either the "
943 "retention time or the summed intensities (%1, database name "
944 "%2, "
945 "executing SQL "
946 "command %3:\n%4\n%5\n%6")
947 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
948 .arg(qdb.databaseName())
949 .arg(q.lastQuery())
950 .arg(qdb.lastError().databaseText())
951 .arg(qdb.lastError().driverText())
952 .arg(qdb.lastError().nativeErrorCode()));
953 }
954
955 // Try to insert value sumY at key rt.
956 std::pair<Iterator, bool> res = rt_tic_map_trace.insert(Pair(rt, sumY));
957
958 if(!res.second)
959 {
960 // One other same rt value was seen already (like in ion mobility
961 // mass spectrometry, for example). Only increment the y value.
962
963 res.first->second += sumY;
964 }
965 }
966
967 // qDebug().noquote() << "The TIC chromatogram:\n"
968 //<< rt_tic_map_trace.toTrace().toString();
969
970 return rt_tic_map_trace.toTrace();
971}
972
973
974void
976 const MsRunIdCstSPtr &msrun_id,
977 QualifiedMassSpectrum &mass_spectrum,
978 const SpectrumDescr &spectrum_descr,
979 bool want_binary_data)
980{
981
982 qDebug() << " ms2_index=" << spectrum_descr.ms2_index
983 << " precursor_index=" << spectrum_descr.precursor_id;
984
985 TracePlusCombiner combiner;
986 MapTrace combiner_result;
987
988 try
989 {
990 mass_spectrum.setMsLevel(1);
991 mass_spectrum.setPrecursorSpectrumIndex(0);
992 mass_spectrum.setEmptyMassSpectrum(true);
993
994 MassSpectrumId spectrum_id;
995 spectrum_id.setSpectrumIndex(spectrum_descr.ms1_index);
996 spectrum_id.setNativeId(
997 QString("frame_id=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
998 .arg(spectrum_descr.parent_frame)
999 .arg(spectrum_descr.scan_mobility_start)
1000 .arg(spectrum_descr.scan_mobility_end)
1001 .arg(spectrum_descr.precursor_id)
1002 .arg(spectrum_descr.ms1_index));
1003
1004 spectrum_id.setMsRunId(msrun_id);
1005
1006 mass_spectrum.setMassSpectrumId(spectrum_id);
1007
1008
1009 TimsFrameBaseCstSPtr tims_frame;
1010 if(want_binary_data)
1011 {
1012 qDebug() << "bindec";
1013 tims_frame = getTimsFrameCstSPtrCached(spectrum_descr.parent_frame);
1014 }
1015 else
1016 {
1017 tims_frame =
1019 }
1020 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1021
1022 mass_spectrum.setParameterValue(
1024 tims_frame.get()->getOneOverK0Transformation(
1025 spectrum_descr.scan_mobility_start));
1026
1027 mass_spectrum.setParameterValue(
1029 tims_frame.get()->getOneOverK0Transformation(
1030 spectrum_descr.scan_mobility_end));
1031
1032
1033 if(want_binary_data)
1034 {
1035 combiner.combine(combiner_result,
1036 tims_frame.get()->cumulateScansToTrace(
1037 spectrum_descr.scan_mobility_start,
1038 spectrum_descr.scan_mobility_end));
1039
1040 Trace trace(combiner_result);
1041 qDebug();
1042
1043 if(trace.size() > 0)
1044 {
1045 if(mcsp_ms1Filter != nullptr)
1046 {
1047 mcsp_ms1Filter->filter(trace);
1048 }
1049
1050 qDebug();
1051 mass_spectrum.setMassSpectrumSPtr(
1052 MassSpectrum(trace).makeMassSpectrumSPtr());
1053 mass_spectrum.setEmptyMassSpectrum(false);
1054 }
1055 else
1056 {
1057 mass_spectrum.setMassSpectrumSPtr(nullptr);
1058 mass_spectrum.setEmptyMassSpectrum(true);
1059 }
1060 }
1061 qDebug();
1062 }
1063
1064 catch(PappsoException &error)
1065 {
1066 throw error;
1067 }
1068 catch(std::exception &error)
1069 {
1070 qDebug() << QString("Failure %1 ").arg(error.what());
1071 }
1072}
1073
1074
1077{
1078 QMutexLocker locker(&m_mutex);
1079 for(auto &tims_frame : m_timsFrameBaseCache)
1080 {
1081 if(tims_frame.get()->getId() == timsId)
1082 {
1083 m_timsFrameBaseCache.push_back(tims_frame);
1085 m_timsFrameBaseCache.pop_front();
1086 return tims_frame;
1087 }
1088 }
1089
1092 m_timsFrameBaseCache.pop_front();
1093 return m_timsFrameBaseCache.back();
1094}
1095
1098{
1099 qDebug();
1100 QMutexLocker locker(&m_mutex);
1101 for(auto &tims_frame : m_timsFrameCache)
1102 {
1103 if(tims_frame.get()->getId() == timsId)
1104 {
1105 m_timsFrameCache.push_back(tims_frame);
1106 if(m_timsFrameCache.size() > m_cacheSize)
1107 m_timsFrameCache.pop_front();
1108 return tims_frame;
1109 }
1110 }
1111 TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1112
1113 // locker.relock();
1114 qDebug();
1115
1116 m_timsFrameCache.push_back(frame_sptr);
1117 if(m_timsFrameCache.size() > m_cacheSize)
1118 m_timsFrameCache.pop_front();
1119 qDebug();
1120 return m_timsFrameCache.back();
1121
1122
1123 /*
1124// the frame is not in the cache
1125if(std::find(m_someoneIsLoadingFrameId.begin(),
1126 m_someoneIsLoadingFrameId.end(),
1127 timsId) == m_someoneIsLoadingFrameId.end())
1128 {
1129 // not found, we are alone on this frame
1130 m_someoneIsLoadingFrameId.push_back(timsId);
1131 qDebug();
1132 //locker.unlock();
1133 TimsFrameCstSPtr frame_sptr = getTimsFrameCstSPtr(timsId);
1134
1135 // locker.relock();
1136 qDebug();
1137 m_someoneIsLoadingFrameId.erase(
1138 std::find(m_someoneIsLoadingFrameId.begin(),
1139 m_someoneIsLoadingFrameId.end(),
1140 timsId));
1141
1142 m_timsFrameCache.push_back(frame_sptr);
1143 if(m_timsFrameCache.size() > m_cacheSize)
1144 m_timsFrameCache.pop_front();
1145 qDebug();
1146 return m_timsFrameCache.back();
1147 }
1148else
1149 {
1150 // this frame is loading by someone else, we have to wait
1151 qDebug();
1152 // locker.unlock();
1153 // std::size_t another_frame_id = timsId;
1154 while(true)
1155 {
1156 QThread::usleep(1);
1157 // locker.relock();
1158
1159 for(auto &tims_frame : m_timsFrameCache)
1160 {
1161 if(tims_frame.get()->getId() == timsId)
1162 {
1163 m_timsFrameCache.push_back(tims_frame);
1164 return tims_frame;
1165 }
1166 }
1167 // locker.unlock();
1168}
1169} // namespace pappso
1170*/
1171}
1172
1173void
1178void
1183
1186 PrecisionPtr precision_ptr)
1187{
1188
1189 qDebug();
1190 XicCoordTims xic_coord_tims_struct;
1191
1192 try
1193 {
1194 if(m_mapXicCoordRecord.size() == 0)
1195 {
1196 QMutexLocker lock(&m_mutex);
1197 // Go get records!
1198
1199 // We proceed in this way:
1200
1201 // 1. For each Precursor reference to the Precursors table's ID
1202 // found in the PasefFrameMsMsInfo table, store the precursor ID for
1203 // step 2.
1204
1205 // 2. From the Precursors table's ID from step 1, get the
1206 // MonoisotopicMz.
1207
1208 // 3. From the PasefFrameMsMsInfo table, for the Precursors table's
1209 // ID reference, get a reference to the Frames table's ID. Thanks to
1210 // the Frames ID, look for the Time value (acquisition retention
1211 // time) for the MS/MS spectrum. The Time value in the Frames tables
1212 // always corresponds to a Frame of MsMsType 8 (that is, MS/MS),
1213 // which is expected since we are looking into MS/MS data.
1214
1215 // 4. From the PasefFrameMsMsInfo table, associate the values
1216 // ScanNumBegin and ScanNumEnd, the mobility bins in which the
1217 // precursor was found.
1218
1219
1220 QSqlDatabase qdb = openDatabaseConnection();
1221 QSqlQuery q = qdb.exec(
1222 QString("SELECT Precursors.id, "
1223 "min(Frames.Time), "
1224 "min(PasefFrameMsMsInfo.ScanNumBegin), "
1225 "max(PasefFrameMsMsInfo.ScanNumEnd), "
1226 "Precursors.MonoisotopicMz "
1227 "FROM "
1228 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1229 "PasefFrameMsMsInfo.Precursor=Precursors.Id INNER JOIN "
1230 "Frames ON PasefFrameMsMsInfo.Frame=Frames.Id "
1231 "GROUP BY Precursors.id;"));
1232 if(q.lastError().isValid())
1233 {
1234 qDebug();
1235 throw PappsoException(
1236 QObject::tr(
1237 "ERROR in TIMS sqlite database file %1, executing SQL "
1238 "command %2:\n%3\n%4\n%5")
1239 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1240 .arg(q.lastQuery())
1241 .arg(qdb.lastError().databaseText())
1242 .arg(qdb.lastError().driverText())
1243 .arg(qdb.lastError().nativeErrorCode()));
1244 }
1245
1246 q.last(); // strange bug : get the last sql record and get back,
1247 // otherwise it will not retrieve all records.
1248 q.first();
1249 // std::size_t i = 0;
1250 do
1251 {
1252 QSqlRecord record = q.record();
1253 m_mapXicCoordRecord.insert(std::pair<std::size_t, QSqlRecord>(
1254 (std::size_t)record.value(0).toULongLong(), record));
1255 }
1256 while(q.next());
1257 }
1258
1259
1260 auto it_map_xiccoord = m_mapXicCoordRecord.find(precursor_id);
1261 if(it_map_xiccoord == m_mapXicCoordRecord.end())
1262 {
1263
1264 throw ExceptionNotFound(
1265 QObject::tr("ERROR Precursors database id %1 not found")
1266 .arg(precursor_id));
1267 }
1268
1269 auto &q = it_map_xiccoord->second;
1270 xic_coord_tims_struct.mzRange =
1271 MzRange(q.value(4).toDouble(), precision_ptr);
1272 xic_coord_tims_struct.scanNumBegin = q.value(2).toUInt();
1273 xic_coord_tims_struct.scanNumEnd = q.value(3).toUInt();
1274 xic_coord_tims_struct.rtTarget = q.value(1).toDouble();
1275 // xic_structure.charge = q.value(5).toUInt();
1276 xic_coord_tims_struct.xicSptr = std::make_shared<Xic>();
1277 }
1278 catch(PappsoException &error)
1279 {
1280 throw error;
1281 }
1282 catch(std::exception &error)
1283 {
1284 qDebug() << QString("Failure %1 ").arg(error.what());
1285 }
1286 return xic_coord_tims_struct;
1287}
1288
1289
1291TimsData::getRawMs2ByPrecursorId(std::size_t precursor_index)
1292{
1293 qDebug();
1295 raw_spectrum.tofIndexList.clear();
1296 try
1297 {
1298 QSqlDatabase qdb = openDatabaseConnection();
1299
1300 qdb = openDatabaseConnection();
1301 QSqlQuery q =
1302 qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
1303 "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1304 "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
1305 "Precursors.Id=%1;")
1306 .arg(precursor_index));
1307 if(q.lastError().isValid())
1308 {
1309 qDebug();
1310 throw PappsoException(
1311 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1312 "command %2:\n%3\n%4\n%5")
1313 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1314 .arg(q.lastQuery())
1315 .arg(qdb.lastError().databaseText())
1316 .arg(qdb.lastError().driverText())
1317 .arg(qdb.lastError().nativeErrorCode()));
1318 }
1319 qDebug();
1320 // m_mutex.unlock();
1321 if(q.size() == 0)
1322 {
1323
1324 throw ExceptionNotFound(
1325 QObject::tr(
1326 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1327 "id=%1 not found")
1328 .arg(precursor_index));
1329 }
1330 else
1331 {
1332 // qDebug() << " q.size()="<< q.size();
1333 qDebug();
1334 bool first = true;
1335 std::size_t scan_mobility_start = 0;
1336 std::size_t scan_mobility_end = 0;
1337 std::vector<std::size_t> tims_frame_list;
1338
1339 while(q.next())
1340 {
1341 tims_frame_list.push_back(q.value(0).toLongLong());
1342 if(first)
1343 {
1344
1345 scan_mobility_start = q.value(1).toLongLong();
1346 scan_mobility_end = q.value(2).toLongLong();
1347
1348 first = false;
1349 }
1350 }
1351 // QMutexLocker locker(&m_mutex_spectrum);
1352 qDebug();
1353 TimsFrameCstSPtr tims_frame, previous_frame;
1354 // TracePlusCombiner combiner;
1355 // MapTrace combiner_result;
1356 for(std::size_t tims_id : tims_frame_list)
1357 {
1358 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1359 qDebug();
1360 /*combiner.combine(combiner_result,
1361 tims_frame.get()->cumulateScanToTrace(
1362 scan_mobility_start, scan_mobility_end));*/
1363 if(previous_frame.get() != nullptr)
1364 {
1365 if(previous_frame.get()->hasSameCalibrationData(
1366 *tims_frame.get()))
1367 {
1368 }
1369 else
1370 {
1371 throw ExceptionNotFound(
1372 QObject::tr(
1373 "ERROR in %1 %2, different calibration data "
1374 "between frame id %3 and frame id %4")
1375 .arg(__FILE__)
1376 .arg(__FUNCTION__)
1377 .arg(previous_frame.get()->getId())
1378 .arg(tims_frame.get()->getId()));
1379 }
1380 }
1381 tims_frame.get()->cumulateScansInRawMap(
1382 raw_spectrum, scan_mobility_start, scan_mobility_end);
1383 qDebug();
1384
1385 previous_frame = tims_frame;
1386 }
1387 qDebug() << " precursor_index=" << precursor_index
1388 << " num_rows=" << tims_frame_list.size()
1389 << " sql=" << q.lastQuery() << " "
1390 << (std::size_t)QThread::currentThreadId();
1391 if(first == true)
1392 {
1393 throw ExceptionNotFound(
1394 QObject::tr(
1395 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1396 "id=%1 not found")
1397 .arg(precursor_index));
1398 }
1399 qDebug();
1400 }
1401 }
1402
1403 catch(PappsoException &error)
1404 {
1405 throw PappsoException(QObject::tr("ERROR in %1 (precursor_index=%2):\n%3")
1406 .arg(__FUNCTION__)
1407 .arg(precursor_index)
1408 .arg(error.qwhat()));
1409 }
1410 catch(std::exception &error)
1411 {
1412 qDebug() << QString("Failure %1 ").arg(error.what());
1413 }
1414 return raw_spectrum;
1415 qDebug();
1416}
1417
1418
1419void
1421 const MsRunIdCstSPtr &msrun_id,
1422 QualifiedMassSpectrum &mass_spectrum,
1423 const SpectrumDescr &spectrum_descr,
1424 bool want_binary_data)
1425{
1426 try
1427 {
1428 qDebug();
1429 MassSpectrumId spectrum_id;
1430
1431 spectrum_id.setSpectrumIndex(spectrum_descr.ms2_index);
1432 spectrum_id.setNativeId(QString("precursor=%1 idxms2=%2")
1433 .arg(spectrum_descr.precursor_id)
1434 .arg(spectrum_descr.ms2_index));
1435 spectrum_id.setMsRunId(msrun_id);
1436
1437 mass_spectrum.setMassSpectrumId(spectrum_id);
1438
1439 mass_spectrum.setMsLevel(2);
1440 qDebug() << "spectrum_descr.precursor_id=" << spectrum_descr.precursor_id
1441 << " spectrum_descr.ms1_index=" << spectrum_descr.ms1_index
1442 << " spectrum_descr.ms2_index=" << spectrum_descr.ms2_index;
1443 mass_spectrum.setPrecursorSpectrumIndex(spectrum_descr.ms1_index);
1444
1445 mass_spectrum.setEmptyMassSpectrum(true);
1446
1447 qDebug();
1448
1449
1450 mass_spectrum.appendPrecursorIonData(spectrum_descr.precursor_ion_data);
1451
1452 mass_spectrum.setPrecursorNativeId(
1453 QString("frame_id=%1 begin=%2 end=%3 precursor=%4 idxms1=%5")
1454 .arg(spectrum_descr.parent_frame)
1455 .arg(spectrum_descr.scan_mobility_start)
1456 .arg(spectrum_descr.scan_mobility_end)
1457 .arg(spectrum_descr.precursor_id)
1458 .arg(spectrum_descr.ms1_index));
1459
1460 mass_spectrum.setParameterValue(
1462 spectrum_descr.isolationMz);
1463 mass_spectrum.setParameterValue(
1465 spectrum_descr.isolationWidth);
1466
1467 mass_spectrum.setParameterValue(
1469 spectrum_descr.collisionEnergy);
1470 mass_spectrum.setParameterValue(
1472 (quint64)spectrum_descr.precursor_id);
1473
1474 // QMutexLocker locker(&m_mutex_spectrum);
1475 qDebug();
1476 TimsFrameBaseCstSPtr tims_frame, previous_frame;
1477 // TracePlusCombiner combiner;
1478 // MapTrace combiner_result;
1479 TimsDataFastMap &raw_spectrum =
1481 raw_spectrum.tofIndexList.clear();
1482 bool first = true;
1483 for(std::size_t tims_id : spectrum_descr.tims_frame_list)
1484 {
1485 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1486 << " tims_id=" << tims_id
1487 << (std::size_t)QThread::currentThreadId();
1488 ;
1489 if(want_binary_data)
1490 {
1491 qDebug() << "bindec";
1492 tims_frame = getTimsFrameCstSPtrCached(tims_id);
1493 }
1494 else
1495 {
1496 tims_frame = getTimsFrameBaseCstSPtrCached(tims_id);
1497 }
1498 qDebug() << (std::size_t)QThread::currentThreadId();
1499 ;
1500 if(first)
1501 {
1502 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1503
1504 mass_spectrum.setParameterValue(
1506 tims_frame.get()->getOneOverK0Transformation(
1507 spectrum_descr.scan_mobility_start));
1508
1509 mass_spectrum.setParameterValue(
1511 tims_frame.get()->getOneOverK0Transformation(
1512 spectrum_descr.scan_mobility_end));
1513
1514 first = false;
1515 }
1516
1517
1518 if(want_binary_data)
1519 {
1520 qDebug();
1521 /*combiner.combine(combiner_result,
1522 tims_frame.get()->cumulateScanToTrace(
1523 scan_mobility_start, scan_mobility_end));*/
1524 if(previous_frame.get() != nullptr)
1525 {
1526 if(previous_frame.get()->hasSameCalibrationData(
1527 *tims_frame.get()))
1528 {
1529 }
1530 else
1531 {
1532 throw ExceptionNotFound(
1533 QObject::tr(
1534 "ERROR in %1 %2, different calibration data "
1535 "between frame id %3 and frame id %4")
1536 .arg(__FILE__)
1537 .arg(__FUNCTION__)
1538 .arg(previous_frame.get()->getId())
1539 .arg(tims_frame.get()->getId()));
1540 }
1541 }
1542 qDebug() << (std::size_t)QThread::currentThreadId();
1543 ;
1544 tims_frame.get()->cumulateScansInRawMap(
1545 raw_spectrum,
1546 spectrum_descr.scan_mobility_start,
1547 spectrum_descr.scan_mobility_end);
1548 qDebug() << (std::size_t)QThread::currentThreadId();
1549 ;
1550 }
1551 previous_frame = tims_frame;
1552 }
1553 qDebug() << " precursor_index=" << spectrum_descr.precursor_id
1554 << " num_rows=" << spectrum_descr.tims_frame_list.size()
1555 << (std::size_t)QThread::currentThreadId();
1556 if(first == true)
1557 {
1558 throw ExceptionNotFound(
1559 QObject::tr(
1560 "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1561 "id=%1 not found")
1562 .arg(spectrum_descr.precursor_id));
1563 }
1564 if(want_binary_data)
1565 {
1566 qDebug() << " precursor_index=" << spectrum_descr.precursor_id;
1567 // peak_pick.filter(trace);
1568 Trace trace;
1570 {
1571 //raw_spectrum.removeArtefactualSpike();
1572 raw_spectrum.builtInCentroid();
1573 }
1574
1575 trace = tims_frame.get()->getTraceFromCumulatedScans(raw_spectrum);
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(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;
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
1691 /*
1692std::size_t i = 0;
1693while(qprecursor_list.next())
1694 {
1695 qDebug() << "i=" << i;
1696 i++;
1697 }*/
1698
1699 qprecursor_list.last(); // strange bug : get the last sql record and get
1700 // back, otherwise it will not retrieve all records.
1701
1702 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
1703 qprecursor_list.first();
1704 std::vector<TimsData::SpectrumDescr> spectrum_description_list;
1705 spectrum_descr.precursor_id = 0;
1706 // std::size_t i = 0;
1707
1708 do
1709 {
1710
1711 if(spectrum_descr.precursor_id !=
1712 (std::size_t)qprecursor_list.value(6).toLongLong())
1713 {
1714 // new precursor
1715 if(spectrum_descr.precursor_id > 0)
1716 {
1717 spectrum_description_list.push_back(spectrum_descr);
1718 }
1719
1720 spectrum_descr.tims_frame_list.clear();
1721 first = true;
1722 }
1723 qDebug() << " qprecursor_list.value(6).toLongLong() ="
1724 << qprecursor_list.value(6).toLongLong();
1725 spectrum_descr.precursor_id =
1726 (std::size_t)qprecursor_list.value(6).toLongLong();
1727 qDebug() << " spectrum_descr.precursor_id ="
1728 << spectrum_descr.precursor_id;
1729 qDebug() << " cumul tims frame:" << qprecursor_list.value(0).toLongLong();
1730 spectrum_descr.tims_frame_list.push_back(
1731 qprecursor_list.value(0).toLongLong());
1732 qDebug() << " first =" << first;
1733 if(first)
1734 {
1735 qDebug();
1736 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1737 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1738 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1739 spectrum_descr.precursor_ion_data =
1740 PrecursorIonData(qprecursor_list.value(10).toDouble(),
1741 qprecursor_list.value(11).toInt(),
1742 qprecursor_list.value(13).toDouble());
1743
1744 // spectrum_descr.precursor_id = q.value(6).toLongLong();
1745 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1746 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1747
1748 spectrum_descr.scan_mobility_start =
1749 qprecursor_list.value(1).toLongLong();
1750 spectrum_descr.scan_mobility_end =
1751 qprecursor_list.value(2).toLongLong();
1752
1753 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
1754 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
1755 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
1756 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
1757
1758
1759 first = false;
1760 }
1761 // qDebug() << "qprecursor_list.executedQuery()="
1762 // << qprecursor_list.executedQuery();
1763 // qDebug() << "qprecursor_list.last()=" << qprecursor_list.last();
1764 // i++;
1765 }
1766 while(qprecursor_list.next());
1767
1768 // last One
1769
1770 // new precursor
1771 if(spectrum_descr.precursor_id > 0)
1772 {
1773 spectrum_description_list.push_back(spectrum_descr);
1774 }
1775
1776
1777 QString local_filepath = m_timsDataDirectory.absoluteFilePath("analysis.tdf");
1778
1779 if(m_isMonoThread)
1780 {
1781 for(SpectrumDescr &spectrum_descr : spectrum_description_list)
1782 {
1783
1784 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1786 msrun_id, mass_spectrum_list, handler, spectrum_descr, ms_level);
1787
1788 for(auto &qualified_spectrum : mass_spectrum_list)
1789 {
1790 handler.setQualifiedMassSpectrum(qualified_spectrum);
1791 }
1792
1793 if(handler.shouldStop())
1794 {
1795 qDebug() << "The operation was cancelled. Breaking the loop.";
1797 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
1798 .arg(local_filepath));
1799 }
1800 }
1801 }
1802 else
1803 {
1804
1805
1806 TimsData *itself = this;
1807 SpectrumCollectionHandlerInterface *pointer_handler = &handler;
1808
1809
1810 std::function<std::vector<QualifiedMassSpectrum>(
1811 const TimsData::SpectrumDescr &)>
1812 map_function_generate_spectrum =
1813 [itself, msrun_id, pointer_handler, ms_level](
1814 const TimsData::SpectrumDescr &spectrum_descr)
1815 -> std::vector<QualifiedMassSpectrum> {
1816 std::vector<QualifiedMassSpectrum> mass_spectrum_list;
1817 itself->ms2ReaderGenerateMS1MS2Spectrum(msrun_id,
1818 mass_spectrum_list,
1819 *pointer_handler,
1820 spectrum_descr,
1821 ms_level);
1822
1823
1824 return mass_spectrum_list;
1825 };
1826
1827 std::function<void(
1828 std::size_t,
1829 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list)>
1830 reduce_function_spectrum_list =
1831 [pointer_handler, local_filepath](
1832 std::size_t res,
1833 const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list) {
1834 for(auto &qualified_spectrum : qualified_spectrum_list)
1835 {
1836 pointer_handler->setQualifiedMassSpectrum(qualified_spectrum);
1837 }
1838
1839 if(pointer_handler->shouldStop())
1840 {
1841 qDebug() << "The operation was cancelled. Breaking the loop.";
1843 QObject::tr("reading TimsTOF job on %1 cancelled by the user")
1844 .arg(local_filepath));
1845 }
1846 res++;
1847 };
1848
1849
1850 QFuture<std::size_t> res;
1851 res = QtConcurrent::mappedReduced<std::size_t>(
1852 spectrum_description_list.begin(),
1853 spectrum_description_list.end(),
1854 map_function_generate_spectrum,
1855 reduce_function_spectrum_list,
1856 QtConcurrent::OrderedReduce);
1857 res.waitForFinished();
1858 }
1859 handler.loadingEnded();
1861}
1862
1863
1864void
1866 const MsRunIdCstSPtr &msrun_id,
1867 std::vector<QualifiedMassSpectrum> &qualified_mass_spectrum_list,
1869 const TimsData::SpectrumDescr &spectrum_descr,
1870 unsigned int ms_level)
1871{
1872
1873 qDebug() << " ms_level=" << ms_level;
1874 // The handler will receive the index of the mass spectrum in the
1875 // current run via the mass spectrum id member datum.
1876 if((ms_level == 0) || (ms_level == 1))
1877 {
1878 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1880 msrun_id,
1881 qualified_mass_spectrum_list.back(),
1882 spectrum_descr,
1883 handler.needMsLevelPeakList(1));
1884 }
1885 if((ms_level == 0) || (ms_level == 2))
1886 {
1887 qualified_mass_spectrum_list.push_back(QualifiedMassSpectrum());
1889 msrun_id,
1890 qualified_mass_spectrum_list.back(),
1891 spectrum_descr,
1892 handler.needMsLevelPeakList(2));
1893 }
1894 qDebug();
1895}
1896
1897
1900{
1901
1902 SpectrumDescr spectrum_descr;
1903 QSqlDatabase qdb = openDatabaseConnection();
1904 QSqlQuery q = qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
1905 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
1906 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
1907 "PasefFrameMsMsInfo.IsolationMz, " // 3
1908 "PasefFrameMsMsInfo.IsolationWidth, " // 4
1909 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
1910 "PasefFrameMsMsInfo.Precursor, " // 6
1911 "Precursors.Id, " // 7
1912 "Precursors.LargestPeakMz, " // 8
1913 "Precursors.AverageMz, " // 9
1914 "Precursors.MonoisotopicMz, " // 10
1915 "Precursors.Charge, " // 11
1916 "Precursors.ScanNumber, " // 12
1917 "Precursors.Intensity, " // 13
1918 "Precursors.Parent " // 14
1919 "FROM PasefFrameMsMsInfo "
1920 "INNER JOIN Precursors ON "
1921 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
1922 "WHERE Precursors.Id=%1;")
1923 .arg(precursor_id));
1924 if(q.lastError().isValid())
1925 {
1926
1927 throw PappsoException(
1928 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1929 "command %2:\n%3\n%4\n%5")
1930 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1931 .arg(q.lastQuery())
1932 .arg(qdb.lastError().databaseText())
1933 .arg(qdb.lastError().driverText())
1934 .arg(qdb.lastError().nativeErrorCode()));
1935 }
1936
1937
1938 bool first = true;
1939 while(q.next())
1940 {
1941
1942 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
1943 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
1944 if(first)
1945 {
1946 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1947 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1948 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1949 spectrum_descr.precursor_ion_data =
1950 PrecursorIonData(q.value(10).toDouble(),
1951 q.value(11).toInt(),
1952 q.value(13).toDouble());
1953
1954 spectrum_descr.precursor_id = q.value(6).toLongLong();
1955 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
1956 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
1957
1958 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
1959 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
1960
1961 spectrum_descr.isolationMz = q.value(3).toDouble();
1962 spectrum_descr.isolationWidth = q.value(4).toDouble();
1963 spectrum_descr.collisionEnergy = q.value(5).toFloat();
1964 spectrum_descr.parent_frame = q.value(14).toLongLong();
1965
1966
1967 first = false;
1968 }
1969 }
1970 if(spectrum_descr.precursor_id == 0)
1971 {
1972 throw ExceptionNotFound(
1973 QObject::tr("ERROR in %1 %2 : precursor id (%3) NOT FOUND ")
1974 .arg(__FILE__)
1975 .arg(__FUNCTION__)
1976 .arg(precursor_id));
1977 }
1978 return spectrum_descr;
1979}
1980
1981std::vector<double>
1983{
1984 std::vector<double> timeline;
1985 timeline.reserve(m_mapFramesRecord.size());
1986 for(const TimsFrameRecord &frame_record : m_mapFramesRecord)
1987 {
1988 if(frame_record.mz_calibration_id != 0)
1989 {
1990 timeline.push_back(frame_record.frame_time);
1991 }
1992 }
1993 return timeline;
1994}
1995
1998 const std::pair<std::size_t, std::size_t> &scan_coordinate)
1999{
2000
2001 SpectrumDescr spectrum_descr;
2002 QSqlDatabase qdb = openDatabaseConnection();
2003 QSqlQuery q =
2004 qdb.exec(QString("SELECT PasefFrameMsMsInfo.Frame, " // 0
2005 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2006 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2007 "PasefFrameMsMsInfo.IsolationMz, " // 3
2008 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2009 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2010 "PasefFrameMsMsInfo.Precursor, " // 6
2011 "Precursors.Id, " // 7
2012 "Precursors.LargestPeakMz, " // 8
2013 "Precursors.AverageMz, " // 9
2014 "Precursors.MonoisotopicMz, " // 10
2015 "Precursors.Charge, " // 11
2016 "Precursors.ScanNumber, " // 12
2017 "Precursors.Intensity, " // 13
2018 "Precursors.Parent " // 14
2019 "FROM PasefFrameMsMsInfo "
2020 "INNER JOIN Precursors ON "
2021 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2022 "WHERE "
2023 "PasefFrameMsMsInfo.Frame=%1 and "
2024 "(PasefFrameMsMsInfo.ScanNumBegin "
2025 "<= %2 and PasefFrameMsMsInfo.ScanNumEnd >= %2);")
2026 .arg(scan_coordinate.first)
2027 .arg(scan_coordinate.second));
2028 if(q.lastError().isValid())
2029 {
2030
2031 throw PappsoException(
2032 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2033 "command %2:\n%3\n%4\n%5")
2034 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2035 .arg(q.lastQuery())
2036 .arg(qdb.lastError().databaseText())
2037 .arg(qdb.lastError().driverText())
2038 .arg(qdb.lastError().nativeErrorCode()));
2039 }
2040
2041 if(q.next())
2042 {
2043
2044 qDebug() << " cumul tims frame:" << q.value(0).toLongLong();
2045 spectrum_descr.tims_frame_list.push_back(q.value(0).toLongLong());
2046 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2047 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2048 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2049 spectrum_descr.precursor_ion_data = PrecursorIonData(
2050 q.value(10).toDouble(), q.value(11).toInt(), q.value(13).toDouble());
2051
2052 spectrum_descr.precursor_id = q.value(6).toLongLong();
2053 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2054 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2055
2056 spectrum_descr.scan_mobility_start = q.value(1).toLongLong();
2057 spectrum_descr.scan_mobility_end = q.value(2).toLongLong();
2058
2059 spectrum_descr.isolationMz = q.value(3).toDouble();
2060 spectrum_descr.isolationWidth = q.value(4).toDouble();
2061 spectrum_descr.collisionEnergy = q.value(5).toFloat();
2062 spectrum_descr.parent_frame = q.value(14).toLongLong();
2063 }
2064 return spectrum_descr;
2065}
2066
2067
2068void
2070 TimsData::SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
2071{
2072
2073 spectrum_descr.tims_frame_list.clear();
2074 spectrum_descr.tims_frame_list.push_back(
2075 qprecursor_list.value(0).toLongLong());
2076 // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
2077 // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
2078 // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
2079 spectrum_descr.precursor_ion_data =
2080 PrecursorIonData(qprecursor_list.value(10).toDouble(),
2081 qprecursor_list.value(11).toInt(),
2082 qprecursor_list.value(13).toDouble());
2083
2084 spectrum_descr.precursor_id = qprecursor_list.value(6).toLongLong();
2085 spectrum_descr.ms2_index = (spectrum_descr.precursor_id * 2) - 1;
2086 spectrum_descr.ms1_index = (spectrum_descr.precursor_id * 2) - 2;
2087
2088 spectrum_descr.scan_mobility_start = qprecursor_list.value(1).toLongLong();
2089 spectrum_descr.scan_mobility_end = qprecursor_list.value(2).toLongLong();
2090
2091 spectrum_descr.isolationMz = qprecursor_list.value(3).toDouble();
2092 spectrum_descr.isolationWidth = qprecursor_list.value(4).toDouble();
2093 spectrum_descr.collisionEnergy = qprecursor_list.value(5).toFloat();
2094 spectrum_descr.parent_frame = qprecursor_list.value(14).toLongLong();
2095}
2096
2097
2098void
2100 const MsRunIdCstSPtr &msrun_id,
2102 unsigned int ms_level)
2103{
2104
2106 {
2107 throw PappsoException(
2108 QObject::tr("unable to read spectrum list : this data file does not "
2109 "contain MS2 data, no precursor found."));
2110 }
2111
2112 // We'll need it to perform the looping in the spectrum list.
2113 std::size_t spectrum_list_size = getTotalNumberOfScans();
2114
2115 // qDebug() << "The spectrum list has size:" << spectrum_list_size;
2116
2117 // Inform the handler of the spectrum list so that it can handle feedback to
2118 // the user.
2119 handler.spectrumListHasSize(spectrum_list_size);
2120
2121 QSqlDatabase qdb = openDatabaseConnection();
2122 QSqlQuery qprecursor_list = qdb.exec(QString(
2123 "SELECT DISTINCT "
2124 "PasefFrameMsMsInfo.Frame, " // 0
2125 "PasefFrameMsMsInfo.ScanNumBegin, " // 1
2126 "PasefFrameMsMsInfo.ScanNumEnd, " // 2
2127 "PasefFrameMsMsInfo.IsolationMz, " // 3
2128 "PasefFrameMsMsInfo.IsolationWidth, " // 4
2129 "PasefFrameMsMsInfo.CollisionEnergy, " // 5
2130 "PasefFrameMsMsInfo.Precursor, " // 6
2131 "Precursors.Id, " // 7
2132 "Precursors.LargestPeakMz, " // 8
2133 "Precursors.AverageMz, " // 9
2134 "Precursors.MonoisotopicMz, " // 10
2135 "Precursors.Charge, " // 11
2136 "Precursors.ScanNumber, " // 12
2137 "Precursors.Intensity, " // 13
2138 "Precursors.Parent " // 14
2139 "FROM PasefFrameMsMsInfo "
2140 "INNER JOIN Precursors ON "
2141 "PasefFrameMsMsInfo.Precursor=Precursors.Id "
2142 "ORDER BY PasefFrameMsMsInfo.Frame, PasefFrameMsMsInfo.ScanNumBegin ;"));
2143 if(qprecursor_list.lastError().isValid())
2144 {
2145 throw PappsoException(
2146 QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
2147 "command %2:\n%3\n%4\n%5")
2148 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
2149 .arg(qprecursor_list.lastQuery())
2150 .arg(qdb.lastError().databaseText())
2151 .arg(qdb.lastError().driverText())
2152 .arg(qdb.lastError().nativeErrorCode()));
2153 }
2154
2155
2156 std::size_t i = 0; // iterate on each Spectrum
2157
2158 qprecursor_list.last(); // strange bug : get the last sql record and get
2159 // back, unless it will not retrieve all records.
2160
2161 qDebug() << "qprecursor_list.at()=" << qprecursor_list.at();
2162 qprecursor_list.first();
2163
2164 TimsFrameBaseCstSPtr tims_frame;
2165 SpectrumDescr spectrum_descr;
2166
2167 for(FrameIdDescr &current_frame : m_frameIdDescrList)
2168 {
2169
2170 // If the user of this reader instance wants to stop reading the
2171 // spectra, then break this loop.
2172 if(handler.shouldStop())
2173 {
2174 qDebug() << "The operation was cancelled. Breaking the loop.";
2176 QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
2177 .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf")));
2178 }
2179
2180 tims_frame = getTimsFrameBaseCstSPtrCached(current_frame.m_frameId);
2181 unsigned int tims_ms_level = tims_frame.get()->getMsLevel();
2182
2183 if((ms_level != 0) && (ms_level != tims_ms_level))
2184 { // bypass
2185 i += current_frame.m_size;
2186 }
2187 else
2188 {
2189 bool want_binary_data = handler.needMsLevelPeakList(tims_ms_level);
2190 qDebug() << "want_binary_data=" << want_binary_data;
2191 if(want_binary_data)
2192 {
2193 qDebug() << "bindec";
2194 tims_frame = getTimsFrameCstSPtrCached(current_frame.m_frameId);
2195 }
2196
2197 bool possible_precursor = false;
2198 if(tims_ms_level == 2)
2199 {
2200 // seek the precursor record:
2201 while(qprecursor_list.value(0).toULongLong() <
2202 current_frame.m_frameId)
2203 {
2204 qprecursor_list.next();
2205
2206 if(qprecursor_list.value(0).toULongLong() ==
2207 current_frame.m_frameId)
2208 {
2209 possible_precursor = true;
2210 }
2212 qprecursor_list);
2213 }
2214 }
2215
2216 for(std::size_t scan_num = 0; scan_num < current_frame.m_size;
2217 scan_num++)
2218 {
2219 bool has_a_precursor = false;
2220 if(possible_precursor)
2221 {
2222 if(spectrum_descr.scan_mobility_end < scan_num)
2223 {
2224 // seek the precursor record:
2225 while(qprecursor_list.value(0).toULongLong() <
2226 current_frame.m_frameId)
2227 {
2228 qprecursor_list.next();
2229
2230 if(qprecursor_list.value(0).toULongLong() !=
2231 current_frame.m_frameId)
2232 {
2233 possible_precursor = false;
2234 }
2236 qprecursor_list);
2237 }
2238 }
2239
2240 if(possible_precursor &&
2241 (spectrum_descr.scan_mobility_start < scan_num))
2242 {
2243 // we are in
2244 has_a_precursor = true;
2245 }
2246 } // end to determine if we are in a precursor for this
2247 // spectrum
2248
2249 QualifiedMassSpectrum mass_spectrum;
2250
2251
2252 MassSpectrumId spectrum_id;
2253
2254 spectrum_id.setSpectrumIndex(i);
2255 spectrum_id.setMsRunId(msrun_id);
2256 spectrum_id.setNativeId(
2257 QString("frame_id=%1 scan_index=%2 global_scan_index=%3")
2258 .arg(current_frame.m_frameId)
2259 .arg(scan_num)
2260 .arg(i));
2261
2262 mass_spectrum.setMassSpectrumId(spectrum_id);
2263
2264 mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
2265 mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
2266
2267 mass_spectrum.setDtInMilliSeconds(
2268 tims_frame.get()->getDriftTime(scan_num));
2269 // 1/K0
2270 mass_spectrum.setParameterValue(
2272 tims_frame.get()->getOneOverK0Transformation(scan_num));
2273
2274 mass_spectrum.setEmptyMassSpectrum(true);
2275 if(want_binary_data)
2276 {
2277 try
2278 {
2279 mass_spectrum.setMassSpectrumSPtr(
2280 tims_frame.get()->getMassSpectrumSPtr(scan_num));
2281 }
2282 catch(PappsoException &error)
2283 {
2284 throw PappsoException(
2285 QObject::tr(
2286 "ERROR in %1 (scan_num=%2 spectrum_index=%3):\n%4")
2287 .arg(__FUNCTION__)
2288 .arg(scan_num)
2289 .arg(spectrum_id.getSpectrumIndex())
2290 .arg(error.qwhat()));
2291 }
2292 if(mass_spectrum.size() > 0)
2293 {
2294 mass_spectrum.setEmptyMassSpectrum(false);
2295 }
2296 }
2297 else
2298 {
2299 // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
2300 //{
2301 mass_spectrum.setEmptyMassSpectrum(false);
2302 // }
2303 }
2304 if(has_a_precursor)
2305 {
2306 if(spectrum_descr.precursor_id > 0)
2307 {
2308
2309 mass_spectrum.appendPrecursorIonData(
2310 spectrum_descr.precursor_ion_data);
2311
2312 std::size_t prec_spectrum_index =
2314 scan_num);
2315
2316 mass_spectrum.setPrecursorSpectrumIndex(
2317 prec_spectrum_index);
2318 mass_spectrum.setPrecursorNativeId(
2319 QString(
2320 "frame_id=%1 scan_index=%2 global_scan_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
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
2358 raw_spectrum.tofIndexList.clear();
2359 tims_frame.get()->cumulateScansInRawMap(
2360 raw_spectrum, coordinate.second, coordinate.second);
2361 return raw_spectrum;
2362}
2363
2364
2365const std::vector<FrameIdDescr> &
2367{
2368 return m_frameIdDescrList;
2369}
2370
2371const std::vector<TimsFrameRecord> &
2376
2377
2378} // 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: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
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:975
virtual ~TimsData()
Definition timsdata.cpp:269
const std::vector< FrameIdDescr > & getFrameIdDescrList() const
std::map< std::size_t, QSqlRecord > m_mapXicCoordRecord
Definition timsdata.h:325
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::size_t m_totalNumberOfFrames
Definition timsdata.h:309
Trace getTicChromatogram() const
Definition timsdata.cpp:891
TimsFrameBaseCstSPtr getTimsFrameBaseCstSPtrCached(std::size_t timsId)
std::size_t m_totalNumberOfScans
Definition timsdata.h:307
std::deque< TimsFrameCstSPtr > m_timsFrameCache
Definition timsdata.h:311
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:646
void fillSpectrumDescriptionWithSqlRecord(SpectrumDescr &spectrum_descr, QSqlQuery &qprecursor_list)
std::map< int, QSqlRecord > m_mapTimsCalibrationRecord
Definition timsdata.h:323
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: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: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...
TimsDataFastMap & getRawMs2ByPrecursorId(std::size_t precursor_index)
get cumulated raw signal for a given precursorCMakeLists.txt.userCMakeLists.txt.userCMakeLists....
QDir m_timsDataDirectory
Definition timsdata.h:304
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: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
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
TimsDataFastMap & 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: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)
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: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:315
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:314
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:308
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:42
std::shared_ptr< TimsFrameBase > TimsFrameBaseSPtr
std::shared_ptr< const MsRunId > MsRunIdCstSPtr
Definition msrunid.h:46
std::shared_ptr< const MassSpectrum > MassSpectrumCstSPtr
@ IsolationMzWidth
m/z isolation window width (left + right)
@ TimsIonMobScanOneOverK0
1/kO of a simple scan
@ CollisionEnergy
Bruker's timsTOF collision energy.
@ BrukerPrecursorIndex
Bruker's timsTOF precursor index.
@ rt
Retention time.
std::shared_ptr< const FilterInterface > FilterInterfaceCstSPtr
std::shared_ptr< const TimsFrame > TimsFrameCstSPtr
Definition timsframe.h:43
replacement for std::map
void builtInCentroid()
simple filter to agregate counts on neigbhor mobility slots (+1)
std::vector< quint32 > tofIndexList
static TimsDataFastMap & getTimsDataFastMapInstance()
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