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