From 4a50ada7bc9e03f65424ede1320179bfbb758c91 Mon Sep 17 00:00:00 2001
From: Olivier Langella <Olivier.Langella@moulon.inra.fr>
Date: Fri, 7 Apr 2017 17:38:41 +0200
Subject: [PATCH] FDR computation OK

---
 src/core/identificationgroup.cpp       |  52 +++++++++
 src/core/identificationgroup.h         |   7 ++
 src/gui/project_view/project_view.ui   | 146 ++++++++++++++++++++++++-
 src/gui/project_view/projectwindow.cpp |  29 ++++-
 src/gui/project_view/projectwindow.h   |   2 +
 src/utils/proteinstore.cpp             |  10 ++
 src/utils/proteinstore.h               |   5 +
 src/utils/types.h                      |  11 ++
 8 files changed, 254 insertions(+), 8 deletions(-)

diff --git a/src/core/identificationgroup.cpp b/src/core/identificationgroup.cpp
index a56976d9a..a2c3f253a 100644
--- a/src/core/identificationgroup.cpp
+++ b/src/core/identificationgroup.cpp
@@ -41,6 +41,58 @@ IdentificationGroup::~IdentificationGroup()
     }
 }
 
+
+unsigned int IdentificationGroup::countDecoyProtein(ValidationState state) const {
+    unsigned int i=0;
+    for (auto & p_protein_match : _protein_match_list) {
+        if (!p_protein_match->getProteinXtpSp().get()->isDecoy()) continue;
+        if (state == ValidationState::grouped) {
+            if (p_protein_match->isGrouped()) {
+                i++;
+            }
+        }
+        else if(state == ValidationState::valid) {
+            if (p_protein_match->isValid()) {
+                i++;
+            }
+
+        }
+        else if (state == ValidationState::validAndChecked) {
+            if (p_protein_match->isValidAndChecked()) {
+                i++;
+            }
+
+        }
+    }
+    return i;
+}
+
+unsigned int IdentificationGroup::countProtein(ValidationState state) const {
+    unsigned int i=0;
+    if (state == ValidationState::grouped) {
+        for (auto & p_protein_match : _protein_match_list) {
+            if (p_protein_match->isGrouped()) {
+                i++;
+            }
+        }
+    }
+    else if(state == ValidationState::valid) {
+        for (auto & p_protein_match : _protein_match_list) {
+            if (p_protein_match->isValid()) {
+                i++;
+            }
+        }
+    }
+    else if (state == ValidationState::validAndChecked) {
+        for (auto & p_protein_match : _protein_match_list) {
+            if (p_protein_match->isValidAndChecked()) {
+                i++;
+            }
+        }
+    }
+    return i;
+}
+
 void IdentificationGroup::updateAutomaticFilters(const AutomaticFilterParameters & automatic_filter_parameters) {
     for (auto & p_protein_match : _protein_match_list) {
         p_protein_match->updateAutomaticFilters(automatic_filter_parameters);
diff --git a/src/core/identificationgroup.h b/src/core/identificationgroup.h
index 27986627f..767f8cc25 100644
--- a/src/core/identificationgroup.h
+++ b/src/core/identificationgroup.h
@@ -68,6 +68,13 @@ public:
        /** @brief count subgroups
      * */    
     std::size_t countSubGroup()const;
+    
+    /** @brief count proteins
+     * */    
+    unsigned int countProtein(ValidationState state) const;
+    /** @brief count decoy proteins
+     * */    
+    unsigned int countDecoyProtein(ValidationState state) const;
 
 
     /** @brief validate or invalidate peptides and proteins based automatic filters and manual checks
diff --git a/src/gui/project_view/project_view.ui b/src/gui/project_view/project_view.ui
index c2a73be55..eaad0707a 100644
--- a/src/gui/project_view/project_view.ui
+++ b/src/gui/project_view/project_view.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>445</width>
-    <height>392</height>
+    <width>465</width>
+    <height>493</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -53,7 +53,121 @@
        </attribute>
        <layout class="QGridLayout" name="gridLayout2">
         <item row="0" column="0">
-         <layout class="QFormLayout" name="formLayout_2"/>
+         <layout class="QVBoxLayout" name="verticalLayout_2">
+          <item>
+           <widget class="QGroupBox" name="groupBox_3">
+            <property name="title">
+             <string>FDR</string>
+            </property>
+            <layout class="QFormLayout" name="formLayout">
+             <item row="0" column="0">
+              <widget class="QLabel" name="label">
+               <property name="text">
+                <string>FDR on peptides</string>
+               </property>
+              </widget>
+             </item>
+             <item row="0" column="1">
+              <widget class="QLabel" name="peptide_fdr_label">
+               <property name="text">
+                <string>0 %</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="0">
+              <widget class="QLabel" name="label_3">
+               <property name="text">
+                <string>FDR on proteins</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1">
+              <widget class="QLabel" name="protein_fdr_label">
+               <property name="text">
+                <string>0 %</string>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item>
+           <widget class="QGroupBox" name="groupBox">
+            <property name="title">
+             <string>Decoy database files</string>
+            </property>
+            <layout class="QVBoxLayout" name="verticalLayout_3">
+             <item>
+              <widget class="QListWidget" name="decoy_database_list_widget"/>
+             </item>
+             <item>
+              <layout class="QHBoxLayout" name="horizontalLayout">
+               <item>
+                <spacer name="horizontalSpacer">
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                 <property name="sizeHint" stdset="0">
+                  <size>
+                   <width>40</width>
+                   <height>20</height>
+                  </size>
+                 </property>
+                </spacer>
+               </item>
+               <item>
+                <widget class="QPushButton" name="pushButton">
+                 <property name="text">
+                  <string>add</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+            </layout>
+           </widget>
+          </item>
+         </layout>
+        </item>
+        <item row="1" column="0">
+         <widget class="QGroupBox" name="groupBox_2">
+          <property name="title">
+           <string>Decoy protein regular expression</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_4">
+           <item>
+            <widget class="QLineEdit" name="decoy_protein_regexp_line_edit">
+             <property name="placeholderText">
+              <string>.*\\|reversed$</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </widget>
+        </item>
+        <item row="3" column="0">
+         <layout class="QHBoxLayout" name="horizontalLayout_2">
+          <item>
+           <spacer name="horizontalSpacer_2">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QPushButton" name="pushButton_2">
+            <property name="text">
+             <string>OK</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
         </item>
        </layout>
       </widget>
@@ -76,13 +190,33 @@
     <rect>
      <x>0</x>
      <y>0</y>
-     <width>445</width>
-     <height>23</height>
+     <width>465</width>
+     <height>25</height>
     </rect>
    </property>
   </widget>
   <widget class="QStatusBar" name="statusbar"/>
  </widget>
  <resources/>
- <connections/>
+ <connections>
+  <connection>
+   <sender>pushButton_2</sender>
+   <signal>clicked()</signal>
+   <receiver>ProjectView</receiver>
+   <slot>doFdrChanged()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>403</x>
+     <y>329</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>484</x>
+     <y>334</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <slots>
+  <slot>doFdrChanged()</slot>
+ </slots>
 </ui>
diff --git a/src/gui/project_view/projectwindow.cpp b/src/gui/project_view/projectwindow.cpp
index 551022b34..125b57b45 100644
--- a/src/gui/project_view/projectwindow.cpp
+++ b/src/gui/project_view/projectwindow.cpp
@@ -45,7 +45,7 @@ ProjectWindow::ProjectWindow(MainWindow *parent):
     _p_automatic_filter_widget = new AutomaticFilterWidget(this);
     ui->filter_parameter_layout->addWidget(_p_automatic_filter_widget);
 
-    
+
 
 #if QT_VERSION >= 0x050000
     // Qt5 code
@@ -58,7 +58,7 @@ ProjectWindow::ProjectWindow(MainWindow *parent):
 // Qt4 code
     //connect (_protein_list_window, SIGNAL(proteinMatchClicked(ProteinMatch *)), this //,SLOT(doProteinMatchClicked(ProteinMatch *)));
     connect (_p_automatic_filter_widget, SIGNAL(automaticFilterParametersChanged(AutomaticFilterParameters)), this,SLOT(doAutomaticFilterParametersChanged(AutomaticFilterParameters)));
-    
+
 #endif
     /*
     */
@@ -138,7 +138,29 @@ void ProjectWindow::refreshGroup(IdentificationGroup * p_ident_group) {
     qDebug() << "ProjectWindow::refreshGroup end";
 }
 
+void ProjectWindow::computeFdr() {
+    pappso::pappso_double total_prot=0;
+    pappso::pappso_double false_prot=0;
+    for (IdentificationGroup * identification_group : _project_sp.get()->getIdentificationGroupList()) {
+        total_prot += identification_group->countProtein(ValidationState::grouped);
+        false_prot += identification_group->countDecoyProtein(ValidationState::grouped);
+    }
+    ui->protein_fdr_label->setText(QString("%1 %").arg(false_prot/total_prot));
+}
+
+void ProjectWindow::doFdrChanged() {
+    qDebug() << "ProjectWindow::doFdrChanged begin ";
+    _project_sp.get()->getProteinStore().setRegexpDecoyPattern(ui->decoy_protein_regexp_line_edit->text());
+    _project_sp.get()->updateAutomaticFilters(_project_sp.get()->getAutomaticFilterParameters());
 
+    //re group
+    for (IdentificationGroup * identification_group : _project_sp.get()->getIdentificationGroupList()) {
+        doIdentificationGroupEdited(identification_group);
+    }
+
+    computeFdr();
+    qDebug() << "ProjectWindow::doFdrChanged end ";
+}
 void ProjectWindow::doAutomaticFilterParametersChanged(AutomaticFilterParameters parameters) {
     qDebug() << "ProjectWindow::doAutomaticFilterParametersChanged begin ";
     _project_sp.get()->updateAutomaticFilters(parameters);
@@ -312,5 +334,8 @@ void ProjectWindow::setProjectSp(ProjectSp project_sp) {
     _p_automatic_filter_widget->setAutomaticFilterParameters(params);
     //_protein_list_window->setIdentificationGroup(_project_sp.get()->getCurrentIdentificationGroupP());
     //_protein_list_window->show();
+
+    ui->decoy_protein_regexp_line_edit->setText(_project_sp.get()->getProteinStore().getRegexpDecoy().pattern());
+    computeFdr();
     this->setEnabled(true);
 }
diff --git a/src/gui/project_view/projectwindow.h b/src/gui/project_view/projectwindow.h
index 6a47e2cb6..c9b140fdb 100644
--- a/src/gui/project_view/projectwindow.h
+++ b/src/gui/project_view/projectwindow.h
@@ -55,6 +55,7 @@ public slots:
     void doViewProteinList(IdentificationGroup* p_identification_group =nullptr);
     void setDefaultProteinListWindow(ProteinListWindow* p_protein_list_window);
     void doAutomaticFilterParametersChanged(AutomaticFilterParameters parameters);
+    void doFdrChanged();
     // void setColor(const QColor &color);
     // void setShape(Shape shape);
 signals:
@@ -67,6 +68,7 @@ protected :
     void doViewPeptideDetail(PeptideMatch * peptide_match);
     void doViewProteinDetail(ProteinMatch * protein_match);
     void doIdentificationGroupEdited(IdentificationGroup * p_identification_group);
+    void computeFdr();
 
 private :
     void connectNewProteinListWindow();
diff --git a/src/utils/proteinstore.cpp b/src/utils/proteinstore.cpp
index 7eab25a11..d2d95dc24 100644
--- a/src/utils/proteinstore.cpp
+++ b/src/utils/proteinstore.cpp
@@ -42,6 +42,16 @@ ProteinStore::~ProteinStore()
 {
 
 }
+QRegExp ProteinStore::getRegexpDecoy() const {
+    return (_regexp_decoy);
+}
+void ProteinStore::setRegexpDecoyPattern(const QString & pattern) {
+    _regexp_decoy.setPattern(pattern);
+    
+    for  (std::pair<const QString, ProteinXtpSp> & acc_protein :_map_accession_protein_list) {
+        setProteinInformations(acc_protein.second);
+    }
+}
 
 ProteinXtpSp & ProteinStore::getInstance(ProteinXtpSp & peptide_in) {
 
diff --git a/src/utils/proteinstore.h b/src/utils/proteinstore.h
index 14d7f1945..93c755cea 100644
--- a/src/utils/proteinstore.h
+++ b/src/utils/proteinstore.h
@@ -33,6 +33,7 @@
 #define PROTEINSTORE_H
 
 #include "../core/proteinxtp.h"
+#include "types.h"
 #include <QString>
 #include <QRegExp>
 #include <map>
@@ -44,6 +45,10 @@ public:
     ~ProteinStore();
     
     ProteinXtpSp & getInstance(ProteinXtpSp & protein_in);
+    
+    void setRegexpDecoyPattern(const QString & pattern);
+    
+    QRegExp getRegexpDecoy() const;
 
 private :
     void setProteinInformations(ProteinXtpSp & protein_in);
diff --git a/src/utils/types.h b/src/utils/types.h
index 7a5be71be..e3cbf9b1c 100644
--- a/src/utils/types.h
+++ b/src/utils/types.h
@@ -46,6 +46,17 @@ enum class MzFormat {
      mzXML, ///< mzXML
 };
 
+/** \def ValidationState
+ *
+ */
+
+enum class ValidationState {
+     valid, ///< valid : automatic filter validation passed
+     validAndChecked, ///< validAndChecked : automatic filter validation passed + manual checking
+     grouped, ///< grouped : automatic filter validation passed + manual checking + grouped
+};
+
+
 /** \def ProteinListColumn list of available fields to display in protein list
  *
  */
-- 
GitLab