diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d83c28381795063e2aaf2c1413a7bf8b640d8bf..150a5ff3cc0d897026c2f2ccb048ca245c3e04b0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -71,6 +71,7 @@ SET(CPP_FILES gui/peptide_detail_view/spectrum_widget/spectrumpainter.cpp input/xpipsaxhandler.cpp input/xtandemsaxhandler.cpp + output/masschroqml.cpp utils/identificationdatasourcestore.cpp utils/groupstore.cpp utils/msrunstore.cpp diff --git a/src/core/msrun.cpp b/src/core/msrun.cpp index f5685957b9625809884c9781f20e25d781a8f34f..38e7c45412eff029c20ef1eb67da290ffc4bfe20 100644 --- a/src/core/msrun.cpp +++ b/src/core/msrun.cpp @@ -61,3 +61,7 @@ const QString & MsRun::getXmlId() const { const QString & MsRun::getFilename() const { return _location; } + +MzFormat MsRun::getMzFormat() const { + return _mz_format; +} diff --git a/src/core/msrun.h b/src/core/msrun.h index 5262b2bead094bfff276405ce12ac683491334eb..40604c926839d3297300452b3b05cabfee134014 100644 --- a/src/core/msrun.h +++ b/src/core/msrun.h @@ -34,6 +34,7 @@ #include <memory> #include <QString> +#include "../utils/types.h" class MsRun; typedef std::shared_ptr<MsRun> MsRunSp; @@ -50,10 +51,13 @@ public: const QString & getFilename() const; const QString & getXmlId() const; + + MzFormat getMzFormat() const; private : QString _xml_id; QString _location; QString _name; + MzFormat _mz_format=MzFormat::mzXML; }; #endif // MSRUN_H diff --git a/src/core/project.cpp b/src/core/project.cpp index 210b0e11c5c8f96a2bb61ee06ea109d0884c3276..0437c22e6ddcedb7006334894d7f776bccc7f511 100644 --- a/src/core/project.cpp +++ b/src/core/project.cpp @@ -122,12 +122,6 @@ void Project::readXpipFile(QFileInfo xpip_fileinfo) { } -IdentificationGroup* Project::getCurrentIdentificationGroupP() const { - - qDebug() << "Project::getCurrentIdentificationGroupP begin " << _p_current_identification_group; - return _p_current_identification_group; -} - void Project::startGrouping() { for (auto & p_id_group : _identification_goup_list) { diff --git a/src/core/project.h b/src/core/project.h index 3d04785b86604291452b4cc7f2594550feff9e7a..cbf721250a1cde53cc6ee525f730cebf96057a72 100644 --- a/src/core/project.h +++ b/src/core/project.h @@ -51,7 +51,6 @@ public: IdentificationDataSourceStore & getIdentificationDataSourceStore(); void readXpipFile(QFileInfo xpip_source); IdentificationGroup* newIdentificationGroup(); - IdentificationGroup* getCurrentIdentificationGroupP() const; /** @brief validate or invalidate peptides and proteins based automatic filters and manual checks * */ diff --git a/src/gui/main.ui b/src/gui/main.ui index 8c36b0b947867c06150e1f9cff2893583573db34..4fd14c2e2d57770d32a465baba4cf79719a082c9 100644 --- a/src/gui/main.ui +++ b/src/gui/main.ui @@ -26,15 +26,25 @@ <x>0</x> <y>0</y> <width>463</width> - <height>23</height> + <height>25</height> </rect> </property> <widget class="QMenu" name="menuFile"> <property name="title"> <string>F&ile</string> </property> + <widget class="QMenu" name="menuExport_files"> + <property name="title"> + <string>Export files</string> + </property> + <addaction name="actionFasta"/> + <addaction name="actionMassChroQ"/> + <addaction name="actionSpreadsheet"/> + </widget> <addaction name="actionLoad_results"/> <addaction name="actionLoad"/> + <addaction name="separator"/> + <addaction name="menuExport_files"/> </widget> <addaction name="menuFile"/> </widget> @@ -46,7 +56,22 @@ </action> <action name="actionLoad_results"> <property name="text"> - <string>Load results</string> + <string>Load &results</string> + </property> + </action> + <action name="actionFasta"> + <property name="text"> + <string>Fasta</string> + </property> + </action> + <action name="actionMassChroQ"> + <property name="text"> + <string>MassChroQ</string> + </property> + </action> + <action name="actionSpreadsheet"> + <property name="text"> + <string>Spreadsheet</string> </property> </action> </widget> @@ -86,9 +111,26 @@ </hint> </hints> </connection> + <connection> + <sender>actionMassChroQ</sender> + <signal>triggered()</signal> + <receiver>Main</receiver> + <slot>doActionMassChroQ()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>231</x> + <y>191</y> + </hint> + </hints> + </connection> </connections> <slots> <slot>selectXpipFile()</slot> <slot>loadResults()</slot> + <slot>doActionMassChroQ()</slot> </slots> </ui> diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 023c091235555831bfea48cd45cff6bb19741704..d4a10d9324fae909decbe0edafc4352563dc20d3 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -30,6 +30,7 @@ #include "ui_main.h" #include <pappsomspp/pappsoexception.h> +#include "../output/masschroqml.h" void XtpLoaderThread::doXpipFileLoad(QString filename) { @@ -37,7 +38,7 @@ void XtpLoaderThread::doXpipFileLoad(QString filename) { try { QFileInfo new_xpip_file; new_xpip_file.setFile(filename); - + emit loadingMessage(tr("loading XPIP file")); XpipFile xpip_file(new_xpip_file); ProjectSp project_sp = xpip_file.getProjectSp(); @@ -175,8 +176,10 @@ void MainWindow::doProjectReady(ProjectSp project_sp) { qDebug() << "MainWindow::doProjectReady begin"; try { + _project_sp = project_sp; doDisplayLoadingMessage(tr("grouping proteins")); project_sp.get()->startGrouping(); + doDisplayLoadingMessage(tr("grouping proteins finished")); } catch (pappso::PappsoException & error) { viewError(tr("Error while grouping :\n%1").arg(error.qwhat())); @@ -219,3 +222,27 @@ void MainWindow::selectXpipFile() { } +void MainWindow::doActionMassChroQ() { + qDebug() << "MainWindow::doActionMassChroQ begin";try { + QSettings settings; + QString default_location = settings.value("path/mcqfile", "").toString(); + + QString filename = QFileDialog::getSaveFileName(this, tr("Save MassChroqML file"), + QString("%1/untitled.masschroqml").arg(default_location), + tr("MassChroqML (*.masschroqml)")); + + if (filename.isEmpty()) { + return; + } + + settings.setValue("path/mcqfile", QFileInfo(filename).absolutePath()); + MassChroQml output(filename); + output.write(_project_sp); + output.close(); + //emit operateXpipFile(filename); + } + catch (pappso::PappsoException & error) { + viewError(tr("Error while writing MassChroqML file :\n%1").arg(error.qwhat())); + } + qDebug() << "MainWindow::doActionMassChroQ end"; +} diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 43946b49ae262f35426e49c8afff5cb425080b3e..02eb1617a3f571ce551a56ea1d0d426e3a88218e 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -78,6 +78,7 @@ public: public slots: void loadResults(); void selectXpipFile(); + void doActionMassChroQ(); void doDisplayLoadingMessage(QString message); void doProjectReady(ProjectSp project_sp); void doProjectNotReady(QString error); diff --git a/src/output/masschroqml.cpp b/src/output/masschroqml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4492759bbc8cd413e88dcd1fb86c8b4ef1647dc --- /dev/null +++ b/src/output/masschroqml.cpp @@ -0,0 +1,188 @@ +/** + * \file output/masschroqml.cpp + * \date 7/4/2017 + * \author Olivier Langella + * \brief MassChroQML writer + */ + +/******************************************************************************* +* Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.fr>. +* +* This file is part of XTPcpp. +* +* XTPcpp 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. +* +* XTPcpp 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 XTPcpp. If not, see <http://www.gnu.org/licenses/>. +* +* Contributors: +* Olivier Langella <olivier.langella@u-psud.fr> - initial API and implementation +******************************************************************************/ + +#include "masschroqml.h" +#include <pappsomspp/pappsoexception.h> +#include <pappsomspp/utils.h> +#include <pappsomspp/grouping/grpprotein.h> + +MassChroQml::MassChroQml(const QString & out_filename) +{ + //_p_digestion_pipeline = p_digestion_pipeline; + + //_mzidentml = "http://psidev.info/psi/pi/mzIdentML/1.1"; + QString complete_out_filename = out_filename; + _output_file = new QFile(complete_out_filename); + + if (_output_file->open(QIODevice::WriteOnly)) + { + _output_stream = new QXmlStreamWriter(); + _output_stream->setDevice(_output_file); + } else + { + throw pappso::PappsoException(QObject::tr("error : cannot open the MassChroqML output file : %1\n").arg(out_filename)); + } + + _output_stream->setAutoFormatting(true); + _output_stream->writeStartDocument("1.0"); + + +} + +MassChroQml::~MassChroQml() +{ + delete _output_file; + delete _output_stream; +} + +void MassChroQml::close() { + _output_stream->writeEndDocument(); + _output_file->close(); +} + +void MassChroQml::write(ProjectSp sp_project) { + + _sp_project = sp_project; + if (_sp_project.get() == nullptr) { + throw pappso::PappsoException(QObject::tr("Error writing MassChroqML file :\n project is empty")); + } + + //<masschroq> + _output_stream->writeStartElement("masschroq"); + _output_stream->writeAttribute("type","input"); + _output_stream->writeAttribute("version","2.2"); + //_output_stream->writeAttribute("creationDate", QDateTime::currentDateTime().toString( Qt::ISODate)); + _output_stream->writeNamespace("http://www.w3.org/2001/XMLSchema-instance","xsi"); + //_output_stream->writeNamespace("http://www.w3.org/2001/XMLSchema-instance","xsi"); + _output_stream->writeAttribute("xmlns","http://pappso.inra.fr/xsd/masschroqml/2.2"); + //xsi:schemaLocation="http://psidev.info/psi/pi/mzIdentML/1.1 http://www.psidev.info/files/mzIdentML1.1.0.xsd" + _output_stream->writeAttribute("http://www.w3.org/2001/XMLSchema-instance","schemaLocation","http://pappso.inra.fr/xsd/masschroqml/2.2 http://pappso.inra.fr/xsd/masschroq-2.2.xsd"); + + // <rawdata><!-- time_values_dir="directory" to read retention time corrections--> + _output_stream->writeStartElement("rawdata"); + _output_stream->writeComment("time_values_dir=\"directory\" to read retention time corrections"); + + std::vector<MsRunSp> msrun_list = _sp_project.get()->getMsRunStore().getMsRunList(); + for (MsRunSp & msrun : msrun_list) { + + //<data_file id="samp0" format="mzxml" path="bsa1.mzXML" type="centroid" /> + _output_stream->writeStartElement("data_file"); + _output_stream->writeAttribute("id",msrun.get()->getXmlId()); + if(msrun.get()->getMzFormat() == MzFormat::mzXML) { + _output_stream->writeAttribute("format","mzxml"); + } + _output_stream->writeAttribute("path",msrun.get()->getFilename()); + _output_stream->writeAttribute("type","centroid"); + // <data_file id="samp1" format="mzxml" path="bsa2.mzXML" type="profile" /> + _output_stream->writeEndElement(); + } + // <data_file id="samp2" format="mzml" path="/home/user/bsa3.mzml" type="profile" /> +//<data_file id="samp3" format="mzml" path="/home/user/bsa4.mzml" type="profile" /> + // _output_stream.writeEndElement(); + // </rawdata> + _output_stream->writeEndElement(); + + + writeGroups(); + writeProteinList(); + writePeptideList(); +} +void MassChroQml::writePeptideList() { +//<peptide_list> + _output_stream->writeStartElement("peptide_list"); + /* + <peptide id="pep0" mh="1463.626" mods="114.08" prot_ids="P1.1" + seq="TCVADESHAGCEK"> + <modifications><!-- this tag is optional but gives an exact mass computation --> + <psimod at="2" acc="MOD:00397"></psimod> + <psimod at="11" acc="MOD:00397"></psimod> + </modifications> + <observed_in data="samp0" scan="655" z="2" /> + <observed_in data="samp1" scan="798" z="2" /> + </peptide> + <peptide id="pep1" mh="1103.461" mods="57.04" prot_ids="P1.1" + seq="ADESHAGCEK"> + <modifications><!-- this tag is optional but gives an exact mass computation --> + <psimod at="8" acc="MOD:00397"></psimod> + </modifications> + <observed_in data="samp3" scan="663" z="2" /> + </peptide>*/ + //</peptide_list> + _output_stream->writeEndElement(); +} + +void MassChroQml::writeGroups() { +//<groups> + _output_stream->writeStartElement("groups"); + //<group data_ids="samp0 samp1" id="G1" /> + _output_stream->writeStartElement("group"); + _output_stream->writeAttribute("id",QString("fractiona1")); + std::vector<MsRunSp> msrun_list = _sp_project.get()->getMsRunStore().getMsRunList(); + QStringList list; + for (MsRunSp & msrun : msrun_list) { + list << msrun.get()->getXmlId(); + } + _output_stream->writeAttribute("data_ids",list.join(" ")); + _output_stream->writeEndElement(); + //<group data_ids="samp2 samp3" id="G2" /> +// </groups> + _output_stream->writeEndElement(); +} + +void MassChroQml::writeProteinList() { +//<protein_list> + _output_stream->writeStartElement("protein_list"); + std::vector<IdentificationGroup *> identification_list = _sp_project.get()->getIdentificationGroupList(); + if (identification_list.size() == 0) { + throw pappso::PappsoException(QObject::tr("Error writing MassChroqML file :\n no protein list")); + } + if (identification_list.size() > 1) { + throw pappso::PappsoException(QObject::tr("Error writing MassChroqML file :\n only available in combine mode")); + } + _p_identification_group = identification_list[0]; + for (ProteinMatch * p_protein_match :_p_identification_group->getProteinMatchList()) { + if (!p_protein_match->isGrouped()) continue; + //<protein desc="conta|P02769|ALBU_BOVIN SERUM ALBUMIN PRECURSOR." + // id="P1.1" /> + pappso::GrpProteinSp grp_protein = p_protein_match->getGrpProteinSp(); + if (grp_protein.get()->getRank() == 1) { + _output_stream->writeStartElement("protein"); + _output_stream->writeAttribute("id",grp_protein.get()->getGroupingId()); + QStringList list; + list << p_protein_match->getProteinXtpSp().get()->getAccession(); + list << p_protein_match->getProteinXtpSp().get()->getDescription(); + _output_stream->writeAttribute("desc",list.join(" ")); + //<protein desc="conta|P02770|ALBU_RAT SERUM ALBUMIN PRECURSOR." + // id="P1.2" /> + _output_stream->writeEndElement(); + } + } + //</protein_list> + _output_stream->writeEndElement(); +} diff --git a/src/output/masschroqml.h b/src/output/masschroqml.h new file mode 100644 index 0000000000000000000000000000000000000000..47559be08346f242c118f6b399bd9742599a297b --- /dev/null +++ b/src/output/masschroqml.h @@ -0,0 +1,57 @@ +/** + * \file output/masschroqml.h + * \date 7/4/2017 + * \author Olivier Langella + * \brief MassChroQML writer + */ + +/******************************************************************************* +* Copyright (c) 2017 Olivier Langella <olivier.langella@u-psud.fr>. +* +* This file is part of XTPcpp. +* +* XTPcpp 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. +* +* XTPcpp 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 XTPcpp. If not, see <http://www.gnu.org/licenses/>. +* +* Contributors: +* Olivier Langella <olivier.langella@u-psud.fr> - initial API and implementation +******************************************************************************/ + +#ifndef MASSCHROQML_H +#define MASSCHROQML_H + +#include <QXmlStreamWriter> +#include <QFile> +#include <QString> +#include "../core/project.h" + +class MassChroQml +{ + public: + MassChroQml(const QString & out_filename); + ~MassChroQml(); + + void write(ProjectSp sp_project); + void close(); +private: + void writeGroups(); + void writeProteinList(); + void writePeptideList(); +private : + QFile * _output_file; + QXmlStreamWriter * _output_stream; + ProjectSp _sp_project; + IdentificationGroup * _p_identification_group; +}; + +#endif // MASSCHROQML_H diff --git a/src/utils/msrunstore.cpp b/src/utils/msrunstore.cpp index 1fee9ca9e8418400fe66135d1d8e8a0e353729f5..ee6c13061885896b559066d3e86a9f1f70321062 100644 --- a/src/utils/msrunstore.cpp +++ b/src/utils/msrunstore.cpp @@ -30,6 +30,7 @@ #include "msrunstore.h" #include <pappsomspp/exception/exceptionnotfound.h> +#include <pappsomspp/utils.h> MsRunStore::MsRunStore() { @@ -49,9 +50,19 @@ MsRunSp MsRunStore::getInstance(const QString & location) { } else { MsRunSp p_xtfile = std::make_shared<MsRun>(location); + p_xtfile.get()->setXmlId(QString("samp%1").arg(pappso::Utils::getLexicalOrderedString(_map_msrun.size()))); _map_msrun.insert(std::pair< QString, MsRunSp >(location, p_xtfile)); return p_xtfile; } throw pappso::ExceptionNotFound(QObject::tr("Ms resource %1 not found").arg(location)); } + + +std::vector<MsRunSp> MsRunStore::getMsRunList() const { + std::vector<MsRunSp> msrun_list; + for (auto & msrun_pair :_map_msrun) { + msrun_list.push_back(msrun_pair.second); + } + return msrun_list; +} diff --git a/src/utils/msrunstore.h b/src/utils/msrunstore.h index 27e6df6f26cc0bd37c3d5ecee7b294223af9f036..0741d45a7777a547b31f1de3683870b4247aa3c1 100644 --- a/src/utils/msrunstore.h +++ b/src/utils/msrunstore.h @@ -33,6 +33,7 @@ #include <QString> #include <map> +#include <vector> #include "../core/msrun.h" class MsRunStore @@ -42,6 +43,8 @@ public: ~MsRunStore(); MsRunSp getInstance(const QString & location); + + std::vector<MsRunSp> getMsRunList() const; private: std::map<QString, MsRunSp> _map_msrun; }; diff --git a/src/utils/types.h b/src/utils/types.h index 3bf0931e26f444e13db4fe087d87c5e9ae4face8..7a5be71be3a1735e6984713699b0ef4356a741de 100644 --- a/src/utils/types.h +++ b/src/utils/types.h @@ -37,6 +37,15 @@ enum class GroupingType { }; +/** \def MzFormat mz data file format types + * + */ + +enum class MzFormat { + mzML, ///< mzML + mzXML, ///< mzXML +}; + /** \def ProteinListColumn list of available fields to display in protein list * */