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