tandemwrapperrun.cpp
Go to the documentation of this file.
/**
* \file pappsomspp/processing/tandemwrapper/tandemwrapperrun.cpp
* \date 25/01/2020
* \author Olivier Langella
* \brief actually does really run tandem directly on Bruker's data
*/
/*******************************************************************************
* Copyright (c) 2020 Olivier Langella <Olivier.Langella@u-psud.fr>.
*
* This file is part of PAPPSOms-tools.
*
* PAPPSOms-tools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PAPPSOms-tools is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PAPPSOms-tools. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "tandemwrapperrun.h"
#include <QDebug>
#include <QFileInfo>
#include <QSettings>
#include <QThread>
#include <QThreadPool>
#include "../../exception/exceptioninterrupted.h"
#include "../../msfile/msfileaccessor.h"
#include "../../msrun/private/timsmsrunreaderms2.h"
#include "../../processing/filters/filtertriangle.h"
#include "../../processing/filters/filterchargedeconvolution.h"
#include "../../msrun/output/mzxmloutput.h"
#include "wraptandemresults.h"
#include "xtandempresetreader.h"
#include "wraptandeminput.h"
namespace pappso
{
TandemWrapperRun::TandemWrapperRun(const QString &tandem_binary,
const QString &tmp_dir)
{
setTandemBinaryPath(tandem_binary);
if(!tmp_dir.isEmpty())
{
mpa_temporaryDirectory = new QTemporaryDir(tmp_dir + "/xtpwrp");
}
else
{
mpa_temporaryDirectory = new QTemporaryDir(QDir::tempPath() + "/xtpwrp");
}
mpa_temporaryDirectory->setAutoRemove(true);
if(!mpa_temporaryDirectory->isValid())
{
throw pappso::PappsoException(
QObject::tr("ERROR: unable to create temporary directory %1\n Please "
"check file system permissions")
.arg(mpa_temporaryDirectory->path()));
}
}
TandemWrapperRun::~TandemWrapperRun()
{
if(mpa_temporaryDirectory != nullptr)
{
delete mpa_temporaryDirectory;
}
if(m_xtProcess != nullptr)
{
m_xtProcess->deleteLater();
}
}
void
TandemWrapperRun::setTandemBinaryPath(const QString &tandem_binary_path)
{
m_tandemBinary = tandem_binary_path;
QSettings settings;
if(m_tandemBinary.isEmpty())
{
m_tandemBinary =
settings.value("path/tandem_binary", "/usr/bin/tandem").toString();
}
// check for tandem executable
m_tandemVersion = checkXtandemVersion(m_tandemBinary);
qDebug() << m_tandemVersion;
settings.setValue("path/tandem_binary", m_tandemBinary);
}
const QString
TandemWrapperRun::checkXtandemVersion(const QString &tandem_bin_path)
{
qDebug();
// check tandem path
QFileInfo tandem_exe(tandem_bin_path);
if(!tandem_exe.exists())
{
// dir.path() returns the unique directory path
throw pappso::PappsoException(
QObject::tr(
"X!Tandem software not found at %1.\nPlease check the X!Tandem "
"installation on your computer and set tandem.exe path.")
.arg(tandem_exe.absoluteFilePath()));
}
if(!tandem_exe.isReadable())
{
// dir.path() returns the unique directory path
throw pappso::PappsoException(
QObject::tr("Please check permissions on X!Tandem software found at %1 "
"(file not readable).")
.arg(tandem_exe.absoluteFilePath()));
}
if(!tandem_exe.isExecutable())
{
// dir.path() returns the unique directory path
throw pappso::PappsoException(
QObject::tr("Please check permissions on X!Tandem software found at %1 "
"(file not executable).")
.arg(tandem_exe.absoluteFilePath()));
}
QString version_return;
QStringList arguments;
arguments << "-v";
QProcess *xt_process = new QProcess();
// hk_process->setWorkingDirectory(QFileInfo(_hardklor_exe).absolutePath());
xt_process->start(tandem_bin_path, arguments);
if(!xt_process->waitForStarted())
{
throw pappso::PappsoException(
QObject::tr("X!Tandem %1 process failed to start")
.arg(m_tandemVersion));
}
while(xt_process->waitForReadyRead(1000))
{
}
/*
if (!xt_process->waitForFinished(_max_xt_time_ms)) {
throw pappso::PappsoException(QObject::tr("can't wait for X!Tandem process
to finish : timeout at %1").arg(_max_xt_time_ms));
}
*/
QByteArray result = xt_process->readAll();
qDebug() << result.constData();
// X! TANDEM Jackhammer TPP (2013.06.15.1 - LabKey, Insilicos, ISB)
QRegExp parse_version("(.*) TANDEM ([A-Z,a-z, ]+) \\(([^ ,^\\)]*)(.*)");
qDebug() << parse_version;
// Pattern patt = Pattern.compile("X! TANDEM [A-Z]+ \\‍((.*)\\‍)",
// Pattern.CASE_INSENSITIVE);
if(parse_version.exactMatch(result.constData()))
{
version_return = QString("X!Tandem %1 %2")
.arg(parse_version.capturedTexts()[2])
.arg(parse_version.capturedTexts()[3]); //.join(" ");
}
else
{
throw pappso::PappsoException(
QObject::tr("This executable %1 may not be a valid X!Tandem software. "
"Please check your X!Tandem installation.")
.arg(tandem_bin_path));
}
QProcess::ExitStatus Status = xt_process->exitStatus();
delete xt_process;
if(Status != 0)
{
// != QProcess::NormalExit
throw pappso::PappsoException(
QObject::tr("error executing X!Tandem Status != 0 : %1 %2\n%3")
.arg(tandem_bin_path)
.arg(arguments.join(" ").arg(result.data())));
}
qDebug();
return version_return;
}
void
TandemWrapperRun::readyReadStandardOutput()
{
QString message(m_xtProcess->readAllStandardOutput());
mp_monitor->appendText(message);
if(message.toLower().contains("error"))
{
throw pappso::XtandemError(message);
}
if(mp_monitor->shouldIstop())
{
m_xtProcess->kill();
delete m_xtProcess;
m_xtProcess = nullptr;
throw pappso::ExceptionInterrupted(
QObject::tr("X!Tandem stopped by the user"));
}
}
void
TandemWrapperRun::readyReadStandardError()
{
mp_monitor->appendText(m_xtProcess->readAllStandardError());
if(mp_monitor->shouldIstop())
{
m_xtProcess->kill();
delete m_xtProcess;
m_xtProcess = nullptr;
throw pappso::ExceptionInterrupted(
QObject::tr("X!Tandem stopped by the user"));
}
}
void
TandemWrapperRun::writeFinalTandemOutput(
const QString &tmp_tandem_output,
const QString &final_tandem_output,
const QString &original_msdata_file_name)
{
mp_monitor->setStatus(QObject::tr("Rewriting X!Tandem XML result file"));
WrapTandemResults wrap_output(final_tandem_output, original_msdata_file_name);
wrap_output.setInputParameters("spectrum, timstof MS2 filters",
getMs2FilterSuiteString());
wrap_output.setInputParameters("spectrum, mzFormat",
QString("%1").arg((int)m_mzFormat));
if(m_convertMzDataUsingSpectrumIndex)
{
wrap_output.setInputParameters("output, spectrum index", "true");
}
else
{
}
if(wrap_output.readFile(tmp_tandem_output))
{
}
else
{
throw pappso::PappsoException(
QObject::tr("Error reading %1 X!Tandem output file :\n %2")
.arg(tmp_tandem_output)
.arg(wrap_output.errorString()));
}
}
void
TandemWrapperRun::readTandemPresetFile(const QString &tandem_preset_file)
{
// get number of threads and centroid parameters from tandem preset
XtandemPresetReader preset_handler;
if(preset_handler.readFile(tandem_preset_file))
{
int ideal_number_of_thread = QThread::idealThreadCount();
int cpu_number = preset_handler.getNumberOfThreads();
qDebug() << " cpu_number=" << cpu_number;
// QThreadPool::globalInstance()->setMaxThreadCount(1);
if(cpu_number > ideal_number_of_thread)
{
cpu_number = ideal_number_of_thread;
}
else
{
if(cpu_number > 0)
{
QThreadPool::globalInstance()->setMaxThreadCount(cpu_number);
qDebug() << " maxThreadCount="
<< QThreadPool::globalInstance()->maxThreadCount();
}
}
QString ms2_filters_str = preset_handler.getMs2FiltersOptions();
if(!ms2_filters_str.isEmpty())
{
msp_ms2FilterSuiteString =
std::make_shared<pappso::FilterSuiteString>(ms2_filters_str);
}
else
{
msp_ms2FilterSuiteString =
std::make_shared<pappso::FilterSuiteString>(
"chargeDeconvolution|0.02dalton mzExclusion|0.01dalton");
}
}
else
{
throw pappso::PappsoException(
QObject::tr("Error reading %1 X!Tandem preset file :\n %2")
.arg(tandem_preset_file)
.arg(preset_handler.errorString()));
}
}
void
TandemWrapperRun::wrapTandemInputFile(const QString &tandem_input_file)
{
// read original tandem input file
// store original ms data file name
// create new mzXML data file in temporary directory
// create new tandem input file based on new mzXML file
QString mzxml_data_file_name =
mpa_temporaryDirectory->filePath("msdata.mzxml");
QString wrapped_tandem_input =
mpa_temporaryDirectory->filePath("input_tandem.xml");
QString wrapped_tandem_output =
mpa_temporaryDirectory->filePath("output_tandem.xml");
WrapTandemInput wrap_tandem_input(
mzxml_data_file_name, wrapped_tandem_input, wrapped_tandem_output);
if(wrap_tandem_input.readFile(tandem_input_file))
{
}
else
{
throw pappso::PappsoException(
QObject::tr("Error reading %1 X!Tandem input file :\n %2")
.arg(tandem_input_file)
.arg(wrap_tandem_input.errorString()));
}
/*
*
XtandemInputSaxHandler wrap_input(
mzxml_data_file_name, wrapped_tandem_input, wrapped_tandem_output);
QFile qfile(tandem_input_file);
if(!qfile.exists())
{
throw pappso::PappsoException(
QObject::tr("Tandem input file %1 does not exists")
.arg(QFileInfo(tandem_input_file).absoluteFilePath()));
}
QXmlInputSource xmlInputSource(&qfile);
QXmlSimpleReader simplereader;
simplereader.setContentHandler(&wrap_input);
simplereader.setErrorHandler(&wrap_input);
if(simplereader.parse(xmlInputSource))
{
}
else
{
throw pappso::PappsoException(
QObject::tr("Error reading %1 X!Tandem input file :\n %2")
.arg(tandem_input_file)
.arg(wrap_input.errorString()));
}
*/
// get number of threads and centroid parameters from tandem preset
readTandemPresetFile(wrap_tandem_input.getOriginalTandemPresetFileName());
// convert to mzXML
QString original_msdata_file_name =
wrap_tandem_input.getOriginalMsDataFileName();
if(convertOrginalMsData2mzXmlData(original_msdata_file_name,
mzxml_data_file_name))
{
// launch tandem
runTandem(wrapped_tandem_input);
// rewrite tandem result file
writeFinalTandemOutput(
wrapped_tandem_output,
wrap_tandem_input.getOriginalTandemOutputFileName(),
original_msdata_file_name);
}
else
{
// launch tandem on original file
runTandem(tandem_input_file);
}
}
bool
TandemWrapperRun::convertOrginalMsData2mzXmlData(const QString &origin,
const QString &target)
{
qDebug();
pappso::MsFileAccessor origin_access(origin, "runa1");
origin_access.setPreferedFileReaderType(pappso::MzFormat::brukerTims,
pappso::FileReaderType::tims_ms2);
origin_access.getMsRunIds();
m_mzFormat = origin_access.getFileFormat();
if(origin_access.getFileFormat() == pappso::MzFormat::brukerTims)
{
m_convertMzDataUsingSpectrumIndex = true;
}
if((origin_access.getFileFormat() == pappso::MzFormat::mzML) ||
(origin_access.getFileFormat() == pappso::MzFormat::brukerTims))
{
mp_monitor->setStatus(
QObject::tr("Converting %1 to mzXML %2").arg(origin).arg(target));
pappso::MsRunReaderSPtr p_reader;
p_reader =
origin_access.msRunReaderSp(origin_access.getMsRunIds().front());
pappso::TimsMsRunReaderMs2 *tims2_reader =
dynamic_cast<pappso::TimsMsRunReaderMs2 *>(p_reader.get());
if(tims2_reader != nullptr)
{
qDebug();
tims2_reader->setMs2BuiltinCentroid(true);
if(msp_ms2FilterSuiteString != nullptr)
{
tims2_reader->setMs2FilterCstSPtr(msp_ms2FilterSuiteString);
}
qDebug();
}
pappso::MzxmlOutput *p_mzxml_output;
QFile output_file(target);
// qDebug() << " TsvDirectoryWriter::writeSheet " <<
// QFileInfo(*_p_ofile).absoluteFilePath();
if(output_file.open(QIODevice::WriteOnly))
{
p_mzxml_output = new pappso::MzxmlOutput(
*mp_monitor, QTextStream(&output_file).device());
p_mzxml_output->maskMs1(true);
p_mzxml_output->setReadAhead(true);
p_mzxml_output->write(p_reader.get());
p_mzxml_output->close();
delete p_mzxml_output;
}
else
{
throw pappso::PappsoException(
QObject::tr("unable to write into %1 mzXML output file")
.arg(target));
}
qDebug();
return true;
}
else
{ // other mz data formats
return false;
}
return true;
}
void
TandemWrapperRun::run(UiMonitorInterface &monitor,
const QString &tandem_input_file)
{
mp_monitor = &monitor;
wrapTandemInputFile(tandem_input_file);
mp_monitor = nullptr;
}
void
TandemWrapperRun::runTandem(const QString &tandem_input_file)
{
if(mp_monitor->shouldIstop())
{
throw pappso::ExceptionInterrupted(
QObject::tr("X!Tandem stopped by the user processing on file %1")
.arg(tandem_input_file));
}
m_xtProcess = new QProcess();
QStringList arguments;
qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
arguments << tandem_input_file;
// hk_process->setWorkingDirectory(QFileInfo(_hardklor_exe).absolutePath());
m_xtProcess->start(m_tandemBinary, arguments);
qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
connect(m_xtProcess,
&QProcess::readyReadStandardOutput,
this,
&TandemWrapperRun::readyReadStandardOutput);
connect(m_xtProcess,
&QProcess::readyReadStandardError,
this,
&TandemWrapperRun::readyReadStandardError);
qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
mp_monitor->setStatus(QObject::tr("Running X!Tandem"));
if(!m_xtProcess->waitForStarted())
{
throw pappso::PappsoException(
QObject::tr("X!Tandem process failed to start"));
}
qDebug() << m_tandemBinary << " " << m_xtProcess->arguments();
while(m_xtProcess->waitForFinished(m_maxTandemRunTimeMs) == false)
{
//_p_monitor->appendText(xt_process->readAll().data());
// data.append(xt_process->readAll());
if(mp_monitor->shouldIstop())
{
m_xtProcess->kill();
delete m_xtProcess;
m_xtProcess = nullptr;
throw pappso::ExceptionInterrupted(
QObject::tr("X!Tandem stopped by the user processing on file %1")
.arg(tandem_input_file));
}
}
QProcess::ExitStatus Status = m_xtProcess->exitStatus();
delete m_xtProcess;
if(Status != QProcess::ExitStatus::NormalExit)
{
// != QProcess::NormalExit
throw pappso::PappsoException(
QObject::tr("error executing X!Tandem Status != 0 : %1")
.arg(m_tandemBinary));
}
m_xtProcess = nullptr;
}
QString
TandemWrapperRun::getMs2FilterSuiteString() const
{
if(msp_ms2FilterSuiteString == nullptr)
return "";
return msp_ms2FilterSuiteString.get()->toString();
}
} // namespace pappso
pappso::ExceptionInterrupted
Definition: exceptioninterrupted.h:36
pappso::MsFileAccessor
Definition: msfileaccessor.h:35
pappso::MsFileAccessor::getFileFormat
MzFormat getFileFormat() const
get the raw format of mz data
Definition: msfileaccessor.cpp:60
pappso::MsFileAccessor::msRunReaderSp
MsRunReaderSPtr msRunReaderSp(MsRunIdCstSPtr ms_run_id)
Definition: msfileaccessor.cpp:175
pappso::MsFileAccessor::setPreferedFileReaderType
void setPreferedFileReaderType(MzFormat format, FileReaderType reader_type)
given an mz format, explicitly set the prefered reader
Definition: msfileaccessor.cpp:316
pappso::MsFileAccessor::getMsRunIds
std::vector< MsRunIdCstSPtr > getMsRunIds()
Definition: msfileaccessor.cpp:67
pappso::MzxmlOutput
Definition: mzxmloutput.h:44
pappso::MzxmlOutput::setReadAhead
void setReadAhead(bool read_ahead)
Definition: mzxmloutput.cpp:93
pappso::MzxmlOutput::write
void write(MsRunReader *p_msrunreader)
Definition: mzxmloutput.cpp:98
pappso::MzxmlOutput::close
void close()
Definition: mzxmloutput.cpp:221
pappso::MzxmlOutput::maskMs1
void maskMs1(bool mask_ms1)
Definition: mzxmloutput.cpp:388
pappso::PappsoException
Definition: pappsoexception.h:42
pappso::TandemWrapperRun::mpa_temporaryDirectory
QTemporaryDir * mpa_temporaryDirectory
Definition: tandemwrapperrun.h:144
pappso::TandemWrapperRun::m_maxTandemRunTimeMs
int m_maxTandemRunTimeMs
Definition: tandemwrapperrun.h:138
pappso::TandemWrapperRun::m_mzFormat
pappso::MzFormat m_mzFormat
Definition: tandemwrapperrun.h:148
pappso::TandemWrapperRun::run
void run(UiMonitorInterface &monitor, const QString &tandem_input_file)
run a tandem job
Definition: tandemwrapperrun.cpp:491
pappso::TandemWrapperRun::m_xtProcess
QProcess * m_xtProcess
Definition: tandemwrapperrun.h:140
pappso::TandemWrapperRun::m_tandemBinary
QString m_tandemBinary
Definition: tandemwrapperrun.h:135
pappso::TandemWrapperRun::setTandemBinaryPath
void setTandemBinaryPath(const QString &tandem_binary_path)
Definition: tandemwrapperrun.cpp:86
pappso::TandemWrapperRun::readyReadStandardError
void readyReadStandardError()
Definition: tandemwrapperrun.cpp:226
pappso::TandemWrapperRun::m_convertMzDataUsingSpectrumIndex
bool m_convertMzDataUsingSpectrumIndex
Definition: tandemwrapperrun.h:146
pappso::TandemWrapperRun::mp_monitor
UiMonitorInterface * mp_monitor
Definition: tandemwrapperrun.h:134
pappso::TandemWrapperRun::m_tandemVersion
QString m_tandemVersion
Definition: tandemwrapperrun.h:136
pappso::TandemWrapperRun::readyReadStandardOutput
void readyReadStandardOutput()
Definition: tandemwrapperrun.cpp:205
pappso::TandemWrapperRun::convertOrginalMsData2mzXmlData
bool convertOrginalMsData2mzXmlData(const QString &origin, const QString &target)
Definition: tandemwrapperrun.cpp:415
pappso::TandemWrapperRun::~TandemWrapperRun
~TandemWrapperRun()
Definition: tandemwrapperrun.cpp:72
pappso::TandemWrapperRun::readTandemPresetFile
void readTandemPresetFile(const QString &tandem_preset_file)
Definition: tandemwrapperrun.cpp:275
pappso::TandemWrapperRun::msp_ms2FilterSuiteString
std::shared_ptr< FilterSuiteString > msp_ms2FilterSuiteString
Definition: tandemwrapperrun.h:142
pappso::TandemWrapperRun::wrapTandemInputFile
void wrapTandemInputFile(const QString &tandem_input_file)
Definition: tandemwrapperrun.cpp:328
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:240
pappso::TandemWrapperRun::TandemWrapperRun
TandemWrapperRun(const QString &tandem_binary, const QString &tmp_dir)
prepare a tandem run
Definition: tandemwrapperrun.cpp:48
pappso::TandemWrapperRun::getMs2FilterSuiteString
QString getMs2FilterSuiteString() const
gets the list of filters used on MS2 spectrum
Definition: tandemwrapperrun.cpp:569
pappso::TandemWrapperRun::runTandem
void runTandem(const QString &tandem_input_file)
run a tandem job
Definition: tandemwrapperrun.cpp:500
pappso::TandemWrapperRun::checkXtandemVersion
const QString checkXtandemVersion(const QString &tandem_bin_path)
Definition: tandemwrapperrun.cpp:106
pappso::TimsMsRunReaderMs2
Definition: timsmsrunreaderms2.h:41
pappso::TimsMsRunReaderMs2::setMs2FilterCstSPtr
void setMs2FilterCstSPtr(pappso::FilterInterfaceCstSPtr filter)
Definition: timsmsrunreaderms2.cpp:84
pappso::TimsMsRunReaderMs2::setMs2BuiltinCentroid
void setMs2BuiltinCentroid(bool centroid)
enable or disable simple centroid filter on raw tims data for MS2
Definition: timsmsrunreaderms2.cpp:68
pappso::UiMonitorInterface
Definition: uimonitorinterface.h:50
pappso::UiMonitorInterface::setStatus
virtual void setStatus(const QString &status)=0
current status of the process
pappso::UiMonitorInterface::appendText
virtual void appendText(const QString &text)=0
append a text to a long report
pappso::UiMonitorInterface::shouldIstop
virtual bool shouldIstop()=0
should the procces be stopped ? If true, then cancel process Use this function at strategic point of ...
pappso::WrapTandemInput
Definition: wraptandeminput.h:43
pappso::WrapTandemInput::getOriginalTandemOutputFileName
const QString & getOriginalTandemOutputFileName() const
Definition: wraptandeminput.cpp:149
pappso::WrapTandemInput::getOriginalTandemPresetFileName
const QString & getOriginalTandemPresetFileName() const
Definition: wraptandeminput.cpp:155
pappso::WrapTandemInput::getOriginalMsDataFileName
const QString & getOriginalMsDataFileName() const
Definition: wraptandeminput.cpp:143
pappso::WrapTandemResults
Definition: wraptandemresults.h:43
pappso::WrapTandemResults::setInputParameters
void setInputParameters(const QString &label_name_attribute, const QString &input_value)
Definition: wraptandemresults.cpp:59
pappso::XmlStreamReaderInterface::errorString
QString errorString() const
Definition: xmlstreamreaderinterface.cpp:46
pappso::XmlStreamReaderInterface::readFile
virtual bool readFile(const QString &fileName)
Definition: xmlstreamreaderinterface.cpp:61
pappso::XtandemError
Definition: tandemwrapperrun.h:48
pappso::XtandemPresetReader
Definition: xtandempresetreader.h:40
pappso::XtandemPresetReader::getMs2FiltersOptions
const QString getMs2FiltersOptions() const
Definition: xtandempresetreader.cpp:110
pappso::XtandemPresetReader::getNumberOfThreads
int getNumberOfThreads() const
Definition: xtandempresetreader.cpp:103
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:184
pappso::MzFormat::brukerTims
@ brukerTims
pappso::MzFormat::mzML
@ mzML
mzML
pappso::FileReaderType::tims_ms2
@ tims_ms2
tandemwrapperrun.h
actually does really run tandem directly on Bruker's data
wraptandeminput.h
rewrites tandem xml input file with temporary files
wraptandemresults.h
rewrites tandem xml output file with temporary files
xtandempresetreader.h
read tandem preset file to get centroid parameters and number of threads