libpappsomspp
Library for mass spectrometry
tandemwrapperrun.cpp
Go to the documentation of this file.
1 /**
2  * \file pappsomspp/processing/tandemwrapper/tandemwrapperrun.cpp
3  * \date 25/01/2020
4  * \author Olivier Langella
5  * \brief actually does really run tandem directly on Bruker's data
6  */
7 
8 /*******************************************************************************
9  * Copyright (c) 2020 Olivier Langella <Olivier.Langella@u-psud.fr>.
10  *
11  * This file is part of PAPPSOms-tools.
12  *
13  * PAPPSOms-tools 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-tools 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-tools. If not, see <http://www.gnu.org/licenses/>.
25  *
26  ******************************************************************************/
27 
28 #include "tandemwrapperrun.h"
29 #include <QDebug>
30 #include <QFileInfo>
31 #include <QSettings>
32 #include <QThread>
33 #include <QThreadPool>
34 #include "../../pappsoexception.h"
35 #include "../../msfile/msfileaccessor.h"
36 #include "../../msrun/private/timsmsrunreaderms2.h"
37 #include "../../processing/filters/filterpseudocentroid.h"
38 #include "../../processing/filters/filtertriangle.h"
39 #include "../../processing/filters/filterchargedeconvolution.h"
40 #include "../../msrun/output/mzxmloutput.h"
41 #include "xtandeminputsaxhandler.h"
44 
45 namespace pappso
46 {
47 TandemWrapperRun::TandemWrapperRun(const QString &tandem_binary,
48  const QString &tmp_dir)
49 {
50 
51  setTandemBinaryPath(tandem_binary);
52 
53  if(!tmp_dir.isEmpty())
54  {
55  mpa_temporaryDirectory = new QTemporaryDir(tmp_dir + "/xtpwrp");
56  }
57  else
58  {
59  mpa_temporaryDirectory = new QTemporaryDir(QDir::tempPath() + "/xtpwrp");
60  }
61  mpa_temporaryDirectory->setAutoRemove(true);
62  if(!mpa_temporaryDirectory->isValid())
63  {
65  QObject::tr("ERROR: unable to create temporary directory %1\n Please "
66  "check file system permissions")
67  .arg(mpa_temporaryDirectory->path()));
68  }
69 }
70 
72 {
73  if(mpa_temporaryDirectory != nullptr)
74  {
76  }
77 }
78 
79 void
80 TandemWrapperRun::setTandemBinaryPath(const QString &tandem_binary_path)
81 {
82 
83 
84  m_tandemBinary = tandem_binary_path;
85  QSettings settings;
86  if(m_tandemBinary.isEmpty())
87  {
89  settings.value("path/tandem_binary", "/usr/bin/tandem").toString();
90  }
91  // check for tandem executable
93 
94  qDebug() << m_tandemVersion;
95  settings.setValue("path/tandem_binary", m_tandemBinary);
96 }
97 
98 
99 const QString
100 TandemWrapperRun::checkXtandemVersion(const QString &tandem_bin_path)
101 {
102  qDebug();
103  // check tandem path
104  QFileInfo tandem_exe(tandem_bin_path);
105  if(!tandem_exe.exists())
106  {
107  // dir.path() returns the unique directory path
109  QObject::tr(
110  "X!Tandem software not found at %1.\nPlease check the X!Tandem "
111  "installation on your computer and set tandem.exe path.")
112  .arg(tandem_exe.absoluteFilePath()));
113  }
114  if(!tandem_exe.isReadable())
115  {
116  // dir.path() returns the unique directory path
118  QObject::tr("Please check permissions on X!Tandem software found at %1 "
119  "(file not readable).")
120  .arg(tandem_exe.absoluteFilePath()));
121  }
122  if(!tandem_exe.isExecutable())
123  {
124  // dir.path() returns the unique directory path
126  QObject::tr("Please check permissions on X!Tandem software found at %1 "
127  "(file not executable).")
128  .arg(tandem_exe.absoluteFilePath()));
129  }
130 
131 
132  QString version_return;
133  QStringList arguments;
134 
135  arguments << "-v";
136 
137  QProcess *xt_process = new QProcess();
138  // hk_process->setWorkingDirectory(QFileInfo(_hardklor_exe).absolutePath());
139 
140  xt_process->start(tandem_bin_path, arguments);
141 
142  if(!xt_process->waitForStarted())
143  {
145  QObject::tr("X!Tandem %1 process failed to start")
146  .arg(m_tandemVersion));
147  }
148 
149  while(xt_process->waitForReadyRead(1000))
150  {
151  }
152  /*
153  if (!xt_process->waitForFinished(_max_xt_time_ms)) {
154  throw pappso::PappsoException(QObject::tr("can't wait for X!Tandem process
155  to finish : timeout at %1").arg(_max_xt_time_ms));
156  }
157  */
158  QByteArray result = xt_process->readAll();
159 
160 
161  qDebug() << result.constData();
162 
163  // X! TANDEM Jackhammer TPP (2013.06.15.1 - LabKey, Insilicos, ISB)
164 
165  QRegExp parse_version("(.*) TANDEM ([A-Z,a-z, ]+) \\(([^ ,^\\)]*)(.*)");
166  qDebug() << parse_version;
167  // Pattern patt = Pattern.compile("X! TANDEM [A-Z]+ \\‍((.*)\\‍)",
168  // Pattern.CASE_INSENSITIVE);
169 
170  if(parse_version.exactMatch(result.constData()))
171  {
172  version_return = QString("X!Tandem %1 %2")
173  .arg(parse_version.capturedTexts()[2])
174  .arg(parse_version.capturedTexts()[3]); //.join(" ");
175  }
176  else
177  {
179  QObject::tr("This executable %1 may not be a valid X!Tandem software. "
180  "Please check your X!Tandem installation.")
181  .arg(tandem_bin_path));
182  }
183 
184  QProcess::ExitStatus Status = xt_process->exitStatus();
185  delete xt_process;
186  if(Status != 0)
187  {
188  // != QProcess::NormalExit
190  QObject::tr("error executing X!Tandem Status != 0 : %1 %2\n%3")
191  .arg(tandem_bin_path)
192  .arg(arguments.join(" ").arg(result.data())));
193  }
194  qDebug();
195  return version_return;
196 }
197 
198 
199 bool
201 {
202  return false;
203 }
204 
205 
206 void
208 {
209  *mp_outputStream << m_xtProcess->readAllStandardOutput();
210  mp_outputStream->flush();
211 }
212 
213 void
215 {
216  *mp_errorStream << m_xtProcess->readAllStandardError();
217  mp_errorStream->flush();
218 }
219 
220 void
222  const QString &tmp_tandem_output,
223  const QString &final_tandem_output,
224  const QString &original_msdata_file_name)
225 {
226 
227  XtandemOutputSaxHandler wrap_output(final_tandem_output,
228  original_msdata_file_name);
229 
230  wrap_output.setInputParameters("spectrum, timstof MS2 filters",
232 
233  QFile qfile(tmp_tandem_output);
234  QXmlInputSource xmlInputSource(&qfile);
235  QXmlSimpleReader simplereader;
236  simplereader.setContentHandler(&wrap_output);
237  simplereader.setErrorHandler(&wrap_output);
238 
239  if(simplereader.parse(xmlInputSource))
240  {
241  }
242  else
243  {
245  QObject::tr("Error reading %1 X!Tandem output file :\n %2")
246  .arg(tmp_tandem_output)
247  .arg(wrap_output.errorString()));
248  }
249 }
250 
251 void
252 TandemWrapperRun::readTandemPresetFile(const QString &tandem_preset_file)
253 {
254  // get number of threads and centroid parameters from tandem preset
255 
256  XtandemPresetSaxHandler preset_handler;
257 
258  QFile qfile(tandem_preset_file);
259  QXmlInputSource xmlInputSource(&qfile);
260  QXmlSimpleReader simplereader;
261  simplereader.setContentHandler(&preset_handler);
262  simplereader.setErrorHandler(&preset_handler);
263 
264  if(simplereader.parse(xmlInputSource))
265  {
266 
267  int ideal_number_of_thread = QThread::idealThreadCount();
268  int cpu_number = preset_handler.getNumberOfThreads();
269  qDebug() << " cpu_number=" << cpu_number;
270  // QThreadPool::globalInstance()->setMaxThreadCount(1);
271  if(cpu_number > ideal_number_of_thread)
272  {
273  cpu_number = ideal_number_of_thread;
274  }
275  else
276  {
277  if(cpu_number > 0)
278  {
279  QThreadPool::globalInstance()->setMaxThreadCount(cpu_number);
280 
281  qDebug() << " maxThreadCount="
282  << QThreadPool::globalInstance()->maxThreadCount();
283  }
284  }
285 
286  QString ms2_filters_str = preset_handler.getMs2FiltersOptions();
288  std::make_shared<pappso::FilterSuiteString>(ms2_filters_str);
289  }
290  else
291  {
293  QObject::tr("Error reading %1 X!Tandem preset file :\n %2")
294  .arg(tandem_preset_file)
295  .arg(preset_handler.errorString()));
296  }
297 }
298 
299 
300 void
301 TandemWrapperRun::wrapTandemInputFile(const QString &tandem_input_file)
302 {
303  // read original tandem input file
304  // store original ms data file name
305  // create new mzXML data file in temporary directory
306  // create new tandem input file based on new mzXML file
307  QString mzxml_data_file_name =
308  mpa_temporaryDirectory->filePath("msdata.mzxml");
309  QString wrapped_tandem_input =
310  mpa_temporaryDirectory->filePath("input_tandem.xml");
311  QString wrapped_tandem_output =
312  mpa_temporaryDirectory->filePath("output_tandem.xml");
313  XtandemInputSaxHandler wrap_input(
314  mzxml_data_file_name, wrapped_tandem_input, wrapped_tandem_output);
315 
316  QFile qfile(tandem_input_file);
317  QXmlInputSource xmlInputSource(&qfile);
318  QXmlSimpleReader simplereader;
319  simplereader.setContentHandler(&wrap_input);
320  simplereader.setErrorHandler(&wrap_input);
321 
322  if(simplereader.parse(xmlInputSource))
323  {
324  }
325  else
326  {
328  QObject::tr("Error reading %1 X!Tandem input file :\n %2")
329  .arg(tandem_input_file)
330  .arg(wrap_input.errorString()));
331  }
332 
333  // get number of threads and centroid parameters from tandem preset
335 
336 
337  // convert to mzXML
338  QString original_msdata_file_name = wrap_input.getOriginalMsDataFileName();
339  convertOrginalMsData2mzXmlData(original_msdata_file_name,
340  mzxml_data_file_name);
341 
342 
343  // launch tandem
344  runTandem(wrapped_tandem_input);
345 
346  // rewrite tandem result file
347  writeFinalTandemOutput(wrapped_tandem_output,
348  wrap_input.getOriginalTandemOutputFileName(),
349  original_msdata_file_name);
350 }
351 
352 void
354  const QString &target) const
355 {
356  qDebug();
357  pappso::MsFileAccessor origin_access(origin, "runa1");
358  origin_access.setPreferedFileReaderType(pappso::MzFormat::brukerTims,
360  origin_access.getMsRunIds();
361 
362  pappso::MsRunReaderSPtr p_reader;
363  p_reader = origin_access.msRunReaderSp(origin_access.getMsRunIds().front());
364 
365  pappso::TimsMsRunReaderMs2 *tims2_reader =
366  dynamic_cast<pappso::TimsMsRunReaderMs2 *>(p_reader.get());
367  if(tims2_reader != nullptr)
368  {
369  qDebug();
370  tims2_reader->setMs2BuiltinCentroid(true);
371 
372  if(msp_ms2FilterSuiteString != nullptr)
373  {
375  }
376  qDebug();
377  }
378 
379 
380  pappso::MzxmlOutput *p_mzxml_output;
381  QFile output_file(target);
382  // qDebug() << " TsvDirectoryWriter::writeSheet " <<
383  // QFileInfo(*_p_ofile).absoluteFilePath();
384  if(output_file.open(QIODevice::WriteOnly))
385  {
386  p_mzxml_output =
387  new pappso::MzxmlOutput(QTextStream(&output_file).device());
388 
389  p_mzxml_output->maskMs1(true);
390 
391  p_mzxml_output->setReadAhead(true);
392 
393  p_mzxml_output->write(p_reader.get());
394 
395  p_mzxml_output->close();
396  }
397  else
398  {
400  tr("unable to write into %1 mzXML output file").arg(target));
401  }
402 
403  qDebug();
404 }
405 
406 void
407 TandemWrapperRun::run(const QString &tandem_input_file,
408  QTextStream &output_stream,
409  QTextStream &error_stream)
410 {
411  mp_outputStream = &output_stream;
412  mp_errorStream = &error_stream;
413 
414  wrapTandemInputFile(tandem_input_file);
415  mp_outputStream = nullptr;
416  mp_errorStream = nullptr;
417 }
418 void
419 TandemWrapperRun::runTandem(const QString &tandem_input_file)
420 {
421 
422  m_xtProcess = new QProcess();
423  QStringList arguments;
424 
425  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
426 
427  arguments << tandem_input_file;
428  // hk_process->setWorkingDirectory(QFileInfo(_hardklor_exe).absolutePath());
429  m_xtProcess->start(m_tandemBinary, arguments);
430 
431  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
432 
433  connect(m_xtProcess,
434  &QProcess::readyReadStandardOutput,
435  this,
437  connect(m_xtProcess,
438  &QProcess::readyReadStandardError,
439  this,
441 
442 
443  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
444 
445  if(!m_xtProcess->waitForStarted())
446  {
448  QObject::tr("X!Tandem process failed to start"));
449  }
450 
451  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
452 
453  while(m_xtProcess->waitForFinished(m_maxTandemRunTimeMs))
454  {
455  //_p_monitor->appendText(xt_process->readAll().data());
456  // data.append(xt_process->readAll());
457  if(shouldIstop())
458  {
459  m_xtProcess->kill();
460  delete m_xtProcess;
462  QObject::tr("X!Tandem stopped by the user processing on file %1")
463  .arg(tandem_input_file));
464  }
465  }
466 
467  QProcess::ExitStatus Status = m_xtProcess->exitStatus();
468 
469  delete m_xtProcess;
470  if(Status != 0)
471  {
472  // != QProcess::NormalExit
474  QObject::tr("error executing X!Tandem Status != 0 : %1")
475  .arg(m_tandemBinary));
476  }
477  m_xtProcess = nullptr;
478 }
479 
480 QString
482 {
483  if(msp_ms2FilterSuiteString == nullptr)
484  return "";
485  return msp_ms2FilterSuiteString.get()->toString();
486 }
487 
488 } // namespace pappso
pappso::TandemWrapperRun::shouldIstop
bool shouldIstop()
Definition: tandemwrapperrun.cpp:200
pappso::XtandemInputSaxHandler::errorString
QString errorString() const
Definition: xtandeminputsaxhandler.cpp:265
pappso::TandemWrapperRun::m_maxTandemRunTimeMs
int m_maxTandemRunTimeMs
Definition: tandemwrapperrun.h:119
tandemwrapperrun.h
actually does really run tandem directly on Bruker's data
pappso::MzxmlOutput
Definition: mzxmloutput.h:43
xtandeminputsaxhandler.h
rewrites tandem xml input file with temporary files
pappso::XtandemInputSaxHandler
Definition: xtandeminputsaxhandler.h:39
pappso::MsFileAccessor::setPreferedFileReaderType
void setPreferedFileReaderType(MzFormat format, FileReaderType reader_type)
given an mz format, explicitly set the prefered reader
Definition: msfileaccessor.cpp:298
pappso::XtandemOutputSaxHandler::errorString
QString errorString() const
Definition: xtandemoutputsaxhandler.cpp:254
xtandemoutputsaxhandler.h
rewrites tandem xml output file with temporary files
pappso
tries to keep as much as possible monoisotopes, removing any possible C13 peaks and changes multichar...
Definition: aa.cpp:39
pappso::MsRunReaderSPtr
std::shared_ptr< MsRunReader > MsRunReaderSPtr
Definition: msrunreader.h:151
pappso::FileReaderType::pwiz
@ pwiz
pappso::XtandemOutputSaxHandler
Definition: xtandemoutputsaxhandler.h:39
pappso::TandemWrapperRun::m_tandemVersion
QString m_tandemVersion
Definition: tandemwrapperrun.h:117
pappso::TandemWrapperRun::msp_ms2FilterSuiteString
std::shared_ptr< FilterSuiteString > msp_ms2FilterSuiteString
Definition: tandemwrapperrun.h:122
pappso::XtandemPresetSaxHandler
Definition: xtandempresetsaxhandler.h:41
pappso::TimsMsRunReaderMs2::setMs2BuiltinCentroid
void setMs2BuiltinCentroid(bool centroid)
enable or disable simple centroid filter on raw tims data for MS2
Definition: timsmsrunreaderms2.cpp:58
xtandempresetsaxhandler.h
read tandem preset file to get centroid parameters and number of threads
pappso::TandemWrapperRun::checkXtandemVersion
const QString checkXtandemVersion(const QString &tandem_bin_path)
Definition: tandemwrapperrun.cpp:100
pappso::MzxmlOutput::write
void write(MsRunReader *p_msrunreader)
Definition: mzxmloutput.cpp:95
pappso::TandemWrapperRun::setTandemBinaryPath
void setTandemBinaryPath(const QString &tandem_binary_path)
Definition: tandemwrapperrun.cpp:80
pappso::TandemWrapperRun::writeFinalTandemOutput
void writeFinalTandemOutput(const QString &tmp_tandem_output, const QString &final_tandem_output, const QString &original_msdata_file_name)
tandem output modification tandem output is modified to contain the Bruker's file as input and centro...
Definition: tandemwrapperrun.cpp:221
pappso::TandemWrapperRun::readyReadStandardOutput
void readyReadStandardOutput()
Definition: tandemwrapperrun.cpp:207
pappso::XtandemPresetSaxHandler::errorString
QString errorString() const
Definition: xtandempresetsaxhandler.cpp:197
pappso::XtandemPresetSaxHandler::getNumberOfThreads
int getNumberOfThreads() const
Definition: xtandempresetsaxhandler.cpp:255
pappso::TandemWrapperRun::runTandem
void runTandem(const QString &tandem_input_file)
run a tandem job
Definition: tandemwrapperrun.cpp:419
pappso::MsFileAccessor
Definition: msfileaccessor.h:35
pappso::TandemWrapperRun::getMs2FilterSuiteString
QString getMs2FilterSuiteString() const
gets the list of filters used on MS2 spectrum
Definition: tandemwrapperrun.cpp:481
pappso::TandemWrapperRun::mp_errorStream
QTextStream * mp_errorStream
Definition: tandemwrapperrun.h:127
pappso::TandemWrapperRun::mpa_temporaryDirectory
QTemporaryDir * mpa_temporaryDirectory
Definition: tandemwrapperrun.h:129
pappso::TandemWrapperRun::readyReadStandardError
void readyReadStandardError()
Definition: tandemwrapperrun.cpp:214
pappso::TandemWrapperRun::m_xtProcess
QProcess * m_xtProcess
Definition: tandemwrapperrun.h:120
pappso::MsFileAccessor::getMsRunIds
std::vector< MsRunIdCstSPtr > getMsRunIds()
Definition: msfileaccessor.cpp:67
pappso::TimsMsRunReaderMs2
Definition: timsmsrunreaderms2.h:41
pappso::TandemWrapperRun::~TandemWrapperRun
~TandemWrapperRun()
Definition: tandemwrapperrun.cpp:71
pappso::XtandemInputSaxHandler::getOriginalTandemOutputFileName
const QString & getOriginalTandemOutputFileName() const
Definition: xtandeminputsaxhandler.cpp:331
pappso::MsFileAccessor::msRunReaderSp
MsRunReaderSPtr msRunReaderSp(MsRunIdCstSPtr ms_run_id)
Definition: msfileaccessor.cpp:174
pappso::TandemWrapperRun::TandemWrapperRun
TandemWrapperRun(const QString &tandem_binary, const QString &tmp_dir)
prepare a tandem run
Definition: tandemwrapperrun.cpp:47
pappso::TandemWrapperRun::m_tandemBinary
QString m_tandemBinary
Definition: tandemwrapperrun.h:116
pappso::TandemWrapperRun::readTandemPresetFile
void readTandemPresetFile(const QString &tandem_preset_file)
Definition: tandemwrapperrun.cpp:252
pappso::MzxmlOutput::setReadAhead
void setReadAhead(bool read_ahead)
Definition: mzxmloutput.cpp:90
pappso::XtandemInputSaxHandler::getOriginalTandemPresetFileName
const QString & getOriginalTandemPresetFileName() const
Definition: xtandeminputsaxhandler.cpp:337
pappso::TandemWrapperRun::run
void run(const QString &tandem_input_file, QTextStream &output_stream, QTextStream &error_stream)
run a tandem job
Definition: tandemwrapperrun.cpp:407
pappso::XtandemInputSaxHandler::getOriginalMsDataFileName
const QString & getOriginalMsDataFileName() const
Definition: xtandeminputsaxhandler.cpp:325
pappso::MzxmlOutput::maskMs1
void maskMs1(bool mask_ms1)
Definition: mzxmloutput.cpp:382
pappso::XtandemOutputSaxHandler::setInputParameters
void setInputParameters(const QString &label_name_attribute, const QString &input_value)
Definition: xtandemoutputsaxhandler.cpp:323
pappso::MzxmlOutput::close
void close()
Definition: mzxmloutput.cpp:215
pappso::TandemWrapperRun::mp_outputStream
QTextStream * mp_outputStream
Definition: tandemwrapperrun.h:126
pappso::TandemWrapperRun::convertOrginalMsData2mzXmlData
void convertOrginalMsData2mzXmlData(const QString &origin, const QString &target) const
Definition: tandemwrapperrun.cpp:353
pappso::TandemWrapperRun::wrapTandemInputFile
void wrapTandemInputFile(const QString &tandem_input_file)
Definition: tandemwrapperrun.cpp:301
pappso::XtandemPresetSaxHandler::getMs2FiltersOptions
const QString getMs2FiltersOptions() const
Definition: xtandempresetsaxhandler.cpp:262
pappso::TimsMsRunReaderMs2::setMs2FilterCstSPtr
void setMs2FilterCstSPtr(pappso::FilterInterfaceCstSPtr filter)
Definition: timsmsrunreaderms2.cpp:74
pappso::PappsoException
Definition: pappsoexception.h:42