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