From 17adc62be0a446237436860527f487867dc1727b Mon Sep 17 00:00:00 2001
From: Olivier Langella <olivier.langella@u-psud.fr>
Date: Thu, 26 Oct 2017 17:16:13 +0200
Subject: [PATCH] building new xpip file

---
 src/CMakeLists.txt                            |   5 +-
 .../identificationdatasource.cpp              |   7 +
 .../identificationdatasource.h                |   5 +
 src/core/msrun.cpp                            |   5 +
 src/core/msrun.h                              |   4 +
 src/gui/main.ui                               |  23 +++
 src/gui/mainwindow.cpp                        |  43 ++++-
 src/gui/mainwindow.h                          |   1 +
 src/output/xpip.cpp                           | 150 +++++++++++++-----
 src/output/xpip.h                             |  14 +-
 src/utils/identificationdatasourcestore.cpp   |   2 +
 src/utils/types.h                             |  20 +--
 12 files changed, 222 insertions(+), 57 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4db3e0c0..8dd1aeed 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -85,8 +85,6 @@ SET(CPP_FILES
   input/xpipsaxhandler.cpp
   input/xtandemparamsaxhandler.cpp
   input/xtandemsaxhandler.cpp
-  output/masschroqml.cpp
-  output/proticdbml.cpp
   output/ods/comparbasesheet.cpp
   output/ods/comparspecificspectrasheet.cpp
   output/ods/comparspectrasheet.cpp
@@ -100,6 +98,9 @@ SET(CPP_FILES
   output/ods/samplesheet.cpp
   output/ods/simplesheet.cpp
   output/ods/spectrasheet.cpp
+  output/masschroqml.cpp
+  output/proticdbml.cpp
+  output/xpip.cpp
   utils/fastafilestore.cpp
   utils/identificationdatasourcestore.cpp
   utils/groupstore.cpp
diff --git a/src/core/identification_sources/identificationdatasource.cpp b/src/core/identification_sources/identificationdatasource.cpp
index c49f027c..ca74c073 100644
--- a/src/core/identification_sources/identificationdatasource.cpp
+++ b/src/core/identification_sources/identificationdatasource.cpp
@@ -37,6 +37,7 @@ IdentificationDataSource::IdentificationDataSource(const IdentificationDataSourc
 {
     _ms_run_sp = other._ms_run_sp;
     _resource_name = other._resource_name;
+    _xml_id = other._xml_id;
 }
 
 IdentificationDataSource::~IdentificationDataSource()
@@ -44,6 +45,12 @@ IdentificationDataSource::~IdentificationDataSource()
 
 }
 
+void IdentificationDataSource::setXmlId(const QString xmlid) {
+    _xml_id = xmlid;
+}
+const QString & IdentificationDataSource::getXmlId() const {
+    return _xml_id;
+}
 bool IdentificationDataSource::operator==(const IdentificationDataSource& other) const
 {
 
diff --git a/src/core/identification_sources/identificationdatasource.h b/src/core/identification_sources/identificationdatasource.h
index f99f8720..7d23ac48 100644
--- a/src/core/identification_sources/identificationdatasource.h
+++ b/src/core/identification_sources/identificationdatasource.h
@@ -43,6 +43,10 @@ public:
     IdentificationDataSource(const IdentificationDataSource& other);
     ~IdentificationDataSource();
     bool operator==(const IdentificationDataSource& other) const;
+    
+    
+    void setXmlId(const QString xmlid);
+    const QString & getXmlId() const;
 
     /** @brief URL or filename containing identification data
      * */
@@ -108,6 +112,7 @@ protected :
     IdentificationEngine _engine = IdentificationEngine::unknown;
 private :
     //static std::map<QString, pappso::MsRunIdSp> _map_msrunidsp;
+    QString _xml_id;
     QString _version;
     MsRunSp _ms_run_sp = nullptr;
     std::map<IdentificationEngineParam, QVariant> _params;
diff --git a/src/core/msrun.cpp b/src/core/msrun.cpp
index 390f27a0..206abdab 100644
--- a/src/core/msrun.cpp
+++ b/src/core/msrun.cpp
@@ -85,6 +85,11 @@ MzFormat MsRun::getMzFormat() const {
 void MsRun::setMsRunStatistics(MsRunStatistics param, const QVariant& value) {
     _param_stats.insert(std::pair<MsRunStatistics, QVariant>(param, value));
 }
+
+const std::map<MsRunStatistics, QVariant> & MsRun::getMsRunStatisticsMap() const {
+    return _param_stats;
+}
+
 const QVariant MsRun::getMsRunStatistics(MsRunStatistics param) const {
     try {
         return _param_stats.at(param);
diff --git a/src/core/msrun.h b/src/core/msrun.h
index ce038fc8..fcba9f99 100644
--- a/src/core/msrun.h
+++ b/src/core/msrun.h
@@ -67,6 +67,10 @@ public:
     /** \brief get MS run statistics
      */
     virtual const QVariant getMsRunStatistics(MsRunStatistics param) const;
+    
+    /** \brief get MS run statistics map
+     */
+    virtual const std::map<MsRunStatistics, QVariant> & getMsRunStatisticsMap() const;
 
 private :
     QString _xml_id;
diff --git a/src/gui/main.ui b/src/gui/main.ui
index 0fd652b6..b7bcf935 100644
--- a/src/gui/main.ui
+++ b/src/gui/main.ui
@@ -74,6 +74,7 @@
     <addaction name="action_xtandem_run"/>
     <addaction name="actionLoad_results"/>
     <addaction name="actionLoad"/>
+    <addaction name="action_save_project"/>
     <addaction name="separator"/>
     <addaction name="menu_export_files"/>
     <addaction name="separator"/>
@@ -160,6 +161,11 @@
     <string>&amp;X!Tandem run</string>
    </property>
   </action>
+  <action name="action_save_project">
+   <property name="text">
+    <string>Save project</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../xtpcpp.qrc"/>
@@ -405,6 +411,22 @@
     </hint>
    </hints>
   </connection>
+  <connection>
+   <sender>action_save_project</sender>
+   <signal>triggered()</signal>
+   <receiver>Main</receiver>
+   <slot>doActionSaveProject()</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>
@@ -419,5 +441,6 @@
   <slot>doActionSpectralCountingMcq()</slot>
   <slot>doActionAbout()</slot>
   <slot>doActionTandemRun()</slot>
+  <slot>doActionSaveProject()</slot>
  </slots>
 </ui>
diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp
index 73698b60..169b28a3 100644
--- a/src/gui/mainwindow.cpp
+++ b/src/gui/mainwindow.cpp
@@ -36,6 +36,7 @@
 #include "../utils/utils.h"
 #include "workerthread.h"
 #include "output/ods/comparspectrasheet.h"
+#include "output/xpip.h"
 
 class TsvNoSheetOutput: public TsvOutputStream {
 public :
@@ -71,6 +72,7 @@ MainWindow::MainWindow(QWidget *parent):
     ui->menu_export_files->setDisabled(true);
     ui->centralwidget->layout()->addWidget(_project_window);
     _project_window->hide();
+    ui->action_save_project->setDisabled(true);
     ui->default_display_widget->show();
     //_protein_list_window = new ProteinListWindow(this);
     //QDockWidget *dock = new QDockWidget(tr("Protein List"), this);
@@ -133,9 +135,9 @@ void MainWindow::doDisplayJobFinished(QString message) {
     qDebug() << "MainWindow::doDisplayJobFinished " <<  message;
     hideWaitingMessage();
     QMessageBox::information(this,
-                         tr("job finished"), message);
-    
-    
+                             tr("job finished"), message);
+
+
 }
 
 void MainWindow::doDisplayLoadingMessage(QString message) {
@@ -237,10 +239,11 @@ void MainWindow::doProjectReady(ProjectSp project_sp) {
 
     ui->menu_export_files->setDisabled(false);
     ui->menu_edit->setDisabled(false);
-    
-    
+
+
     _project_window->show();
     ui->default_display_widget->hide();
+    ui->action_save_project->setDisabled(false);
 
     qDebug() << "MainWindow::doProjectReady end";
 }
@@ -307,6 +310,36 @@ void MainWindow::selectXpipFile() {
 
 }
 
+
+void MainWindow::doActionSaveProject() {
+    try {
+        QMessageBox::warning(this,
+                             tr("Experimental feature"), "WARNING : project files export is not ready");
+        QSettings settings;
+        QString default_location = settings.value("path/xpipfile", "").toString();
+
+
+        QString filename = QFileDialog::getSaveFileName(this, tr("Save XPIP file"),
+                           QString("%1/untitled.xpip").arg(default_location),
+                           tr("XPIP (*.xpip)"));
+
+        if (filename.isEmpty()) {
+            return;
+        }
+
+        settings.setValue("path/xpipfile", QFileInfo(filename).absolutePath());
+
+        Xpip xpip_file(filename);
+        xpip_file.write(_project_sp);
+        xpip_file.close();
+
+    }
+    catch (pappso::PappsoException & error) {
+        viewError(tr("Error while writing XPIP file :\n%1").arg(error.qwhat()));
+    }
+
+}
+
 void MainWindow::doActionSpreadsheet() {
     qDebug() << "MainWindow::doActionSpreadsheet begin";
     try {
diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h
index d0ab7b21..40212223 100644
--- a/src/gui/mainwindow.h
+++ b/src/gui/mainwindow.h
@@ -74,6 +74,7 @@ public slots:
     void doActionTandemRun();
     void doActionSpreadsheet();
     void doActionModifications();
+    void doActionSaveProject();
     void doDisplayLoadingMessage(QString message);
     void doDisplayLoadingMessagePercent(QString message, int value);
     void doDisplayJobFinished(QString message);
diff --git a/src/output/xpip.cpp b/src/output/xpip.cpp
index e9a836e2..662bf0c9 100644
--- a/src/output/xpip.cpp
+++ b/src/output/xpip.cpp
@@ -28,6 +28,8 @@
 ******************************************************************************/
 
 #include "xpip.h"
+#include "../config.h"
+#include <QDateTime>
 #include <pappsomspp/pappsoexception.h>
 
 Xpip::Xpip(const QString & out_filename)
@@ -81,35 +83,36 @@ void Xpip::write(ProjectSp sp_project) {
     //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/xpip/4.0 http://pappso.inra.fr/xsd/xpip-4.0.xsd");
 
-    
-  //<information Data_Type="combi" match_number="6807"/>
-   // _output_stream->writeStartElement("information");
-  //  _output_stream->writeAttribute("Data_Type","combi");
-   // _output_stream->writeEndElement();
-    
-  //<filter_params pep_evalue="0.01" prot_evalue="-2.0" pep_number="2" filter_to_all="false" database_filter="/gorgone/pappso/jouy/raw/2013_Orbitrap/2013_07_04_Chanat/contaminants_standarts.fasta"/>
-    _output_stream->writeStartElement("filter_params");
-    _output_stream->writeAttribute("pep_evalue","combi");
-    _output_stream->writeAttribute("prot_evalue","combi");
-    _output_stream->writeAttribute("pep_number","combi");
-    _output_stream->writeAttribute("filter_to_all","combi");
-    _output_stream->writeEndElement();
-    
-  <identifications>
-    <identification>
-      <modifs_list_mass>
+
+    //<information Data_Type="combi" match_number="6807"/>
+    // _output_stream->writeStartElement("information");
+    //  _output_stream->writeAttribute("Data_Type","combi");
+    // _output_stream->writeEndElement();
+    writeDescription();
+
+    //<filter_params pep_evalue="0.01" prot_evalue="-2.0" pep_number="2" filter_to_all="false" database_filter="/gorgone/pappso/jouy/raw/2013_Orbitrap/2013_07_04_Chanat/contaminants_standarts.fasta"/>
+    //const AutomaticFilterParameters & getAutomaticFilterParameters() const;
+    writeFilterParameters(_sp_project.get()->getAutomaticFilterParameters());
+
+    writeMsrunList(_sp_project.get()->getMsRunStore());
+    writeIdentificationDataSourceList(_sp_project.get()->getIdentificationDataSourceStore());
+    /*
+        <identifications>
+        <identification>
+        <modifs_list_mass>
         <modifs_mass modvalue="-18.01056"/>
-        <modifs_mass modvalue="-17.02655"/>
-        <modifs_mass modvalue="15.99491"/>
-        <modifs_mass modvalue="42.01057"/>
-        <modifs_mass modvalue="42.01056"/>
-        <modifs_mass modvalue="57.02146"/>
-      </modifs_list_mass>
-      <samples>
-        <sample value="20120906_balliau_extract_1_A01_urnb-1"/>
-        <sample value="20120906_balliau_extract_1_A02_urzb-1"/>
-      </samples>
-    //<masschroq>
+                              <modifs_mass modvalue="-17.02655"/>
+                                      <modifs_mass modvalue="15.99491"/>
+                                              <modifs_mass modvalue="42.01057"/>
+                                                      <modifs_mass modvalue="42.01056"/>
+                                                              <modifs_mass modvalue="57.02146"/>
+                                                                      </modifs_list_mass>
+                                                                      <samples>
+                                                                      <sample value="20120906_balliau_extract_1_A01_urnb-1"/>
+                                                                              <sample value="20120906_balliau_extract_1_A02_urzb-1"/>
+                                                                                      </samples>
+                                                                                      //<masschroq>
+                                                                                      */
     // <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");
@@ -135,16 +138,87 @@ void Xpip::write(ProjectSp sp_project) {
     _output_stream->writeEndElement();
 
 
-    writeGroups();
-    writeProteinList();
-    writePeptideList();
-    writeIsotopeLabelList();
-    writeAlignments();
-    writeQuantificationMethods();
-    _output_stream->writeStartElement("quantification");
-    writeQuantificationResults();
-    writeQuantificationTraces();
-    writeQuantify();
+    _output_stream->writeEndDocument();
+}
+void Xpip::writeDoubleAttribute(const QString & attribute, pappso::pappso_double value) {
+    _output_stream->writeAttribute(attribute,QString::number(value, 'f', 10));
+
+}
+void Xpip::writeBooleanAttribute(const QString & attribute, bool value) {
+    if (value) {
+        _output_stream->writeAttribute(attribute,"true");
+    }
+    else {
+        _output_stream->writeAttribute(attribute,"false");
+    }
+
+}
+void Xpip::writeFilterParameters(const AutomaticFilterParameters & filters) {
+
+    _output_stream->writeStartElement("filter_params");
+    writeDoubleAttribute("pep_evalue",filters.getFilterPeptideEvalue());
+    writeDoubleAttribute("prot_evalue",filters.getFilterProteinEvalue());
+    _output_stream->writeAttribute("pep_number",QString("%1").arg(filters.getFilterMinimumPeptidePerMatch()));
+    writeBooleanAttribute("cross_sample",filters.getFilterCrossSamplePeptideNumber());
+    _output_stream->writeEndElement();
+}
+
+void Xpip::writeDescription() {
+
+    _output_stream->writeStartElement("description");
+    _output_stream->writeAttribute("version",XTPCPP_VERSION);
+    writeBooleanAttribute("combine",_sp_project.get()->isCombineMode());
+    _output_stream->writeAttribute("date",QDateTime::currentDateTime().toString( Qt::ISODate));
+    _output_stream->writeEndElement();
+}
+
+
+void Xpip::writeIdentificationDataSourceList(const IdentificationDataSourceStore & ident_store) {
+
+    _output_stream->writeStartElement("identification_source_list");
+    for (const IdentificationDataSourceSp ident_source_sp : ident_store.getIdentificationDataSourceList()) {
+        _output_stream->writeStartElement("identification_source");
+        _output_stream->writeAttribute("id",ident_source_sp.get()->getXmlId());
+        _output_stream->writeAttribute("msrun_id",ident_source_sp.get()->getMsRunSp().get()->getXmlId());
+        //_output_stream->writeAttribute("format",QString("%1").arg(static_cast<std::int8_t>(ident_source_sp.get()->getIdentFormat())));
+        _output_stream->writeAttribute("path",ident_source_sp.get()->getResourceName());
+
+        _output_stream->writeAttribute("engine",QString("%1").arg(static_cast<std::int8_t>(ident_source_sp.get()->getIdentificationEngine())));
+        _output_stream->writeAttribute("version",ident_source_sp.get()->getIdentificationEngineVersion());
+
+        _output_stream->writeEndElement();
+    }
     _output_stream->writeEndElement();
+
 }
 
+void Xpip::writeMsrunList(const MsRunStore & msrun_store) {
+
+    _output_stream->writeStartElement("msrun_list");
+    for (const MsRunSp msrun_sp : msrun_store.getMsRunList()) {
+        _output_stream->writeStartElement("msrun");
+        _output_stream->writeAttribute("id",msrun_sp.get()->getXmlId());
+        _output_stream->writeAttribute("name",msrun_sp.get()->getSampleName());
+        _output_stream->writeAttribute("format",QString("%1").arg(static_cast<std::int8_t>(msrun_sp.get()->getMzFormat())));
+        QFileInfo mz_info(msrun_sp.get()->getFilename());
+        if (mz_info.exists()) {
+            _output_stream->writeAttribute("path",msrun_sp.get()->getFilename());
+        }
+        else {
+            _output_stream->writeAttribute("path",mz_info.completeBaseName());
+        }
+        const std::map<MsRunStatistics, QVariant> stats = msrun_sp.get()->getMsRunStatisticsMap();
+        if (stats.size() > 0) {
+            _output_stream->writeStartElement("stats");
+            for (const std::pair<MsRunStatistics, QVariant> stat_pair: stats) {
+                _output_stream->writeStartElement("stat");
+                _output_stream->writeAttribute("key",QString("%1").arg(static_cast<std::int8_t>(stat_pair.first)));
+                _output_stream->writeAttribute("value",stat_pair.second.toString());
+                _output_stream->writeEndElement();
+            }
+            _output_stream->writeEndElement();
+        }
+        _output_stream->writeEndElement();
+    }
+    _output_stream->writeEndElement();
+}
diff --git a/src/output/xpip.h b/src/output/xpip.h
index 2e2f190c..a6636dc7 100644
--- a/src/output/xpip.h
+++ b/src/output/xpip.h
@@ -37,13 +37,23 @@
 
 class Xpip
 {
-        public:
+public:
     Xpip(const QString & out_filename);
     ~Xpip();
 
     void write(ProjectSp sp_project);
     void close();
-  
+
+private :
+    void writeFilterParameters(const AutomaticFilterParameters & filters);
+    void writeDescription();
+
+    void writeMsrunList(const MsRunStore & msrun_store);
+    void writeIdentificationDataSourceList(const IdentificationDataSourceStore & ident_store);
+    void writeDoubleAttribute(const QString & attribute, pappso::pappso_double value);
+    void writeBooleanAttribute(const QString & attribute, bool value);
+
+
 private :
     QFile * _output_file;
     QXmlStreamWriter * _output_stream;
diff --git a/src/utils/identificationdatasourcestore.cpp b/src/utils/identificationdatasourcestore.cpp
index c675520b..c01d92ac 100644
--- a/src/utils/identificationdatasourcestore.cpp
+++ b/src/utils/identificationdatasourcestore.cpp
@@ -32,6 +32,7 @@
 #include "../core/identification_sources/identificationxtandemfile.h"
 #include "../core/identification_sources/identificationpwizfile.h"
 #include <pappsomspp/pappsoexception.h>
+#include <pappsomspp/utils.h>
 
 IdentificationDataSourceStore::IdentificationDataSourceStore()
 {
@@ -68,6 +69,7 @@ IdentificationDataSourceSp IdentificationDataSourceStore::getInstance(const QStr
         if (p_identfile == nullptr) {
             throw pappso::PappsoException(QObject::tr("Identification resource %1 not recognized (null pointer)").arg(location));
         }
+        p_identfile.get()->setXmlId(QString("ident%1").arg(pappso::Utils::getLexicalOrderedString(_map_identification_data_sources.size())));
         
         _map_identification_data_sources.insert(std::pair< QString, IdentificationDataSourceSp >(location, p_identfile));
         _map_identification_data_sources.insert(std::pair< QString, IdentificationDataSourceSp >(location_file.absoluteFilePath(), p_identfile));
diff --git a/src/utils/types.h b/src/utils/types.h
index 619d3b7c..68c5507b 100644
--- a/src/utils/types.h
+++ b/src/utils/types.h
@@ -43,11 +43,11 @@ enum class ExternalDatabase: std::int8_t {
 /** \def IdentificationEngine identification engine
  *
  */
-enum class IdentificationEngine {
-    unknown, ///< X!Tandem
-    XTandem, ///< X!Tandem
-    mascot, ///< Mascot
-    peptider ///< peptider
+enum class IdentificationEngine: std::int8_t {
+    unknown=0, ///< X!Tandem
+    XTandem=1, ///< X!Tandem
+    mascot=2, ///< Mascot
+    peptider=3 ///< peptider
 };
 
 /** \def PeptideMatchParam peptide match specific parameters
@@ -102,11 +102,11 @@ enum class GroupingType {
  *
  */
 
-enum class MzFormat {
-    unknown, ///< unknown format
-    mzML, ///< mzML
-    mzXML, ///< mzXML
-    MGF, ///< Mascot format
+enum class MzFormat: std::int8_t {
+    unknown=0, ///< unknown format
+    mzML=1, ///< mzML
+    mzXML=2, ///< mzXML
+    MGF=3, ///< Mascot format
 };
 
 /** \def ValidationState
-- 
GitLab