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 "../../processing/combiners/tracepluscombiner.h"
31 #include "../../processing/filters/filtertriangle.h"
32 #include "../../processing/filters/filterpseudocentroid.h"
33 #include "../../processing/filters/filterpass.h"
35 #include <QDebug>
36 #include <solvers.h>
37 #include <QSqlError>
38 #include <QSqlQuery>
39 #include <QSqlRecord>
40 #include <QMutexLocker>
41 #include <QThread>
42 #include <set>
43 
44 using namespace pappso;
45 
46 TimsData::TimsData(QDir timsDataDirectory)
47  : m_timsDataDirectory(timsDataDirectory)
48 {
49 
50  qDebug();
52  if(!m_timsDataDirectory.exists())
53  {
54  throw PappsoException(
55  QObject::tr("ERROR TIMS data directory %1 not found")
56  .arg(m_timsDataDirectory.absolutePath()));
57  }
58 
59  if(!QFileInfo(m_timsDataDirectory.absoluteFilePath("analysis.tdf")).exists())
60  {
61 
62  throw PappsoException(
63  QObject::tr("ERROR TIMS data directory, %1 sqlite file not found")
64  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf")));
65  }
66 
67  // Open the database
68  QSqlDatabase qdb = openDatabaseConnection();
69 
70 
71  QSqlQuery q(qdb);
72  if(!q.exec("select Key, Value from GlobalMetadata where "
73  "Key='TimsCompressionType';"))
74  {
75 
76  qDebug();
77  throw PappsoException(
78  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
79  "command %2:\n%3\n%4\n%5")
80  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
81  .arg(q.lastQuery())
82  .arg(q.lastError().databaseText())
83  .arg(q.lastError().driverText())
84  .arg(q.lastError().nativeErrorCode()));
85  }
86 
87 
88  int compression_type = 0;
89  if(q.next())
90  {
91  compression_type = q.value(1).toInt();
92  }
93  qDebug() << " compression_type=" << compression_type;
95  QFileInfo(m_timsDataDirectory.absoluteFilePath("analysis.tdf_bin")),
96  compression_type);
97 
98 
99  // get number of precursors
100  if(!q.exec("SELECT COUNT( DISTINCT Id) FROM Precursors;"))
101  {
102  qDebug();
103  throw PappsoException(
104  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
105  "command %2:\n%3\n%4\n%5")
106  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
107  .arg(q.lastQuery())
108  .arg(qdb.lastError().databaseText())
109  .arg(qdb.lastError().driverText())
110  .arg(qdb.lastError().nativeErrorCode()));
111  }
112  if(q.next())
113  {
114  m_totalNumberOfPrecursors = q.value(0).toLongLong();
115  }
116 
117 
119 
120  // get number of scans
121  if(!q.exec("SELECT SUM(NumScans) FROM Frames"))
122  {
123  qDebug();
124  throw PappsoException(
125  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
126  "command %2:\n%3\n%4\n%5")
127  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
128  .arg(q.lastQuery())
129  .arg(qdb.lastError().databaseText())
130  .arg(qdb.lastError().driverText())
131  .arg(qdb.lastError().nativeErrorCode()));
132  }
133  if(q.next())
134  {
135  m_totalNumberOfScans = q.value(0).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  while(q.next())
199  {
200  QSqlRecord record = q.record();
201  m_mapFramesRecord.insert(
202  std::pair<std::size_t, QSqlRecord>(record.value(8).toUInt(), record));
203  }
204 
205 
206  std::shared_ptr<pappso::FilterPseudoCentroid> ms2filter =
207  std::make_shared<pappso::FilterPseudoCentroid>(35000, 5, 0.5, 0.1);
208  mcsp_ms2Filter = ms2filter;
209 
210 
211  std::shared_ptr<FilterTriangle> ms1filter =
212  std::make_shared<FilterTriangle>();
213  ms1filter.get()->setTriangleSlope(50, 0.01);
214  mcsp_ms1Filter = ms1filter;
215 }
216 
217 QSqlDatabase
219 {
220  QString database_connection_name = QString("%1_%2")
221  .arg(m_timsDataDirectory.absolutePath())
222  .arg((quintptr)QThread::currentThread());
223  // Open the database
224  QSqlDatabase qdb = QSqlDatabase::database(database_connection_name);
225  if(!qdb.isValid())
226  {
227  qDebug() << database_connection_name;
228  qdb = QSqlDatabase::addDatabase("QSQLITE", database_connection_name);
229  qdb.setDatabaseName(m_timsDataDirectory.absoluteFilePath("analysis.tdf"));
230  }
231 
232 
233  if(!qdb.open())
234  {
235  qDebug();
236  throw PappsoException(
237  QObject::tr("ERROR opening TIMS sqlite database file %1, database name "
238  "%2 :\n%3\n%4\n%5")
239  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
240  .arg(database_connection_name)
241  .arg(qdb.lastError().databaseText())
242  .arg(qdb.lastError().driverText())
243  .arg(qdb.lastError().nativeErrorCode()));
244  }
245  return qdb;
246 }
247 
248 TimsData::TimsData([[maybe_unused]] const pappso::TimsData &other)
249 {
250  qDebug();
251 }
252 
254 {
255  // m_qdb.close();
256  if(mpa_timsBinDec != nullptr)
257  {
258  delete mpa_timsBinDec;
259  }
260  if(mpa_mzCalibrationStore != nullptr)
261  {
262  delete mpa_mzCalibrationStore;
263  }
264 }
265 
266 void
268 {
269  m_builtinMs2Centroid = centroid;
270 }
271 
272 bool
274 {
275  return m_builtinMs2Centroid;
276 }
277 
278 void
280 {
281 
282  QSqlDatabase qdb = openDatabaseConnection();
283 
284  QSqlQuery q =
285  qdb.exec(QString("SELECT Id, NumScans FROM "
286  "Frames ORDER BY Id"));
287  if(q.lastError().isValid())
288  {
289 
290  throw PappsoException(
291  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
292  "command %2:\n%3\n%4\n%5")
293  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
294  .arg(q.lastQuery())
295  .arg(qdb.lastError().databaseText())
296  .arg(qdb.lastError().driverText())
297  .arg(qdb.lastError().nativeErrorCode()));
298  }
299  pappso::TimsFrameSPtr tims_frame;
300  bool index_found = false;
301  std::size_t timsId;
302  std::size_t numberScans;
303  std::size_t cumulScans = 0;
304  while(q.next() && (!index_found))
305  {
306  timsId = q.value(0).toUInt();
307  numberScans = q.value(1).toUInt();
308 
310  std::pair<std::size_t, std::size_t>((cumulScans % 1000),
311  m_frameIdDescrList.size()));
312 
313  m_frameIdDescrList.push_back({timsId, numberScans, cumulScans});
314  cumulScans += numberScans;
315  }
316 }
317 
318 std::pair<std::size_t, std::size_t>
319 TimsData::getScanCoordinateFromRawIndex(std::size_t raw_index) const
320 {
321 
322  std::size_t modulo = raw_index % 1000;
323  auto map_it = m_thousandIndexToFrameIdDescrListIndex.find(modulo);
324  if(map_it == m_thousandIndexToFrameIdDescrListIndex.end())
325  {
326  throw ExceptionNotFound(
327  QObject::tr("ERROR raw index %1 not found (modulo)").arg(raw_index));
328  }
329  std::size_t start_point_index = map_it->second;
330  while((start_point_index > 0) &&
331  (m_frameIdDescrList[start_point_index].m_cumulSize > raw_index))
332  {
333  start_point_index--;
334  }
335  for(std::size_t i = start_point_index; i < m_frameIdDescrList.size(); i++)
336  {
337 
338  if(raw_index <
339  (m_frameIdDescrList[i].m_cumulSize + m_frameIdDescrList[i].m_size))
340  {
341  return std::pair<std::size_t, std::size_t>(
342  m_frameIdDescrList[i].m_frameId,
343  raw_index - m_frameIdDescrList[i].m_cumulSize);
344  }
345  }
346 
347  throw ExceptionNotFound(
348  QObject::tr("ERROR raw index %1 not found").arg(raw_index));
349 }
350 
351 
352 std::size_t
354  std::size_t scan_num) const
355 {
356 
357  for(auto frameDescr : m_frameIdDescrList)
358  {
359  if(frameDescr.m_frameId == frame_id)
360  {
361  return frameDescr.m_cumulSize + scan_num;
362  }
363  }
364 
365  throw ExceptionNotFound(
366  QObject::tr("ERROR raw index with frame=%1 scan=%2 not found")
367  .arg(frame_id)
368  .arg(scan_num));
369 }
370 
371 /** @brief get a mass spectrum given its spectrum index
372  * @param raw_index a number begining at 0, corresponding to a Tims Scan in
373  * the order they lies in the binary data file
374  */
377 {
378 
379  auto coordinate = getScanCoordinateFromRawIndex(raw_index);
380  return getMassSpectrumCstSPtr(coordinate.first, coordinate.second);
381 }
382 
383 
385 TimsData::getTimsFrameBaseCstSPtr(std::size_t timsId) const
386 {
387 
388  qDebug() << " timsId=" << timsId;
389 
390  auto it_map_record_frames = m_mapFramesRecord.find(timsId);
391  if(it_map_record_frames == m_mapFramesRecord.end())
392  {
393  throw ExceptionNotFound(
394  QObject::tr("ERROR Frames database id %1 not found").arg(timsId));
395  }
396  pappso::TimsFrameBaseSPtr tims_frame;
397 
398 
399  tims_frame = std::make_shared<TimsFrameBase>(
400  TimsFrameBase(timsId, it_map_record_frames->second.value(0).toUInt()));
401 
402  auto it_map_record = m_mapMzCalibrationRecord.find(
403  it_map_record_frames->second.value(2).toInt());
404  if(it_map_record != m_mapMzCalibrationRecord.end())
405  {
406 
407  double T1_frame =
408  it_map_record_frames->second.value(3).toDouble(); // Frames.T1
409  double T2_frame =
410  it_map_record_frames->second.value(4).toDouble(); // Frames.T2
411 
412 
413  tims_frame.get()->setMzCalibrationInterfaceSPtr(
415  T1_frame, T2_frame, it_map_record->second));
416  }
417  else
418  {
419  throw ExceptionNotFound(
420  QObject::tr("ERROR MzCalibration database id %1 not found")
421  .arg(it_map_record_frames->second.value(2).toInt()));
422  }
423 
424  tims_frame.get()->setAccumulationTime(
425  it_map_record_frames->second.value(1).toDouble());
426 
427  tims_frame.get()->setTime(it_map_record_frames->second.value(5).toDouble());
428  tims_frame.get()->setMsMsType(it_map_record_frames->second.value(6).toUInt());
429 
430 
431  auto it_map_record_tims_calibration = m_mapTimsCalibrationRecord.find(
432  it_map_record_frames->second.value(7).toInt());
433  if(it_map_record_tims_calibration != m_mapTimsCalibrationRecord.end())
434  {
435 
436  tims_frame.get()->setTimsCalibration(
437  it_map_record_tims_calibration->second.value(1).toInt(),
438  it_map_record_tims_calibration->second.value(2).toDouble(),
439  it_map_record_tims_calibration->second.value(3).toDouble(),
440  it_map_record_tims_calibration->second.value(4).toDouble(),
441  it_map_record_tims_calibration->second.value(5).toDouble(),
442  it_map_record_tims_calibration->second.value(6).toDouble(),
443  it_map_record_tims_calibration->second.value(7).toDouble(),
444  it_map_record_tims_calibration->second.value(8).toDouble(),
445  it_map_record_tims_calibration->second.value(9).toDouble(),
446  it_map_record_tims_calibration->second.value(10).toDouble(),
447  it_map_record_tims_calibration->second.value(11).toDouble());
448  }
449  else
450  {
451  throw ExceptionNotFound(
452  QObject::tr("ERROR TimsCalibration database id %1 not found")
453  .arg(it_map_record_frames->second.value(7).toInt()));
454  }
455 
456  return tims_frame;
457 }
458 
459 std::vector<std::size_t>
460 TimsData::getTimsMS1FrameIdRange(double rt_begin, double rt_end) const
461 {
462 
463  qDebug() << " rt_begin=" << rt_begin << " rt_end=" << rt_end;
464  if(rt_begin < 0)
465  rt_begin = 0;
466  std::vector<std::size_t> tims_frameid_list;
467  QSqlDatabase qdb = openDatabaseConnection();
468  QSqlQuery q = qdb.exec(QString("SELECT Frames.Id FROM Frames WHERE "
469  "Frames.MsMsType=0 AND (Frames.Time>=%1) AND "
470  "(Frames.Time<=%2) ORDER BY Frames.Time;")
471  .arg(rt_begin)
472  .arg(rt_end));
473  if(q.lastError().isValid())
474  {
475 
476  throw PappsoException(
477  QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
478  "executing SQL "
479  "command %3:\n%4\n%5\n%6")
480  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
481  .arg(qdb.databaseName())
482  .arg(q.lastQuery())
483  .arg(qdb.lastError().databaseText())
484  .arg(qdb.lastError().driverText())
485  .arg(qdb.lastError().nativeErrorCode()));
486  }
487  while(q.next())
488  {
489 
490  tims_frameid_list.push_back(q.value(0).toUInt());
491  }
492  return tims_frameid_list;
493 }
494 
496 TimsData::getTimsFrameCstSPtr(std::size_t timsId) const
497 {
498 
499  qDebug() << " timsId=" << timsId
500  << " m_mapFramesRecord.size()=" << m_mapFramesRecord.size();
501  /*
502  for(auto pair_i : m_mapFramesRecord)
503  {
504 
505  qDebug() << " pair_i=" << pair_i.first;
506  }
507  */
508 
509  auto it_map_record_frames = m_mapFramesRecord.find(timsId);
510  if(it_map_record_frames == m_mapFramesRecord.end())
511  {
512 
513  throw ExceptionNotFound(
514  QObject::tr("ERROR Frames database id %1 not found").arg(timsId));
515  }
516 
517 
518  pappso::TimsFrameSPtr tims_frame;
519 
520 
522  timsId, it_map_record_frames->second.value(0).toUInt());
523 
524  qDebug();
525  auto it_map_record = m_mapMzCalibrationRecord.find(
526  it_map_record_frames->second.value(2).toInt());
527  if(it_map_record != m_mapMzCalibrationRecord.end())
528  {
529 
530  double T1_frame =
531  it_map_record_frames->second.value(3).toDouble(); // Frames.T1
532  double T2_frame =
533  it_map_record_frames->second.value(4).toDouble(); // Frames.T2
534 
535 
536  tims_frame.get()->setMzCalibrationInterfaceSPtr(
538  T1_frame, T2_frame, it_map_record->second));
539  }
540  else
541  {
542  throw ExceptionNotFound(
543  QObject::tr("ERROR MzCalibration database id %1 not found")
544  .arg(it_map_record_frames->second.value(2).toInt()));
545  }
546 
547  tims_frame.get()->setAccumulationTime(
548  it_map_record_frames->second.value(1).toDouble());
549 
550  tims_frame.get()->setTime(it_map_record_frames->second.value(5).toDouble());
551  tims_frame.get()->setMsMsType(it_map_record_frames->second.value(6).toUInt());
552 
553  qDebug();
554  auto it_map_record_tims_calibration = m_mapTimsCalibrationRecord.find(
555  it_map_record_frames->second.value(7).toInt());
556  if(it_map_record_tims_calibration != m_mapTimsCalibrationRecord.end())
557  {
558 
559  tims_frame.get()->setTimsCalibration(
560  it_map_record_tims_calibration->second.value(1).toInt(),
561  it_map_record_tims_calibration->second.value(2).toDouble(),
562  it_map_record_tims_calibration->second.value(3).toDouble(),
563  it_map_record_tims_calibration->second.value(4).toDouble(),
564  it_map_record_tims_calibration->second.value(5).toDouble(),
565  it_map_record_tims_calibration->second.value(6).toDouble(),
566  it_map_record_tims_calibration->second.value(7).toDouble(),
567  it_map_record_tims_calibration->second.value(8).toDouble(),
568  it_map_record_tims_calibration->second.value(9).toDouble(),
569  it_map_record_tims_calibration->second.value(10).toDouble(),
570  it_map_record_tims_calibration->second.value(11).toDouble());
571  }
572  else
573  {
574  throw ExceptionNotFound(
575  QObject::tr("ERROR TimsCalibration database id %1 not found")
576  .arg(it_map_record_frames->second.value(7).toInt()));
577  }
578  qDebug();
579  return tims_frame;
580 }
581 
582 
584 TimsData::getMassSpectrumCstSPtr(std::size_t timsId, std::size_t scanNum)
585 {
587 
588  return frame->getMassSpectrumCstSPtr(scanNum);
589 }
590 
591 std::size_t
593 {
594  return m_totalNumberOfScans;
595 }
596 
597 
598 std::size_t
600 {
602 }
603 
604 std::vector<std::size_t>
606  double mz_val,
607  double rt_sec,
608  double k0)
609 {
610  std::vector<std::size_t> precursor_ids;
611  std::vector<std::vector<double>> ids;
612 
613  QSqlDatabase qdb = openDatabaseConnection();
614  QSqlQuery q = qdb.exec(
615  QString(
616  "SELECT Frames.Time, Precursors.MonoisotopicMz, Precursors.Charge, "
617  "Precursors.Id, Frames.Id, PasefFrameMsMsInfo.ScanNumBegin, "
618  "PasefFrameMsMsInfo.scanNumEnd "
619  "FROM Frames "
620  "INNER JOIN PasefFrameMsMsInfo ON Frames.Id = PasefFrameMsMsInfo.Frame "
621  "INNER JOIN Precursors ON PasefFrameMsMsInfo.Precursor = Precursors.Id "
622  "WHERE Precursors.Charge == %1 "
623  "AND Precursors.MonoisotopicMz > %2 -0.01 "
624  "AND Precursors.MonoisotopicMz < %2 +0.01 "
625  "AND Frames.Time >= %3 -1 "
626  "AND Frames.Time < %3 +1; ")
627  .arg(charge)
628  .arg(mz_val)
629  .arg(rt_sec));
630  if(q.lastError().isValid())
631  {
632 
633  throw PappsoException(
634  QObject::tr("ERROR in TIMS sqlite database file %1, database name %2, "
635  "executing SQL "
636  "command %3:\n%4\n%5\n%6")
637  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
638  .arg(qdb.databaseName())
639  .arg(q.lastQuery())
640  .arg(qdb.lastError().databaseText())
641  .arg(qdb.lastError().driverText())
642  .arg(qdb.lastError().nativeErrorCode()));
643  }
644  while(q.next())
645  {
646  // qInfo() << q.value(0).toDouble() << q.value(1).toDouble()
647  // << q.value(2).toDouble() << q.value(3).toDouble();
648 
649  std::vector<double> sql_values;
650  sql_values.push_back(q.value(4).toDouble()); // frame id
651  sql_values.push_back(q.value(3).toDouble()); // precursor id
652  sql_values.push_back(q.value(5).toDouble()); // scan num begin
653  sql_values.push_back(q.value(6).toDouble()); // scan num end
654  sql_values.push_back(q.value(1).toDouble()); // mz_value
655 
656  ids.push_back(sql_values);
657 
658 
659  if(std::find(precursor_ids.begin(),
660  precursor_ids.end(),
661  q.value(3).toDouble()) == precursor_ids.end())
662  {
663  precursor_ids.push_back(q.value(3).toDouble());
664  }
665  }
666 
667  if(precursor_ids.size() > 1)
668  {
669  // std::vector<std::size_t> precursor_ids_ko =
670  // getMatchPrecursorIdByKo(ids, values[3]);
671  if(precursor_ids.size() > 1)
672  {
673  precursor_ids = getClosestPrecursorIdByMz(ids, k0);
674  }
675  return precursor_ids;
676  }
677  else
678  {
679  return precursor_ids;
680  }
681 }
682 
683 std::vector<std::size_t>
684 TimsData::getMatchPrecursorIdByKo(std::vector<std::vector<double>> ids,
685  double ko_value)
686 {
687  std::vector<std::size_t> precursor_id;
688  for(std::vector<double> index : ids)
689  {
690  auto coordinate = getScanCoordinateFromRawIndex(index[0]);
691 
692  TimsFrameBaseCstSPtr tims_frame;
693  tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
694 
695  double bko = tims_frame.get()->getOneOverK0Transformation(index[2]);
696  double eko = tims_frame.get()->getOneOverK0Transformation(index[3]);
697 
698  // qInfo() << "diff" << (bko + eko) / 2;
699  double mean_ko = (bko + eko) / 2;
700 
701  if(mean_ko > ko_value - 0.1 && mean_ko < ko_value + 0.1)
702  {
703  precursor_id.push_back(index[1]);
704  }
705  }
706  return precursor_id;
707 }
708 
709 std::vector<std::size_t>
710 TimsData::getClosestPrecursorIdByMz(std::vector<std::vector<double>> ids,
711  double mz_value)
712 {
713  std::vector<std::size_t> best_precursor;
714  double best_value = 1;
715  int count = 1;
716  int best_val_position = 0;
717 
718  for(std::vector<double> values : ids)
719  {
720  double new_val = abs(mz_value - values[4]);
721  if(new_val < best_value)
722  {
723  best_value = new_val;
724  best_val_position = count;
725  }
726  count++;
727  }
728  best_precursor.push_back(ids[best_val_position][1]);
729  return best_precursor;
730 }
731 
732 
733 unsigned int
734 TimsData::getMsLevelBySpectrumIndex(std::size_t spectrum_index)
735 {
736  auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
737  auto tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
738  return tims_frame.get()->getMsLevel();
739 }
740 
741 
744  bool want_binary_data)
745 {
746  auto coordinate = getScanCoordinateFromRawIndex(spectrum_index);
747  TimsFrameBaseCstSPtr tims_frame;
748  if(want_binary_data)
749  {
750  tims_frame = getTimsFrameCstSPtrCached(coordinate.first);
751  }
752  else
753  {
754  tims_frame = getTimsFrameBaseCstSPtrCached(coordinate.first);
755  }
756  QualifiedMassSpectrum mass_spectrum;
757  MassSpectrumId spectrum_id;
758 
759  spectrum_id.setSpectrumIndex(spectrum_index);
760  spectrum_id.setNativeId(QString("frame=%1 scan=%2 index=%3")
761  .arg(coordinate.first)
762  .arg(coordinate.second)
763  .arg(spectrum_index));
764 
765  mass_spectrum.setMassSpectrumId(spectrum_id);
766 
767  mass_spectrum.setMsLevel(tims_frame.get()->getMsLevel());
768  mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
769 
770  mass_spectrum.setDtInMilliSeconds(
771  tims_frame.get()->getDriftTime(coordinate.second));
772  // 1/K0
773  mass_spectrum.setParameterValue(
775  tims_frame.get()->getOneOverK0Transformation(coordinate.second));
776 
777  mass_spectrum.setEmptyMassSpectrum(true);
778  if(want_binary_data)
779  {
780  mass_spectrum.setMassSpectrumSPtr(
781  tims_frame.get()->getMassSpectrumSPtr(coordinate.second));
782  if(mass_spectrum.size() > 0)
783  {
784  mass_spectrum.setEmptyMassSpectrum(false);
785  }
786  }
787  else
788  {
789  // if(tims_frame.get()->getNbrPeaks(coordinate.second) > 0)
790  //{
791  mass_spectrum.setEmptyMassSpectrum(false);
792  // }
793  }
794  if(tims_frame.get()->getMsLevel() > 1)
795  {
796 
797  QSqlDatabase qdb = openDatabaseConnection();
798  QSqlQuery q = qdb.exec(
799  QString(
800  "SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
801  "PasefFrameMsMsInfo INNER JOIN Precursors ON "
802  "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
803  "PasefFrameMsMsInfo.Frame=%1 and (PasefFrameMsMsInfo.ScanNumBegin "
804  "<= %2 and PasefFrameMsMsInfo.ScanNumEnd >= %2);")
805  .arg(coordinate.first)
806  .arg(coordinate.second));
807  if(q.lastError().isValid())
808  {
809  throw PappsoException(
810  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
811  "command %2:\n%3\n%4\n%5")
812  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
813  .arg(q.lastQuery())
814  .arg(qdb.lastError().databaseText())
815  .arg(qdb.lastError().driverText())
816  .arg(qdb.lastError().nativeErrorCode()));
817  }
818  if(q.next())
819  {
820  // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
821  // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
822  // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
823  // mass_spectrum.setPrecursorSpectrumIndex();
824 
825  mass_spectrum.appendPrecursorIonData(
826  PrecursorIonData(q.value(10).toDouble(),
827  q.value(11).toInt(),
828  q.value(13).toDouble()));
829 
830 
831  MassSpectrumId spectrum_id;
832  std::size_t prec_spectrum_index = getRawIndexFromCoordinate(
833  q.value(14).toDouble(), coordinate.second);
834 
835  mass_spectrum.setPrecursorSpectrumIndex(prec_spectrum_index);
836  mass_spectrum.setPrecursorNativeId(
837  QString("frame=%1 scan=%2 index=%3")
838  .arg(q.value(14).toDouble())
839  .arg(coordinate.second)
840  .arg(prec_spectrum_index));
841 
842  mass_spectrum.setParameterValue(
843  QualifiedMassSpectrumParameter::IsolationMz, q.value(3).toDouble());
844  mass_spectrum.setParameterValue(
846  q.value(4).toDouble());
847 
848  mass_spectrum.setParameterValue(
850  q.value(5).toFloat());
851  mass_spectrum.setParameterValue(
853  q.value(6).toInt());
854  }
855  }
856 
857  return mass_spectrum;
858 }
859 
860 
863  std::size_t precursor_index,
864  bool want_binary_data)
865 {
866  QualifiedMassSpectrum mass_spectrum;
867 
868  try
869  {
870  QSqlDatabase qdb = openDatabaseConnection();
871  mass_spectrum.setMsLevel(1);
872  mass_spectrum.setPrecursorSpectrumIndex(0);
873  mass_spectrum.setEmptyMassSpectrum(true);
874  QSqlQuery q =
875  qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
876  "PasefFrameMsMsInfo INNER JOIN Precursors ON "
877  "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
878  "Precursors.Id=%1;")
879  .arg(precursor_index));
880  if(q.lastError().isValid())
881  {
882 
883  throw PappsoException(
884  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
885  "command %2:\n%3\n%4\n%5")
886  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
887  .arg(q.lastQuery())
888  .arg(qdb.lastError().databaseText())
889  .arg(qdb.lastError().driverText())
890  .arg(qdb.lastError().nativeErrorCode()));
891  }
892  if(q.size() == 0)
893  {
894 
895  throw ExceptionNotFound(
896  QObject::tr(
897  "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
898  "id=%1 not found")
899  .arg(precursor_index));
900  }
901  else
902  {
903  TracePlusCombiner combiner;
904  MapTrace combiner_result;
905 
906 
907  bool first = true;
908  std::size_t scan_mobility_start = 0;
909  std::size_t scan_mobility_end = 0;
910  std::set<std::size_t> tims_frame_list;
911  while(q.next())
912  {
913  // get MS1 frame
914  tims_frame_list.insert(q.value(14).toLongLong());
915  if(first)
916  {
917 
918 
919  MassSpectrumId spectrum_id;
920 
921  spectrum_id.setSpectrumIndex(precursor_index);
922  spectrum_id.setNativeId(
923  QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms2=%5")
924  .arg(q.value(0).toLongLong())
925  .arg(q.value(1).toLongLong())
926  .arg(q.value(2).toLongLong())
927  .arg(precursor_index)
928  .arg(ms2_index));
929 
930 
931  mass_spectrum.setMassSpectrumId(spectrum_id);
932 
933 
934  scan_mobility_start = q.value(1).toLongLong();
935  scan_mobility_end = q.value(2).toLongLong();
936 
937  first = false;
938  }
939  }
940 
941  first = true;
942  for(std::size_t tims_id : tims_frame_list)
943  {
944  TimsFrameBaseCstSPtr tims_frame =
945  getTimsFrameCstSPtrCached(tims_id);
946  if(first)
947  {
948  mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
949 
950  mass_spectrum.setParameterValue(
952  tims_frame.get()->getOneOverK0Transformation(
953  scan_mobility_start));
954 
955  mass_spectrum.setParameterValue(
957  tims_frame.get()->getOneOverK0Transformation(
958  scan_mobility_end));
959 
960  first = false;
961  }
962 
963 
964  if(want_binary_data)
965  {
966  combiner.combine(combiner_result,
967  tims_frame.get()->cumulateScanToTrace(
968  scan_mobility_start, scan_mobility_end));
969  }
970  else
971  {
972  break;
973  }
974  }
975 
976 
977  if(first == true)
978  {
979  throw ExceptionNotFound(
980  QObject::tr(
981  "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
982  "id=%1 not found")
983  .arg(precursor_index));
984  }
985 
986 
987  if(want_binary_data)
988  {
989 
990  pappso::Trace trace(combiner_result);
991  qDebug();
992 
993  if(trace.size() > 0)
994  {
995  if(mcsp_ms1Filter != nullptr)
996  {
997  mcsp_ms1Filter->filter(trace);
998  }
999 
1000  qDebug();
1001  mass_spectrum.setMassSpectrumSPtr(
1002  MassSpectrum(trace).makeMassSpectrumSPtr());
1003  mass_spectrum.setEmptyMassSpectrum(false);
1004  }
1005  else
1006  {
1007  mass_spectrum.setMassSpectrumSPtr(nullptr);
1008  mass_spectrum.setEmptyMassSpectrum(true);
1009  }
1010  }
1011  }
1012  }
1013 
1014  catch(PappsoException &error)
1015  {
1016  throw error;
1017  }
1018  catch(std::exception &error)
1019  {
1020  qDebug() << QString("Failure %1 ").arg(error.what());
1021  }
1022  return mass_spectrum;
1023 }
1024 
1025 
1026 void
1028  QualifiedMassSpectrum &mass_spectrum,
1029  std::size_t ms2_index,
1030  std::size_t precursor_index,
1031  bool want_binary_data)
1032 {
1033  qDebug();
1034  try
1035  {
1036  QSqlDatabase qdb = openDatabaseConnection();
1037  MassSpectrumId spectrum_id;
1038 
1039  spectrum_id.setSpectrumIndex(precursor_index);
1040  spectrum_id.setNativeId(
1041  QString("precursor=%1 idxms2=%2").arg(precursor_index).arg(ms2_index));
1042 
1043  mass_spectrum.setMassSpectrumId(spectrum_id);
1044 
1045  mass_spectrum.setMsLevel(2);
1046  mass_spectrum.setPrecursorSpectrumIndex(ms2_index - 1);
1047 
1048  mass_spectrum.setEmptyMassSpectrum(true);
1049 
1050  qdb = openDatabaseConnection();
1051  // m_mutex.lock();
1052  // if(m_query != nullptr)
1053  // {
1054  // *m_query =
1055  // qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.*
1056  // FROM "
1057  // "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1058  // "PasefFrameMsMsInfo.Precursor=Precursors.Id
1059  // where " "Precursors.Id=%1;")
1060  // .arg(precursor_index));
1061  // }
1062  QSqlQuery q =
1063  qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
1064  "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1065  "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
1066  "Precursors.Id=%1;")
1067  .arg(precursor_index));
1068  if(q.lastError().isValid())
1069  {
1070  qDebug();
1071  throw PappsoException(
1072  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1073  "command %2:\n%3\n%4\n%5")
1074  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1075  .arg(q.lastQuery())
1076  .arg(qdb.lastError().databaseText())
1077  .arg(qdb.lastError().driverText())
1078  .arg(qdb.lastError().nativeErrorCode()));
1079  }
1080  qDebug();
1081  // m_mutex.unlock();
1082  if(q.size() == 0)
1083  {
1084 
1085  throw ExceptionNotFound(
1086  QObject::tr(
1087  "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1088  "id=%1 not found")
1089  .arg(precursor_index));
1090  }
1091  else
1092  {
1093  // qDebug() << " q.size()="<< q.size();
1094  qDebug();
1095  bool first = true;
1096  std::size_t scan_mobility_start = 0;
1097  std::size_t scan_mobility_end = 0;
1098  std::vector<std::size_t> tims_frame_list;
1099 
1100  while(q.next())
1101  {
1102  tims_frame_list.push_back(q.value(0).toLongLong());
1103  if(first)
1104  {
1105  // mass_spectrum.setPrecursorCharge(q.value(11).toInt());
1106  // mass_spectrum.setPrecursorMz(q.value(10).toDouble());
1107  // mass_spectrum.setPrecursorIntensity(q.value(13).toDouble());
1108 
1109  mass_spectrum.appendPrecursorIonData(
1110  PrecursorIonData(q.value(10).toDouble(),
1111  q.value(11).toInt(),
1112  q.value(13).toDouble()));
1113 
1114  mass_spectrum.setPrecursorNativeId(
1115  QString("frame=%1 begin=%2 end=%3 precursor=%4 idxms2=%5")
1116  .arg(q.value(14).toLongLong())
1117  .arg(q.value(1).toLongLong())
1118  .arg(q.value(2).toLongLong())
1119  .arg(precursor_index)
1120  .arg(ms2_index - 1));
1121  // mass_spectrum.setPrecursorSpectrumIndex();
1122 
1123  scan_mobility_start = q.value(1).toLongLong();
1124  scan_mobility_end = q.value(2).toLongLong();
1125 
1126  mass_spectrum.setParameterValue(
1128  q.value(3).toDouble());
1129  mass_spectrum.setParameterValue(
1131  q.value(4).toDouble());
1132 
1133  mass_spectrum.setParameterValue(
1135  q.value(5).toFloat());
1136  mass_spectrum.setParameterValue(
1138  q.value(6).toInt());
1139 
1140  first = false;
1141  }
1142  }
1143  // QMutexLocker locker(&m_mutex_spectrum);
1144  qDebug();
1145  pappso::TimsFrameCstSPtr tims_frame, previous_frame;
1146  // TracePlusCombiner combiner;
1147  // MapTrace combiner_result;
1148  std::map<quint32, quint32> raw_spectrum;
1149  first = true;
1150  for(std::size_t tims_id : tims_frame_list)
1151  {
1152 
1153  tims_frame = getTimsFrameCstSPtrCached(tims_id);
1154  if(first)
1155  {
1156  mass_spectrum.setRtInSeconds(tims_frame.get()->getTime());
1157 
1158  mass_spectrum.setParameterValue(
1160  tims_frame.get()->getOneOverK0Transformation(
1161  scan_mobility_start));
1162 
1163  mass_spectrum.setParameterValue(
1165  tims_frame.get()->getOneOverK0Transformation(
1166  scan_mobility_end));
1167 
1168  first = false;
1169  }
1170 
1171 
1172  if(want_binary_data)
1173  {
1174  qDebug();
1175  /*combiner.combine(combiner_result,
1176  tims_frame.get()->cumulateScanToTrace(
1177  scan_mobility_start, scan_mobility_end));*/
1178  if(previous_frame.get() != nullptr)
1179  {
1180  if(previous_frame.get()->hasSameCalibrationData(
1181  *tims_frame.get()))
1182  {
1183  }
1184  else
1185  {
1186  throw ExceptionNotFound(
1187  QObject::tr(
1188  "ERROR in %1 %2, different calibration data "
1189  "between frame id %3 and frame id %4")
1190  .arg(__FILE__)
1191  .arg(__FUNCTION__)
1192  .arg(previous_frame.get()->getId())
1193  .arg(tims_frame.get()->getId()));
1194  }
1195  }
1196  tims_frame.get()->cumulateScansInRawMap(
1197  raw_spectrum, scan_mobility_start, scan_mobility_end);
1198  qDebug();
1199  }
1200  previous_frame = tims_frame;
1201  }
1202  qDebug() << " precursor_index=" << precursor_index
1203  << " num_rows=" << tims_frame_list.size()
1204  << " sql=" << q.lastQuery() << " "
1205  << (std::size_t)QThread::currentThreadId();
1206  if(first == true)
1207  {
1208  throw ExceptionNotFound(
1209  QObject::tr(
1210  "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1211  "id=%1 not found")
1212  .arg(precursor_index));
1213  }
1214  if(want_binary_data)
1215  {
1216  qDebug();
1217  // peak_pick.filter(trace);
1218  pappso::Trace trace;
1220  {
1221  trace =
1222  tims_frame.get()->getTraceFromCumulatedScansBuiltinCentroid(
1223  raw_spectrum);
1224  }
1225  else
1226  {
1227  // no builtin centroid:
1228 
1229  trace =
1230  tims_frame.get()->getTraceFromCumulatedScans(raw_spectrum);
1231  }
1232 
1233  if(trace.size() > 0)
1234  {
1235  qDebug() << trace.size() << " "
1236  << (std::size_t)QThread::currentThreadId();
1237 
1238  if(mcsp_ms2Filter != nullptr)
1239  {
1240  // FilterTriangle filter;
1241  // filter.setTriangleSlope(50, 0.02);
1242  // filter.filter(trace);
1243  // trace.filter(pappso::FilterHighPass(10));
1244  mcsp_ms2Filter->filter(trace);
1245  }
1246 
1247  // FilterScaleFactorY filter_scale((double)1 /
1248  // (double)tims_frame_list.size());
1249  // filter_scale.filter(trace);
1250  qDebug();
1251  mass_spectrum.setMassSpectrumSPtr(
1252  MassSpectrum(trace).makeMassSpectrumSPtr());
1253  mass_spectrum.setEmptyMassSpectrum(false);
1254  }
1255  else
1256  {
1257  mass_spectrum.setMassSpectrumSPtr(nullptr);
1258  mass_spectrum.setEmptyMassSpectrum(true);
1259  }
1260 
1261  qDebug();
1262  }
1263  qDebug();
1264  }
1265  }
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  qDebug();
1276 }
1277 
1278 
1281 {
1282  QMutexLocker locker(&m_mutex);
1283  for(auto &tims_frame : m_timsFrameBaseCache)
1284  {
1285  if(tims_frame.get()->getId() == timsId)
1286  {
1287  m_timsFrameBaseCache.push_back(tims_frame);
1288  return tims_frame;
1289  }
1290  }
1291 
1292  m_timsFrameBaseCache.push_back(getTimsFrameBaseCstSPtr(timsId));
1293  if(m_timsFrameBaseCache.size() > m_cacheSize)
1294  m_timsFrameBaseCache.pop_front();
1295  return m_timsFrameBaseCache.back();
1296 }
1297 
1300 {
1301  QMutexLocker locker(&m_mutex);
1302  for(auto &tims_frame : m_timsFrameCache)
1303  {
1304  if(tims_frame.get()->getId() == timsId)
1305  {
1306  m_timsFrameCache.push_back(tims_frame);
1307  return tims_frame;
1308  }
1309  }
1310 
1311  m_timsFrameCache.push_back(getTimsFrameCstSPtr(timsId));
1312  if(m_timsFrameCache.size() > m_cacheSize)
1313  m_timsFrameCache.pop_front();
1314  return m_timsFrameCache.back();
1315 }
1316 
1317 void
1319 {
1320  mcsp_ms2Filter = filter;
1321 }
1322 void
1324 {
1325  mcsp_ms1Filter = filter;
1326 }
1327 
1328 std::vector<TimsXicStructure>
1330  const std::vector<std::size_t> &precursor_id_list,
1331  PrecisionPtr precision_ptr,
1332  XicExtractMethod xicExtractMethod,
1333  double rtRange) const
1334 {
1335 
1336  qDebug();
1337  std::vector<TimsXicStructure> xic_list;
1338 
1339  try
1340  {
1341  QSqlDatabase qdb = openDatabaseConnection();
1342 
1343  for(auto precursor_id : precursor_id_list)
1344  {
1345  QSqlQuery q = qdb.exec(
1346  QString("SELECT Frames.Time, "
1347  "PasefFrameMsMsInfo.Frame,PasefFrameMsMsInfo.ScanNumBegin,"
1348  "PasefFrameMsMsInfo.ScanNumEnd, Precursors.MonoisotopicMz, "
1349  "Precursors.Charge FROM "
1350  "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1351  "PasefFrameMsMsInfo.Precursor=Precursors.Id INNER JOIN "
1352  "Frames ON PasefFrameMsMsInfo.Frame=Frames.Id where "
1353  "Precursors.Id=%1;")
1354  .arg(precursor_id));
1355  if(q.lastError().isValid())
1356  {
1357  qDebug();
1358  throw PappsoException(
1359  QObject::tr(
1360  "ERROR in TIMS sqlite database file %1, executing SQL "
1361  "command %2:\n%3\n%4\n%5")
1362  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1363  .arg(q.lastQuery())
1364  .arg(qdb.lastError().databaseText())
1365  .arg(qdb.lastError().driverText())
1366  .arg(qdb.lastError().nativeErrorCode()));
1367  }
1368 
1369  while(q.next())
1370  {
1371  // Frame, ScanNumBegin, ScanNumEnd, IsolationMz, ColliqionEnergy,
1372  // Precursor
1373  // Id, LargestPeakMz, AverageMz, MonoisotopicMz, Charge,
1374  // ScanNumber, Intensity, Parent
1375  TimsXicStructure xic_structure;
1376 
1377  xic_structure.precursorId = precursor_id;
1378  xic_structure.mzRange =
1379  MzRange(q.value(4).toDouble(), precision_ptr);
1380  xic_structure.scanNumBegin = q.value(2).toUInt();
1381  xic_structure.scanNumEnd = q.value(3).toUInt();
1382  xic_structure.rtTarget = q.value(0).toDouble();
1383  // xic_structure.charge = q.value(5).toUInt();
1384  xic_structure.xicSptr = std::make_shared<Xic>();
1385 
1386  xic_list.push_back(xic_structure);
1387  }
1388  }
1389  qDebug();
1390 
1391  TimsXicExtractorInterface *extractor_p = new TimsDirectXicExtractor(this);
1392  extractor_p->setXicExtractMethod(xicExtractMethod);
1393  extractor_p->extractTimsXicList(xic_list, rtRange);
1394  }
1395  catch(PappsoException &error)
1396  {
1397  throw error;
1398  }
1399  catch(std::exception &error)
1400  {
1401  qDebug() << QString("Failure %1 ").arg(error.what());
1402  }
1403 
1404  qDebug();
1405  return xic_list;
1406 }
1407 
1408 void
1410  std::vector<TimsXicStructure> &tims_xic_structure_list,
1411  pappso::XicExtractMethod xicExtractMethod,
1412  double rtRange) const
1413 {
1414  try
1415  {
1416 
1417  TimsXicExtractorInterface *extractor_p = new TimsDirectXicExtractor(this);
1418  extractor_p->setXicExtractMethod(xicExtractMethod);
1419  extractor_p->extractTimsXicList(tims_xic_structure_list, rtRange);
1420  }
1421  catch(PappsoException &error)
1422  {
1423  throw error;
1424  }
1425  catch(std::exception &error)
1426  {
1427  qDebug() << QString("Failure %1 ").arg(error.what());
1428  }
1429 
1430  qDebug();
1431 }
1432 
1433 
1436  std::size_t precursor_id, PrecisionPtr precision_ptr) const
1437 {
1438 
1439  qDebug();
1440  TimsXicStructure tims_xic_structure;
1441 
1442  try
1443  {
1444  QSqlDatabase qdb = openDatabaseConnection();
1445  QSqlQuery q = qdb.exec(
1446  QString("SELECT Frames.Time, "
1447  "PasefFrameMsMsInfo.Frame,PasefFrameMsMsInfo.ScanNumBegin,"
1448  "PasefFrameMsMsInfo.ScanNumEnd, Precursors.MonoisotopicMz, "
1449  "Precursors.Charge FROM "
1450  "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1451  "PasefFrameMsMsInfo.Precursor=Precursors.Id INNER JOIN "
1452  "Frames ON PasefFrameMsMsInfo.Frame=Frames.Id where "
1453  "Precursors.Id=%1;")
1454  .arg(precursor_id));
1455  if(q.lastError().isValid())
1456  {
1457  qDebug();
1458  throw PappsoException(
1459  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1460  "command %2:\n%3\n%4\n%5")
1461  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1462  .arg(q.lastQuery())
1463  .arg(qdb.lastError().databaseText())
1464  .arg(qdb.lastError().driverText())
1465  .arg(qdb.lastError().nativeErrorCode()));
1466  }
1467 
1468  while(q.next())
1469  {
1470  // Frame, ScanNumBegin, ScanNumEnd, IsolationMz, ColliqionEnergy,
1471  // Precursor
1472  // Id, LargestPeakMz, AverageMz, MonoisotopicMz, Charge,
1473  // ScanNumber, Intensity, Parent
1474 
1475  tims_xic_structure.precursorId = precursor_id;
1476  tims_xic_structure.mzRange =
1477  MzRange(q.value(4).toDouble(), precision_ptr);
1478  tims_xic_structure.scanNumBegin = q.value(2).toUInt();
1479  tims_xic_structure.scanNumEnd = q.value(3).toUInt();
1480  tims_xic_structure.rtTarget = q.value(0).toDouble();
1481  // xic_structure.charge = q.value(5).toUInt();
1482  tims_xic_structure.xicSptr = std::make_shared<Xic>();
1483  }
1484  }
1485  catch(PappsoException &error)
1486  {
1487  throw error;
1488  }
1489  catch(std::exception &error)
1490  {
1491  qDebug() << QString("Failure %1 ").arg(error.what());
1492  }
1493  return tims_xic_structure;
1494 }
1495 
1496 
1497 std::map<quint32, quint32>
1498 TimsData::getRawMs2ByPrecursorId(std::size_t precursor_index)
1499 {
1500  qDebug();
1501  std::map<quint32, quint32> raw_spectrum;
1502  try
1503  {
1504  QSqlDatabase qdb = openDatabaseConnection();
1505 
1506  qdb = openDatabaseConnection();
1507  QSqlQuery q =
1508  qdb.exec(QString("SELECT PasefFrameMsMsInfo.*, Precursors.* FROM "
1509  "PasefFrameMsMsInfo INNER JOIN Precursors ON "
1510  "PasefFrameMsMsInfo.Precursor=Precursors.Id where "
1511  "Precursors.Id=%1;")
1512  .arg(precursor_index));
1513  if(q.lastError().isValid())
1514  {
1515  qDebug();
1516  throw PappsoException(
1517  QObject::tr("ERROR in TIMS sqlite database file %1, executing SQL "
1518  "command %2:\n%3\n%4\n%5")
1519  .arg(m_timsDataDirectory.absoluteFilePath("analysis.tdf"))
1520  .arg(q.lastQuery())
1521  .arg(qdb.lastError().databaseText())
1522  .arg(qdb.lastError().driverText())
1523  .arg(qdb.lastError().nativeErrorCode()));
1524  }
1525  qDebug();
1526  // m_mutex.unlock();
1527  if(q.size() == 0)
1528  {
1529 
1530  throw ExceptionNotFound(
1531  QObject::tr(
1532  "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1533  "id=%1 not found")
1534  .arg(precursor_index));
1535  }
1536  else
1537  {
1538  // qDebug() << " q.size()="<< q.size();
1539  qDebug();
1540  bool first = true;
1541  std::size_t scan_mobility_start = 0;
1542  std::size_t scan_mobility_end = 0;
1543  std::vector<std::size_t> tims_frame_list;
1544 
1545  while(q.next())
1546  {
1547  tims_frame_list.push_back(q.value(0).toLongLong());
1548  if(first)
1549  {
1550 
1551  scan_mobility_start = q.value(1).toLongLong();
1552  scan_mobility_end = q.value(2).toLongLong();
1553 
1554  first = false;
1555  }
1556  }
1557  // QMutexLocker locker(&m_mutex_spectrum);
1558  qDebug();
1559  pappso::TimsFrameCstSPtr tims_frame, previous_frame;
1560  // TracePlusCombiner combiner;
1561  // MapTrace combiner_result;
1562  for(std::size_t tims_id : tims_frame_list)
1563  {
1564  tims_frame = getTimsFrameCstSPtrCached(tims_id);
1565  qDebug();
1566  /*combiner.combine(combiner_result,
1567  tims_frame.get()->cumulateScanToTrace(
1568  scan_mobility_start, scan_mobility_end));*/
1569  if(previous_frame.get() != nullptr)
1570  {
1571  if(previous_frame.get()->hasSameCalibrationData(
1572  *tims_frame.get()))
1573  {
1574  }
1575  else
1576  {
1577  throw ExceptionNotFound(
1578  QObject::tr(
1579  "ERROR in %1 %2, different calibration data "
1580  "between frame id %3 and frame id %4")
1581  .arg(__FILE__)
1582  .arg(__FUNCTION__)
1583  .arg(previous_frame.get()->getId())
1584  .arg(tims_frame.get()->getId()));
1585  }
1586  }
1587  tims_frame.get()->cumulateScansInRawMap(
1588  raw_spectrum, scan_mobility_start, scan_mobility_end);
1589  qDebug();
1590 
1591  previous_frame = tims_frame;
1592  }
1593  qDebug() << " precursor_index=" << precursor_index
1594  << " num_rows=" << tims_frame_list.size()
1595  << " sql=" << q.lastQuery() << " "
1596  << (std::size_t)QThread::currentThreadId();
1597  if(first == true)
1598  {
1599  throw ExceptionNotFound(
1600  QObject::tr(
1601  "ERROR in getQualifiedMassSpectrumByPrecursorId, precursor "
1602  "id=%1 not found")
1603  .arg(precursor_index));
1604  }
1605  qDebug();
1606  }
1607  }
1608 
1609  catch(PappsoException &error)
1610  {
1611  throw error;
1612  }
1613  catch(std::exception &error)
1614  {
1615  qDebug() << QString("Failure %1 ").arg(error.what());
1616  }
1617  return raw_spectrum;
1618  qDebug();
1619 }
void setNativeId(const QString &native_id)
void setSpectrumIndex(std::size_t index)
Class to represent a mass spectrum.
Definition: massspectrum.h:71
MzCalibrationInterfaceSPtr getInstance(double T1_frame, double T2_frame, const QSqlRecord &mzcalibration_record)
const char * what() const noexcept override
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)
TimsFrameSPtr getTimsFrameSPtrByOffset(std::size_t timsId, std::size_t timsOffset) const
Definition: timsbindec.cpp:142
QualifiedMassSpectrum getQualifiedMs1MassSpectrumByPrecursorId(std::size_t ms2_index, std::size_t precursor_index, bool want_binary_data)
Definition: timsdata.cpp:862
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:1323
void fillFrameIdDescrList()
private function to fill m_frameIdDescrList
Definition: timsdata.cpp:279
TimsFrameBaseCstSPtr getTimsFrameBaseCstSPtr(std::size_t timsId) const
get a Tims frame base (no binary data file access) with his database ID
Definition: timsdata.cpp:385
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:584
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:1318
std::vector< FrameIdDescr > m_frameIdDescrList
store every frame id and corresponding sizes
Definition: timsdata.h:302
std::map< std::size_t, QSqlRecord > m_mapFramesRecord
Definition: timsdata.h:288
TimsFrameCstSPtr getTimsFrameCstSPtrCached(std::size_t timsId)
get a Tims frame with his database ID but look in the cache first
Definition: timsdata.cpp:1299
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:605
TimsData(QDir timsDataDirectory)
build using the tims data directory
Definition: timsdata.cpp:46
void extractXicListByTimsXicStructureList(std::vector< TimsXicStructure > &tims_xic_structure_list, XicExtractMethod xicExtractMethod, double rtRange) const
extract a list of XICs from Tims data
Definition: timsdata.cpp:1409
QualifiedMassSpectrum getQualifiedMassSpectrumByRawIndex(std::size_t spectrum_index, bool want_binary_data)
Definition: timsdata.cpp:743
QSqlDatabase openDatabaseConnection() const
Definition: timsdata.cpp:218
TimsFrameCstSPtr getTimsFrameCstSPtr(std::size_t timsId) const
get a Tims frame with his database ID
Definition: timsdata.cpp:496
std::size_t getRawIndexFromCoordinate(std::size_t frame_id, std::size_t scan_num) const
Definition: timsdata.cpp:353
TimsXicStructure getTimsXicStructureFromPrecursorId(std::size_t precursor_id, PrecisionPtr precision_ptr) const
Definition: timsdata.cpp:1435
std::size_t m_totalNumberOfScans
Definition: timsdata.h:272
std::deque< TimsFrameCstSPtr > m_timsFrameCache
Definition: timsdata.h:275
std::size_t m_cacheSize
Definition: timsdata.h:274
unsigned int getMsLevelBySpectrumIndex(std::size_t spectrum_index)
Definition: timsdata.cpp:734
std::map< int, QSqlRecord > m_mapMzCalibrationRecord
Definition: timsdata.h:286
std::map< int, QSqlRecord > m_mapTimsCalibrationRecord
Definition: timsdata.h:287
QMutex m_mutex
Definition: timsdata.h:309
bool m_builtinMs2Centroid
enable builtin centroid on raw tims integers by default
Definition: timsdata.h:283
std::vector< std::size_t > getTimsMS1FrameIdRange(double rt_begin, double rt_end) const
Definition: timsdata.cpp:460
QDir m_timsDataDirectory
Definition: timsdata.h:269
std::vector< std::size_t > getClosestPrecursorIdByMz(std::vector< std::vector< double >> ids, double mz_value)
Definition: timsdata.cpp:710
MzCalibrationStore * mpa_mzCalibrationStore
Definition: timsdata.h:290
TimsFrameBaseCstSPtr getTimsFrameBaseCstSPtrCached(std::size_t timsId)
Definition: timsdata.cpp:1280
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:1498
std::vector< TimsXicStructure > extractXicListByPrecursorIds(const std::vector< std::size_t > &precursor_id_list, PrecisionPtr precision_ptr, XicExtractMethod xicExtractMethod, double rtRange) const
extract a list of XICs from Tims data
Definition: timsdata.cpp:1329
std::size_t getTotalNumberOfScans() const
get the total number of scans
Definition: timsdata.cpp:592
std::deque< TimsFrameBaseCstSPtr > m_timsFrameBaseCache
Definition: timsdata.h:276
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:307
TimsBinDec * mpa_timsBinDec
Definition: timsdata.h:270
void setMs2BuiltinCentroid(bool centroid)
enable or disable simple centroid filter on raw tims data for MS2
Definition: timsdata.cpp:267
std::vector< std::size_t > getMatchPrecursorIdByKo(std::vector< std::vector< double >> ids, double ko_value)
Definition: timsdata.cpp:684
pappso::FilterInterfaceCstSPtr mcsp_ms1Filter
Definition: timsdata.h:279
void getQualifiedMs2MassSpectrumByPrecursorId(QualifiedMassSpectrum &mass_spectrum, std::size_t ms2_index, std::size_t precursor_index, bool want_binary_data)
Definition: timsdata.cpp:1027
bool getMs2BuiltinCentroid() const
tells if simple centroid filter on raw tims data for MS2 is enabled or not
Definition: timsdata.cpp:273
std::pair< std::size_t, std::size_t > getScanCoordinateFromRawIndex(std::size_t spectrum_index) const
Definition: timsdata.cpp:319
pappso::FilterInterfaceCstSPtr mcsp_ms2Filter
Definition: timsdata.h:278
pappso::MassSpectrumCstSPtr getMassSpectrumCstSPtrByRawIndex(std::size_t raw_index)
get a mass spectrum given its spectrum index
Definition: timsdata.cpp:376
std::size_t getTotalNumberOfPrecursors() const
get the number of precursors analyzes by PASEF
Definition: timsdata.cpp:599
std::size_t m_totalNumberOfPrecursors
Definition: timsdata.h:273
void setXicExtractMethod(XicExtractMethod method)
set the XIC extraction method
virtual void extractTimsXicList(std::vector< TimsXicStructure > &timsXicList, double rtRange) const =0
extract XICs for given coordinates XICs are extracted given their coordinates : retention time target...
virtual MapTrace & combine(MapTrace &map_trace, const Trace &trace) const override
A simple container of DataPoint instances.
Definition: trace.h:132
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 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.
std::shared_ptr< const FilterInterface > FilterInterfaceCstSPtr
XicExtractMethod
Definition: types.h:200
std::shared_ptr< const TimsFrame > TimsFrameCstSPtr
Definition: timsframe.h:42
structure needed to extract XIC from Tims data
Definition: timsdata.h:49
pappso::pappso_double rtTarget
targeted retention time for this precursor
Definition: timsdata.h:69
std::size_t scanNumEnd
mobility index end
Definition: timsdata.h:65
MzRange mzRange
mass range to extract
Definition: timsdata.h:58
XicSPtr xicSptr
extracted xic
Definition: timsdata.h:73
std::size_t scanNumBegin
mobility index begin
Definition: timsdata.h:61
std::size_t precursorId
the corresponding precursor id
Definition: timsdata.h:51
main Tims data handler
minimum functions to extract XICs from Tims Data