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(false);
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  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  else
284  {
286  QObject::tr("Error reading %1 X!Tandem preset file :\n %2")
287  .arg(tandem_preset_file)
288  .arg(preset_handler.errorString()));
289  }
290 }
291 
292 
293 void
294 TandemWrapperRun::wrapTandemInputFile(const QString &tandem_input_file)
295 {
296  // read original tandem input file
297  // store original ms data file name
298  // create new mzXML data file in temporary directory
299  // create new tandem input file based on new mzXML file
300  QString mzxml_data_file_name =
301  mpa_temporaryDirectory->filePath("msdata.mzxml");
302  QString wrapped_tandem_input =
303  mpa_temporaryDirectory->filePath("input_tandem.xml");
304  QString wrapped_tandem_output =
305  mpa_temporaryDirectory->filePath("output_tandem.xml");
306  XtandemInputSaxHandler wrap_input(
307  mzxml_data_file_name, wrapped_tandem_input, wrapped_tandem_output);
308 
309  QFile qfile(tandem_input_file);
310  QXmlInputSource xmlInputSource(&qfile);
311  QXmlSimpleReader simplereader;
312  simplereader.setContentHandler(&wrap_input);
313  simplereader.setErrorHandler(&wrap_input);
314 
315  if(simplereader.parse(xmlInputSource))
316  {
317  }
318  else
319  {
321  QObject::tr("Error reading %1 X!Tandem input file :\n %2")
322  .arg(tandem_input_file)
323  .arg(wrap_input.errorString()));
324  }
325 
326  // get number of threads and centroid parameters from tandem preset
328 
329 
330  // convert to mzXML
331  QString original_msdata_file_name = wrap_input.getOriginalMsDataFileName();
332  qDebug() << "DDDDDDDDDDD" << original_msdata_file_name
333  << wrap_input.getOriginalTandemOutputFileName();
334  convertOrginalMsData2mzXmlData(original_msdata_file_name,
335  mzxml_data_file_name);
336 
337 
338  // launch tandem
339  runTandem(wrapped_tandem_input);
340 
341  // rewrite tandem result file
342  writeFinalTandemOutput(wrapped_tandem_output,
343  wrap_input.getOriginalTandemOutputFileName(),
344  original_msdata_file_name);
345 }
346 
347 void
349  const QString &target) const
350 {
351  qDebug();
352  pappso::MsFileAccessor origin_access(origin, "runa1");
353  origin_access.setPreferedFileReaderType(pappso::MzFormat::brukerTims,
355  origin_access.getMsRunIds();
356 
357  pappso::MsRunReaderSPtr p_reader;
358  p_reader = origin_access.msRunReaderSp(origin_access.getMsRunIds().front());
359 
360  pappso::TimsMsRunReaderMs2 *tims2_reader =
361  dynamic_cast<pappso::TimsMsRunReaderMs2 *>(p_reader.get());
362  if(tims2_reader != nullptr)
363  {
364  qDebug();
365 
366  if(msp_ms2FilterSuite != nullptr)
367  {
369  }
370  else
371  {
372  std::shared_ptr<FilterSuite> ms2filter =
373  std::make_shared<FilterSuite>();
374 
375  ms2filter.get()->push_back(
376  std::make_shared<FilterChargeDeconvolution>(
378 
379  tims2_reader->setMs2FilterCstSPtr(ms2filter);
380  }
381  qDebug();
382  }
383 
384 
385  pappso::MzxmlOutput *p_mzxml_output;
386  QFile output_file(target);
387  // qDebug() << " TsvDirectoryWriter::writeSheet " <<
388  // QFileInfo(*_p_ofile).absoluteFilePath();
389  if(output_file.open(QIODevice::WriteOnly))
390  {
391  p_mzxml_output =
392  new pappso::MzxmlOutput(QTextStream(&output_file).device());
393 
394  p_mzxml_output->maskMs1(true);
395 
396  p_mzxml_output->setReadAhead(true);
397 
398  p_mzxml_output->write(p_reader.get());
399 
400  p_mzxml_output->close();
401  }
402  else
403  {
405  tr("unable to write into %1 mzXML output file").arg(target));
406  }
407 
408  qDebug();
409 }
410 
411 void
412 TandemWrapperRun::run(const QString &tandem_input_file,
413  QTextStream &output_stream,
414  QTextStream &error_stream)
415 {
416  mp_outputStream = &output_stream;
417  mp_errorStream = &error_stream;
418 
419  wrapTandemInputFile(tandem_input_file);
420  mp_outputStream = nullptr;
421  mp_errorStream = nullptr;
422 }
423 void
424 TandemWrapperRun::runTandem(const QString &tandem_input_file)
425 {
426 
427  m_xtProcess = new QProcess();
428  QStringList arguments;
429 
430  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
431 
432  arguments << tandem_input_file;
433  // hk_process->setWorkingDirectory(QFileInfo(_hardklor_exe).absolutePath());
434  m_xtProcess->start(m_tandemBinary, arguments);
435 
436  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
437 
438  connect(m_xtProcess,
439  &QProcess::readyReadStandardOutput,
440  this,
442  connect(m_xtProcess,
443  &QProcess::readyReadStandardError,
444  this,
446 
447 
448  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
449 
450  if(!m_xtProcess->waitForStarted())
451  {
453  QObject::tr("X!Tandem process failed to start"));
454  }
455 
456  qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
457 
458  while(m_xtProcess->waitForFinished(m_maxTandemRunTimeMs))
459  {
460  //_p_monitor->appendText(xt_process->readAll().data());
461  // data.append(xt_process->readAll());
462  if(shouldIstop())
463  {
464  m_xtProcess->kill();
465  delete m_xtProcess;
467  QObject::tr("X!Tandem stopped by the user processing on file %1")
468  .arg(tandem_input_file));
469  }
470  }
471 
472  QProcess::ExitStatus Status = m_xtProcess->exitStatus();
473 
474  delete m_xtProcess;
475  if(Status != 0)
476  {
477  // != QProcess::NormalExit
479  QObject::tr("error executing X!Tandem Status != 0 : %1")
480  .arg(m_tandemBinary));
481  }
482  m_xtProcess = nullptr;
483 }
484 
485 void
487  const std::shared_ptr<FilterSuite> ms2filter)
488 {
489  msp_ms2FilterSuite = ms2filter;
490 }
491 
492 std::shared_ptr<FilterSuite>
494 {
495  return msp_ms2FilterSuite;
496 }
497 
498 } // 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::XtandemPresetSaxHandler
Definition: xtandempresetsaxhandler.h:40
xtandempresetsaxhandler.h
read tandem preset file to get centroid parameters and number of threads
pappso::TandemWrapperRun::setMs2FilterSuite
void setMs2FilterSuite(const std::shared_ptr< FilterSuite > ms2filter)
sets optional filters to use on MS2 spectrum
Definition: tandemwrapperrun.cpp:486
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: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:424
pappso::MsFileAccessor
Definition: msfileaccessor.h:35
pappso::PrecisionFactory::getDaltonInstance
static PrecisionPtr getDaltonInstance(pappso_double value)
Definition: precision.cpp:129
pappso::TandemWrapperRun::mp_errorStream
QTextStream * mp_errorStream
Definition: tandemwrapperrun.h:126
pappso::TandemWrapperRun::mpa_temporaryDirectory
QTemporaryDir * mpa_temporaryDirectory
Definition: tandemwrapperrun.h:128
pappso::TandemWrapperRun::readyReadStandardError
void readyReadStandardError()
Definition: tandemwrapperrun.cpp:214
pappso::TandemWrapperRun::m_xtProcess
QProcess * m_xtProcess
Definition: tandemwrapperrun.h:120
pappso::TandemWrapperRun::msp_ms2FilterSuite
std::shared_ptr< FilterSuite > msp_ms2FilterSuite
Definition: tandemwrapperrun.h:122
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:249
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:412
pappso::XtandemInputSaxHandler::getOriginalMsDataFileName
const QString & getOriginalMsDataFileName() const
Definition: xtandeminputsaxhandler.cpp:325
pappso::MzxmlOutput::maskMs1
void maskMs1(bool mask_ms1)
Definition: mzxmloutput.cpp:382
pappso::MzxmlOutput::close
void close()
Definition: mzxmloutput.cpp:215
pappso::TandemWrapperRun::mp_outputStream
QTextStream * mp_outputStream
Definition: tandemwrapperrun.h:125
pappso::TandemWrapperRun::convertOrginalMsData2mzXmlData
void convertOrginalMsData2mzXmlData(const QString &origin, const QString &target) const
Definition: tandemwrapperrun.cpp:348
pappso::TandemWrapperRun::wrapTandemInputFile
void wrapTandemInputFile(const QString &tandem_input_file)
Definition: tandemwrapperrun.cpp:294
pappso::TandemWrapperRun::getMs2FilterSuite
std::shared_ptr< FilterSuite > getMs2FilterSuite() const
gets the list of filters used on MS2 spectrum
Definition: tandemwrapperrun.cpp:493
pappso::TimsMsRunReaderMs2::setMs2FilterCstSPtr
void setMs2FilterCstSPtr(pappso::FilterInterfaceCstSPtr filter)
Definition: timsmsrunreaderms2.cpp:74
pappso::PappsoException
Definition: pappsoexception.h:42