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  convertOrginalMsData2mzXmlData(original_msdata_file_name,
338  mzxml_data_file_name);
339 
340 
341  // launch tandem
342  runTandem(wrapped_tandem_input);
343 
344  // rewrite tandem result file
345  writeFinalTandemOutput(wrapped_tandem_output,
346  wrap_input.getOriginalTandemOutputFileName(),
347  original_msdata_file_name);
348 }
349 
350 void
352  const QString &target) const
353 {
354  qDebug();
355  pappso::MsFileAccessor origin_access(origin, "runa1");
356  origin_access.setPreferedFileReaderType(pappso::MzFormat::brukerTims,
358  origin_access.getMsRunIds();
359 
360  pappso::MsRunReaderSPtr p_reader;
361  p_reader = origin_access.msRunReaderSp(origin_access.getMsRunIds().front());
362  // if(!m_centroidOptions.isEmpty())
363  // {
364  pappso::TimsMsRunReaderMs2 *tims2_reader =
365  dynamic_cast<pappso::TimsMsRunReaderMs2 *>(p_reader.get());
366  if(tims2_reader != nullptr)
367  {
368  qDebug();
369 
370  QStringList option_list = m_centroidOptions.split(" ");
371  std::shared_ptr<pappso::FilterPseudoCentroid> ms2filter =
372  std::make_shared<pappso::FilterPseudoCentroid>(
373  option_list.at(0).toDouble(),
374  option_list.at(1).toDouble(),
375  option_list.at(2).toDouble(),
376  option_list.at(3).toDouble());
377 
378 
379  /*
380  std::shared_ptr<pappso::FilterTriangle> ms2filter =
381  std::make_shared<pappso::FilterTriangle>();
382  ms2filter.get()->setTriangleSlope(50, 0.02);
383  */
384 
385  tims2_reader->setMs2FilterCstSPtr(ms2filter);
386 
387  qDebug();
388  }
389  // }
390 
391 
392  pappso::MzxmlOutput *p_mzxml_output;
393  QFile output_file(target);
394  // qDebug() << " TsvDirectoryWriter::writeSheet " <<
395  // QFileInfo(*_p_ofile).absoluteFilePath();
396  if(output_file.open(QIODevice::WriteOnly))
397  {
398  p_mzxml_output =
399  new pappso::MzxmlOutput(QTextStream(&output_file).device());
400 
401  p_mzxml_output->maskMs1(true);
402 
403  p_mzxml_output->setReadAhead(true);
404 
405  p_mzxml_output->write(p_reader.get());
406 
407  p_mzxml_output->close();
408  }
409  else
410  {
412  tr("unable to write into %1 mzXML output file").arg(target));
413  }
414 
415  qDebug();
416 }
417 
418 void
419 TandemWrapperRun::run(const QString &tandem_input_file,
420  QTextStream &output_stream,
421  QTextStream &error_stream)
422 {
423  mp_outputStream = &output_stream;
424  mp_errorStream = &error_stream;
425 
426  wrapTandemInputFile(tandem_input_file);
427  mp_outputStream = nullptr;
428  mp_errorStream = nullptr;
429 }
430 
431 void
432 TandemWrapperRun::runTandem(const QString &tandem_input_file)
433 {
434 
435  m_xtProcess = new QProcess();
436  QStringList arguments;
437 
438  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
439 
440  arguments << tandem_input_file;
441  // hk_process->setWorkingDirectory(QFileInfo(_hardklor_exe).absolutePath());
442  m_xtProcess->start(m_tandemBinary, arguments);
443 
444  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
445 
446  connect(m_xtProcess,
447  &QProcess::readyReadStandardOutput,
448  this,
450  connect(m_xtProcess,
451  &QProcess::readyReadStandardError,
452  this,
454 
455 
456  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
457 
458  if(!m_xtProcess->waitForStarted())
459  {
461  QObject::tr("X!Tandem process failed to start"));
462  }
463 
464  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
465 
466  while(m_xtProcess->waitForFinished(m_maxTandemRunTimeMs))
467  {
468  //_p_monitor->appendText(xt_process->readAll().data());
469  // data.append(xt_process->readAll());
470  if(shouldIstop())
471  {
472  m_xtProcess->kill();
473  delete m_xtProcess;
475  QObject::tr("X!Tandem stopped by the user processing on file %1")
476  .arg(tandem_input_file));
477  }
478  }
479 
480  QProcess::ExitStatus Status = m_xtProcess->exitStatus();
481 
482  delete m_xtProcess;
483  if(Status != 0)
484  {
485  // != QProcess::NormalExit
487  QObject::tr("error executing X!Tandem Status != 0 : %1")
488  .arg(m_tandemBinary));
489  }
490  m_xtProcess = nullptr;
491 }
492 } // namespace pappso
pappso::TandemWrapperRun::shouldIstop
bool shouldIstop()
Definition: tandemwrapperrun.cpp:197
pappso::XtandemInputSaxHandler::errorString
QString errorString() const
Definition: xtandeminputsaxhandler.cpp:258
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:252
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:432
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:324
pappso::MsFileAccessor::msRunReaderSp
MsRunReaderSPtr msRunReaderSp(MsRunIdCstSPtr ms_run_id)
Definition: msfileaccessor.cpp:175
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:330
pappso::TandemWrapperRun::run
void run(const QString &tandem_input_file, QTextStream &output_stream, QTextStream &error_stream)
run a tandem job
Definition: tandemwrapperrun.cpp:419
pappso::XtandemInputSaxHandler::getOriginalMsDataFileName
const QString & getOriginalMsDataFileName() const
Definition: xtandeminputsaxhandler.cpp:318
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:321
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:351
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