From 8daacc98c00e72dc1609143b88d413e538674ada Mon Sep 17 00:00:00 2001
From: "Filippo Rusconi (Uploading Debian Developer)" <lopippo@debian.org>
Date: Fri, 4 Nov 2022 11:43:53 +0100
Subject: [PATCH 1/6] Import new versions from the qt6olivier branch.

---
 src/pappsomspp/msfile/msfileaccessor.cpp      |   9 +-
 src/pappsomspp/peptide/peptide.cpp            |  16 +
 src/pappsomspp/peptide/peptide.h              |  11 +-
 .../peptide/peptidenaturalisotope.h           |   2 +-
 .../peptide/peptidenaturalisotopeaverage.cpp  |  34 ++
 .../peptide/peptidenaturalisotopeaverage.h    |  11 +-
 .../detection/tracedetectioninterface.h       |  11 +-
 .../detection/tracedetectionmoulon.cpp        |   5 +-
 .../detection/tracedetectionmoulon.h          |   3 +-
 .../detection/tracedetectionzivy.cpp          |   5 +-
 .../processing/detection/tracedetectionzivy.h |  17 +-
 .../processing/detection/tracepeak.cpp        |  53 +++
 .../processing/detection/tracepeak.h          |  54 ++-
 src/pappsomspp/psm/features/psmfeatures.cpp   | 313 +++++++++++++++++-
 src/pappsomspp/psm/features/psmfeatures.h     | 103 +++++-
 src/pappsomspp/psm/peakionisotopematch.cpp    |  60 +++-
 src/pappsomspp/psm/peakionisotopematch.h      |  12 +
 src/pappsomspp/psm/peakionmatch.cpp           |  54 +++
 src/pappsomspp/psm/peakionmatch.h             |  39 +--
 .../psm/peptideisotopespectrummatch.cpp       | 110 ++++--
 .../psm/peptideisotopespectrummatch.h         |  28 +-
 src/pappsomspp/psm/peptidespectrummatch.h     |   2 +-
 .../psm/xtandem/xtandemhyperscore.cpp         |   8 +-
 src/pappsomspp/trace/trace.cpp                |  29 ++
 src/pappsomspp/trace/trace.h                  |   8 +-
 src/pappsomspp/vendors/tims/timsframebase.cpp |  65 ++++
 src/pappsomspp/vendors/tims/timsframebase.h   |  11 +
 .../massspectrumwidget/massspectrumwidget.cpp |  13 +-
 .../massspectrumwidget/massspectrumwidget.h   |   2 +-
 .../widget/massspectrumwidget/qcpspectrum.cpp |  12 +-
 .../widget/plotwidget/basetraceplotwidget.cpp |   3 -
 src/pappsomspp/widget/xicwidget/qcpxic.cpp    |  28 +-
 src/pappsomspp/widget/xicwidget/qcpxic.h      |   2 +-
 src/pappsomspp/widget/xicwidget/xicwidget.cpp |   6 +-
 src/pappsomspp/widget/xicwidget/xicwidget.h   |   2 +-
 src/pappsomspp/xic/xic.cpp                    |   4 +
 src/pappsomspp/xic/xic.h                      |   1 +
 .../xicextractor/msrunxicextractorfactory.cpp |   3 -
 tests/test_psm.cpp                            | 242 +++++++++++++-
 tests/test_xic.cpp                            |  67 ++--
 40 files changed, 1234 insertions(+), 224 deletions(-)

diff --git a/src/pappsomspp/msfile/msfileaccessor.cpp b/src/pappsomspp/msfile/msfileaccessor.cpp
index caeab30ae..f37ef669e 100644
--- a/src/pappsomspp/msfile/msfileaccessor.cpp
+++ b/src/pappsomspp/msfile/msfileaccessor.cpp
@@ -7,7 +7,7 @@
 
 #include "msfileaccessor.h"
 #include "pwizmsfilereader.h"
-//#include "timsmsfilereader.h"
+#include "timsmsfilereader.h"
 #include "xymsfilereader.h"
 
 
@@ -16,8 +16,8 @@
 #include "../utils.h"
 #include "../msrun/msrunid.h"
 #include "../msrun/private/pwizmsrunreader.h"
-//#include "../msrun/private/timsmsrunreader.h"
-//#include "../msrun/private/timsmsrunreaderms2.h"
+#include "../msrun/private/timsmsrunreader.h"
+#include "../msrun/private/timsmsrunreaderms2.h"
 #include "../msrun/xymsrunreader.h"
 
 
@@ -260,8 +260,6 @@ MsFileAccessor::buildMsRunReaderSPtr(
         QObject::tr("unable to build a reader for %1 : unknown file format")
           .arg(QFileInfo(ms_run_id.get()->getFileName()).absoluteFilePath())));
     }
-#if 0
-// Remove this section because it cripples my work on Qt6 build
   
   else if(file_format == MzFormat::brukerTims)
     {
@@ -278,7 +276,6 @@ MsFileAccessor::buildMsRunReaderSPtr(
       qDebug() << "by default, build a TimsMsRunReader.";
       return std::make_shared<TimsMsRunReader>(ms_run_id);
     }
-#endif
   else
     {
       qDebug() << "Returning a PwizMsRunReader .";
diff --git a/src/pappsomspp/peptide/peptide.cpp b/src/pappsomspp/peptide/peptide.cpp
index db6deba79..28745eea1 100644
--- a/src/pappsomspp/peptide/peptide.cpp
+++ b/src/pappsomspp/peptide/peptide.cpp
@@ -39,6 +39,22 @@
 namespace pappso
 {
 
+bool
+peptideIonTypeIsComplement(PeptideIon ion_type_ref, PeptideIon ion_type)
+{
+  if(peptideIonIsNter(ion_type))
+    std::swap(ion_type_ref, ion_type);
+  if(peptideIonIsNter(ion_type))
+    return false;
+  if((ion_type_ref == PeptideIon::b) && (ion_type == PeptideIon::y))
+    return true;
+  if((ion_type_ref == PeptideIon::ao) && (ion_type == PeptideIon::yo))
+    return true;
+  if((ion_type_ref == PeptideIon::bstar) && (ion_type == PeptideIon::ystar))
+    return true;
+
+  return false;
+}
 
 bool
 peptideIonIsNter(PeptideIon ion_type)
diff --git a/src/pappsomspp/peptide/peptide.h b/src/pappsomspp/peptide/peptide.h
index 82db6a9f5..22fd740ca 100644
--- a/src/pappsomspp/peptide/peptide.h
+++ b/src/pappsomspp/peptide/peptide.h
@@ -52,14 +52,21 @@ enum class PeptideDirection : std::int8_t
 /** \brief tells if an ion is Nter
  * \param ion_type the ion to test
  */
-bool peptideIonIsNter(PeptideIon ion_type);
+PMSPP_LIB_DECL bool peptideIonIsNter(PeptideIon ion_type);
+
+/** \brief tells if an ion type is the complement ion of the other
+ * \param ion_type_ref the ion type reference
+ * \param ion_type the ion to test
+ */
+PMSPP_LIB_DECL bool peptideIonTypeIsComplement(PeptideIon ion_type_ref,
+                                               PeptideIon ion_type);
 
 
 /** \brief get the direction of a peptide ion
  * \param ion_type the ion to test
  * \return the peptide direction
  */
-PeptideDirection getPeptideIonDirection(PeptideIon ion_type);
+PMSPP_LIB_DECL PeptideDirection getPeptideIonDirection(PeptideIon ion_type);
 
 enum class PeptideIonNter
 {
diff --git a/src/pappsomspp/peptide/peptidenaturalisotope.h b/src/pappsomspp/peptide/peptidenaturalisotope.h
index b55eaeb38..bce9b9602 100644
--- a/src/pappsomspp/peptide/peptidenaturalisotope.h
+++ b/src/pappsomspp/peptide/peptidenaturalisotope.h
@@ -48,7 +48,7 @@ class PMSPP_LIB_DECL PeptideNaturalIsotope : public PeptideInterface
   PeptideNaturalIsotope(const PeptideInterfaceSp &peptide,
                         const std::map<Isotope, int> &map_isotope);
   PeptideNaturalIsotope(const PeptideNaturalIsotope &other);
-  ~PeptideNaturalIsotope();
+  virtual ~PeptideNaturalIsotope();
 
   virtual unsigned int size() const override;
   virtual const QString getSequence() const override;
diff --git a/src/pappsomspp/peptide/peptidenaturalisotopeaverage.cpp b/src/pappsomspp/peptide/peptidenaturalisotopeaverage.cpp
index 6d54a05b1..90a4deac1 100644
--- a/src/pappsomspp/peptide/peptidenaturalisotopeaverage.cpp
+++ b/src/pappsomspp/peptide/peptidenaturalisotopeaverage.cpp
@@ -29,6 +29,28 @@
 
 namespace pappso
 {
+
+
+PeptideNaturalIsotopeAverage::PeptideNaturalIsotopeAverage(
+  const PeptideInterfaceSp &peptide,
+  unsigned int isotopeNumber,
+  unsigned int charge,
+  PrecisionPtr precision)
+  : mcsp_peptideSp(peptide),
+    m_isotopeLevel(isotopeNumber),
+    m_isotopeRank(1),
+    m_z(charge),
+    mp_precision(precision)
+{
+
+  m_peptideNaturalIsotopeSpList.clear();
+
+  double diffC13 = ((double)isotopeNumber * DIFFC12C13) / (double)charge;
+
+  m_averageMz      = peptide.get()->getMz(charge) + diffC13;
+  m_abundanceRatio = 0;
+}
+
 PeptideNaturalIsotopeAverage::PeptideNaturalIsotopeAverage(
   const PeptideInterfaceSp &peptide,
   unsigned int askedIsotopeRank,
@@ -161,6 +183,7 @@ PeptideNaturalIsotopeAverage::PeptideNaturalIsotopeAverage(
   : mcsp_peptideSp(other.mcsp_peptideSp), mp_precision(other.mp_precision)
 {
 
+  qDebug();
   m_peptideNaturalIsotopeSpList = other.m_peptideNaturalIsotopeSpList;
 
   m_averageMz      = other.m_averageMz;
@@ -168,6 +191,7 @@ PeptideNaturalIsotopeAverage::PeptideNaturalIsotopeAverage(
   m_isotopeLevel   = other.m_isotopeLevel;
   m_isotopeRank    = other.m_isotopeRank;
   m_z              = other.m_z;
+  qDebug();
 }
 
 PeptideNaturalIsotopeAverage::~PeptideNaturalIsotopeAverage()
@@ -237,4 +261,14 @@ PeptideNaturalIsotopeAverage::isEmpty() const
   return (m_peptideNaturalIsotopeSpList.size() == 0);
 }
 
+QString
+PeptideNaturalIsotopeAverage::toString() const
+{
+  return QString("%1 l%2 mz%3 z%4 N%5")
+    .arg(getPeptideInterfaceSp().get()->getSequence())
+    .arg(getPeptideInterfaceSp().get()->size())
+    .arg(getMz())
+    .arg(getCharge())
+    .arg(getIsotopeNumber());
+}
 } // namespace pappso
diff --git a/src/pappsomspp/peptide/peptidenaturalisotopeaverage.h b/src/pappsomspp/peptide/peptidenaturalisotopeaverage.h
index c84556e4c..c06ca0232 100644
--- a/src/pappsomspp/peptide/peptidenaturalisotopeaverage.h
+++ b/src/pappsomspp/peptide/peptidenaturalisotopeaverage.h
@@ -42,6 +42,14 @@ typedef std::shared_ptr<const PeptideNaturalIsotopeAverage>
 class PMSPP_LIB_DECL PeptideNaturalIsotopeAverage
 {
   public:
+  /** @brief fast constructor
+   * simple isotope build, not computing isotope ratio
+   */
+  PeptideNaturalIsotopeAverage(const PeptideInterfaceSp &peptide,
+                               unsigned int isotopeNumber,
+                               unsigned int charge,
+                               PrecisionPtr precision);
+
   PeptideNaturalIsotopeAverage(const PeptideInterfaceSp &peptide,
                                unsigned int askedIsotopeRank,
                                unsigned int isotopeLevel,
@@ -54,7 +62,7 @@ class PMSPP_LIB_DECL PeptideNaturalIsotopeAverage
                                PrecisionPtr precision);
 
   PeptideNaturalIsotopeAverage(const PeptideNaturalIsotopeAverage &other);
-  ~PeptideNaturalIsotopeAverage();
+  virtual ~PeptideNaturalIsotopeAverage();
 
   PeptideNaturalIsotopeAverageSp makePeptideNaturalIsotopeAverageSp() const;
   pappso_double getMz() const;
@@ -67,6 +75,7 @@ class PMSPP_LIB_DECL PeptideNaturalIsotopeAverage
   PrecisionPtr getPrecision() const;
   virtual bool matchPeak(pappso_double peak_mz) const final;
   bool isEmpty() const;
+  virtual QString toString() const;
 
   private:
   void recursiveDepletion(std::vector<PeptideNaturalIsotopeSp> &v_isotope_list,
diff --git a/src/pappsomspp/processing/detection/tracedetectioninterface.h b/src/pappsomspp/processing/detection/tracedetectioninterface.h
index 52aa045bd..114c9cd85 100644
--- a/src/pappsomspp/processing/detection/tracedetectioninterface.h
+++ b/src/pappsomspp/processing/detection/tracedetectioninterface.h
@@ -43,8 +43,15 @@ class TraceDetectionSinkInterface
 class TraceDetectionInterface
 {
   public:
-  virtual void detect(const Trace &xic,
-                      TraceDetectionSinkInterface &sink) const = 0;
+  /** @brief detect peaks on a trace
+   * @param trace the trace to detect peaks on
+   * @param sink the object to store peaks or stream it
+   * @param remove_peak_base if true, removes the area under the base of the
+   * peak
+   */
+  virtual void detect(const Trace &trace,
+                      TraceDetectionSinkInterface &sink,
+                      bool remove_peak_base) const = 0;
 };
 
 
diff --git a/src/pappsomspp/processing/detection/tracedetectionmoulon.cpp b/src/pappsomspp/processing/detection/tracedetectionmoulon.cpp
index 2fb3ed76f..a3c275c7b 100644
--- a/src/pappsomspp/processing/detection/tracedetectionmoulon.cpp
+++ b/src/pappsomspp/processing/detection/tracedetectionmoulon.cpp
@@ -84,7 +84,8 @@ TraceDetectionMoulon::getTicStop() const
 
 void
 TraceDetectionMoulon::detect(const Trace &xic,
-                             TraceDetectionSinkInterface &sink) const
+                             TraceDetectionSinkInterface &sink,
+                             bool remove_peak_base) const
 {
 
   Trace xic_smoothed(xic);
@@ -138,7 +139,7 @@ TraceDetectionMoulon::detect(const Trace &xic,
 
               if(banked)
                 {
-                  TracePeak peak(it_begin, it + 1);
+                  TracePeak peak(it_begin, it + 1, remove_peak_base);
                   sink.setTracePeak(peak);
                 }
               banked = false;
diff --git a/src/pappsomspp/processing/detection/tracedetectionmoulon.h b/src/pappsomspp/processing/detection/tracedetectionmoulon.h
index d144048c4..22dd6d402 100644
--- a/src/pappsomspp/processing/detection/tracedetectionmoulon.h
+++ b/src/pappsomspp/processing/detection/tracedetectionmoulon.h
@@ -56,7 +56,8 @@ class PMSPP_LIB_DECL TraceDetectionMoulon : public TraceDetectionInterface
 
 
   void detect(const Trace &xic,
-              TraceDetectionSinkInterface &sink) const override;
+              TraceDetectionSinkInterface &sink,
+              bool remove_peak_base) const override;
 };
 
 
diff --git a/src/pappsomspp/processing/detection/tracedetectionzivy.cpp b/src/pappsomspp/processing/detection/tracedetectionzivy.cpp
index db3dd951d..e72c72ecd 100644
--- a/src/pappsomspp/processing/detection/tracedetectionzivy.cpp
+++ b/src/pappsomspp/processing/detection/tracedetectionzivy.cpp
@@ -107,7 +107,8 @@ TraceDetectionZivy::getDetectionThresholdOnMaxmin() const
 
 void
 TraceDetectionZivy::detect(const Trace &xic,
-                           TraceDetectionSinkInterface &sink) const
+                           TraceDetectionSinkInterface &sink,
+                           bool remove_peak_base) const
 {
 
   // detect peak positions on close curve : a peak is an intensity value
@@ -214,7 +215,7 @@ TraceDetectionZivy::detect(const Trace &xic,
               // peak.setMaxXicElement(*maxYDataPoint(it, xic_position));
 
               // areaTrace()
-              TracePeak peak(it, xic_position);
+              TracePeak peak(it, xic_position, remove_peak_base);
               sink.setTracePeak(peak);
               // }
               //++i;
diff --git a/src/pappsomspp/processing/detection/tracedetectionzivy.h b/src/pappsomspp/processing/detection/tracedetectionzivy.h
index 3ec699efa..a2a44be3a 100644
--- a/src/pappsomspp/processing/detection/tracedetectionzivy.h
+++ b/src/pappsomspp/processing/detection/tracedetectionzivy.h
@@ -35,12 +35,6 @@ namespace pappso
 
 class PMSPP_LIB_DECL TraceDetectionZivy : public TraceDetectionInterface
 {
-  private:
-  FilterMorphoMean m_smooth;
-  FilterMorphoMinMax m_minMax;
-  FilterMorphoMaxMin m_maxMin;
-  pappso_double m_detectionThresholdOnMinMax;
-  pappso_double m_detectionThresholdOnMaxMin;
 
   public:
   TraceDetectionZivy(unsigned int smoothing_half_window_length,
@@ -65,7 +59,16 @@ class PMSPP_LIB_DECL TraceDetectionZivy : public TraceDetectionInterface
   pappso_double getDetectionThresholdOnMaxmin() const;
 
   void detect(const Trace &xic,
-              TraceDetectionSinkInterface &sink) const override;
+              TraceDetectionSinkInterface &sink,
+              bool remove_peak_base) const override;
+
+
+  private:
+  FilterMorphoMean m_smooth;
+  FilterMorphoMinMax m_minMax;
+  FilterMorphoMaxMin m_maxMin;
+  pappso_double m_detectionThresholdOnMinMax;
+  pappso_double m_detectionThresholdOnMaxMin;
 };
 
 } // namespace pappso
diff --git a/src/pappsomspp/processing/detection/tracepeak.cpp b/src/pappsomspp/processing/detection/tracepeak.cpp
index 68c04b32f..5bb4c0128 100644
--- a/src/pappsomspp/processing/detection/tracepeak.cpp
+++ b/src/pappsomspp/processing/detection/tracepeak.cpp
@@ -31,6 +31,7 @@ namespace pappso
 TracePeak::TracePeak()
 {
 }
+
 TracePeak::TracePeak(std::vector<DataPoint>::const_iterator it_begin,
                      std::vector<DataPoint>::const_iterator it_end)
 {
@@ -41,6 +42,24 @@ TracePeak::TracePeak(std::vector<DataPoint>::const_iterator it_begin,
   m_area  = areaTrace(it_begin, it_end);
 }
 
+TracePeak::TracePeak(std::vector<DataPoint>::const_iterator it_begin,
+                     std::vector<DataPoint>::const_iterator it_end,
+                     bool remove_base)
+{
+
+  m_left  = *it_begin;
+  m_right = *(it_end - 1);
+  m_max   = *maxYDataPoint(it_begin, it_end);
+  m_area  = areaTrace(it_begin, it_end);
+  if(remove_base)
+    {
+      // remove the base of this peak
+      m_area -= std::min(m_left.y, m_right.y) * (m_right.x - m_left.x);
+      if(m_area < 0)
+        m_area = 0;
+    }
+}
+
 TracePeak::TracePeak(const TracePeak &other)
 {
   m_area  = other.m_area;
@@ -117,4 +136,38 @@ TracePeak::containsRt(pappso::pappso_double rt) const
   return (false);
 }
 
+
+const DataPoint &
+TracePeak::getMaxXicElement() const
+{
+  return m_max;
+}
+
+const DataPoint &
+TracePeak::getLeftBoundary() const
+{
+  return m_left;
+}
+
+
+bool
+TracePeak::operator==(const TracePeak &other) const
+{
+  return ((m_area == other.m_area) && (m_max == other.m_max) &&
+          (m_left == other.m_left) && (m_right == other.m_right));
+}
+
+TracePeak &
+TracePeak::operator=(const TracePeak &other)
+{
+  if(this == &other)
+    return *this;
+
+  m_area  = other.m_area;
+  m_max   = other.m_max;
+  m_left  = other.m_left;
+  m_right = other.m_right;
+
+  return *this;
+}
 } // namespace pappso
diff --git a/src/pappsomspp/processing/detection/tracepeak.h b/src/pappsomspp/processing/detection/tracepeak.h
index 372359260..abfbafb4d 100644
--- a/src/pappsomspp/processing/detection/tracepeak.h
+++ b/src/pappsomspp/processing/detection/tracepeak.h
@@ -38,18 +38,22 @@ typedef std::shared_ptr<const TracePeak> TracePeakCstSPtr;
  * */
 class PMSPP_LIB_DECL TracePeak
 {
-  protected:
-  pappso_double m_area = 0;
-  DataPoint m_max;
-  DataPoint m_left;
-  DataPoint m_right;
-
   public:
   TracePeak();
   /** @brief construct a peak given a trace, begin and end x coordinate
    */
   TracePeak(std::vector<DataPoint>::const_iterator it_begin,
             std::vector<DataPoint>::const_iterator it_end);
+
+  /** @brief construct a peak given a trace, begin and end x coordinate
+   *
+   * @param it_begin begining of trace
+   * @param it_end end of trace
+   * @param remove_base if true, remove the base peak signal
+   */
+  TracePeak(std::vector<DataPoint>::const_iterator it_begin,
+            std::vector<DataPoint>::const_iterator it_end,
+            bool remove_base);
   TracePeak(const TracePeak &other);
   ~TracePeak();
 
@@ -57,50 +61,34 @@ class PMSPP_LIB_DECL TracePeak
   TracePeakCstSPtr makeTracePeakCstSPtr() const;
 
   DataPoint &getMaxXicElement();
-  const DataPoint &
-  getMaxXicElement() const
-  {
-    return m_max;
-  };
+  const DataPoint &getMaxXicElement() const;
   void setMaxXicElement(const DataPoint &max);
 
   DataPoint &getLeftBoundary();
-  const DataPoint &
-  getLeftBoundary() const
-  {
-    return m_left;
-  };
+  const DataPoint &getLeftBoundary() const;
   void setLeftBoundary(const DataPoint &left);
 
   DataPoint &getRightBoundary();
   const DataPoint &getRightBoundary() const;
   void setRightBoundary(const DataPoint &right);
   pappso_double getArea() const;
+
+
   void setArea(pappso_double area);
 
   bool containsRt(pappso::pappso_double rt) const;
 
 
-  bool
-  operator==(const TracePeak &other) const
-  {
-    return ((m_area == other.m_area) && (m_max == other.m_max) &&
-            (m_left == other.m_left) && (m_right == other.m_right));
-  };
+  bool operator==(const TracePeak &other) const;
 
-  TracePeak &
-  operator=(const TracePeak &other)
-  {
-    if(this == &other)
-      return *this;
+  TracePeak &operator=(const TracePeak &other);
 
-    m_area  = other.m_area;
-    m_max   = other.m_max;
-    m_left  = other.m_left;
-    m_right = other.m_right;
 
-    return *this;
-  }
+  protected:
+  pappso_double m_area = 0;
+  DataPoint m_max;
+  DataPoint m_left;
+  DataPoint m_right;
 };
 
 
diff --git a/src/pappsomspp/psm/features/psmfeatures.cpp b/src/pappsomspp/psm/features/psmfeatures.cpp
index ecb34f06f..fd8b4923b 100644
--- a/src/pappsomspp/psm/features/psmfeatures.cpp
+++ b/src/pappsomspp/psm/features/psmfeatures.cpp
@@ -28,24 +28,26 @@
 
 #include "psmfeatures.h"
 #include <memory>
+#include <cmath>
 
 using namespace pappso;
 
-PsmFeatures::PsmFeatures()
+PsmFeatures::PsmFeatures(PrecisionPtr ms2precision, double minimumMz)
 {
 
-  m_ms2precision = PrecisionFactory::getDaltonInstance(0.02);
+  m_ms2precision = ms2precision;
 
   m_ionList.push_back(PeptideIon::y);
   m_ionList.push_back(PeptideIon::b);
 
+
+  msp_filterKeepGreater =
+    std::make_shared<FilterResampleKeepGreater>(minimumMz);
+
   msp_filterChargeDeconvolution =
     std::make_shared<FilterChargeDeconvolution>(m_ms2precision);
   msp_filterMzExclusion = std::make_shared<FilterMzExclusion>(
     PrecisionFactory::getPrecisionPtrFractionInstance(m_ms2precision, 0.5));
-
-  // TODO compute number of matched complementary peaks having m/z compatible
-  // with the precursor
 }
 
 PsmFeatures::~PsmFeatures()
@@ -53,24 +55,80 @@ PsmFeatures::~PsmFeatures()
 }
 
 void
-PsmFeatures::setPeptideSpectrumCharge(pappso::PeptideSp peptideSp,
+PsmFeatures::setPeptideSpectrumCharge(const pappso::PeptideSp peptideSp,
                                       const MassSpectrum *p_spectrum,
                                       unsigned int parent_charge)
 {
+  m_peakIonPairs.clear();
+  msp_peptide = peptideSp;
   MassSpectrum spectrum(*p_spectrum);
-  msp_filterChargeDeconvolution.get()->filter(spectrum);
-  msp_filterMzExclusion.get()->filter(spectrum);
+  msp_filterKeepGreater.get()->filter(spectrum);
+  // msp_filterChargeDeconvolution.get()->filter(spectrum);
+  // msp_filterMzExclusion.get()->filter(spectrum);
+
+  msp_peptideSpectrumMatch =
+    std::make_shared<PeptideIsotopeSpectrumMatch>(spectrum,
+                                                  peptideSp,
+                                                  parent_charge,
+                                                  m_ms2precision,
+                                                  m_ionList,
+                                                  (unsigned int)1,
+                                                  0);
+
+  msp_peptideSpectrumMatch.get()->dropPeaksLackingMonoisotope();
+  m_spectrumSumIntensity = spectrum.sumY();
+
+
+  qDebug() << " accumulate";
+  std::vector<double> delta_list;
+
+
+  // TODO compute number of matched complementary peaks having m/z compatible
+  // with the precursor
 
-  unsigned int max_charge = parent_charge;
-  if(parent_charge > 1)
+  m_precursorTheoreticalMz   = peptideSp.get()->getMz(parent_charge);
+  m_precursorTheoreticalMass = peptideSp.get()->getMass();
+  m_parentCharge             = parent_charge;
+
+
+  findComplementIonPairs(peptideSp);
+
+
+  for(const pappso::PeakIonIsotopeMatch &peak_ion :
+      msp_peptideSpectrumMatch.get()->getPeakIonIsotopeMatchList())
     {
-      max_charge = parent_charge - 1;
+      delta_list.push_back(
+        peak_ion.getPeptideFragmentIonSp().get()->getMz(peak_ion.getCharge()) -
+        peak_ion.getPeak().x);
     }
+  pappso::pappso_double sum =
+    std::accumulate(delta_list.begin(), delta_list.end(), 0);
 
-  msp_peptideSpectrumMatch = std::make_shared<PeptideSpectrumMatch>(
-    spectrum, peptideSp, max_charge, m_ms2precision, m_ionList);
+  qDebug() << " delta_list.size()=" << delta_list.size();
+  m_matchedMzDiffMean   = 0;
+  m_matchedMzDiffMedian = 0;
+  m_matchedMzDiffSd     = 0;
+  if(delta_list.size() > 0)
+    {
+      m_matchedMzDiffMean = sum / ((pappso::pappso_double)delta_list.size());
 
-  m_spectrumSumIntensity = spectrum.sumY();
+      std::sort(delta_list.begin(), delta_list.end());
+      m_matchedMzDiffMedian = delta_list[(delta_list.size() / 2)];
+
+
+      qDebug() << " sd";
+      m_matchedMzDiffSd = 0;
+      for(pappso::pappso_double val : delta_list)
+        {
+          // sd = sd + ((val - mean) * (val - mean));
+          m_matchedMzDiffSd += std::pow((val - m_matchedMzDiffMean), 2);
+        }
+      m_matchedMzDiffSd = m_matchedMzDiffSd / delta_list.size();
+      m_matchedMzDiffSd = std::sqrt(m_matchedMzDiffSd);
+    }
+  else
+    {
+    }
 }
 
 
@@ -88,7 +146,7 @@ PsmFeatures::getIntensityOfMatchedIon(PeptideIon ion_type)
   return sum;
 }
 double
-PsmFeatures::getTotalIntensityOfMatchedIons()
+PsmFeatures::getTotalIntensityOfMatchedIons() const
 {
   double sum = 0;
   for(const PeakIonMatch &peak_ion_match : *msp_peptideSpectrumMatch.get())
@@ -99,7 +157,230 @@ PsmFeatures::getTotalIntensityOfMatchedIons()
 }
 
 double
-PsmFeatures::getTotalIntensity()
+PsmFeatures::getTotalIntensity() const
 {
   return m_spectrumSumIntensity;
 }
+
+std::size_t
+pappso::PsmFeatures::countMatchedIonComplementPairs() const
+{
+  return m_peakIonPairs.size();
+}
+
+const std::vector<
+  std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>> &
+pappso::PsmFeatures::getPeakIonPairs() const
+{
+  return m_peakIonPairs;
+}
+
+double
+pappso::PsmFeatures::getTotalIntensityOfMatchedIonComplementPairs() const
+{
+
+  double sum = 0;
+  for(auto &peak_pairs : m_peakIonPairs)
+    {
+      sum += peak_pairs.first.getPeak().y;
+      sum += peak_pairs.second.getPeak().y;
+    }
+  return sum;
+}
+
+double
+pappso::PsmFeatures::getMatchedMzDiffSd() const
+{
+  return m_matchedMzDiffSd;
+}
+
+double
+pappso::PsmFeatures::getMatchedMzDiffMean() const
+{
+  return m_matchedMzDiffMean;
+}
+
+
+std::size_t
+pappso::PsmFeatures::getNumberOfMatchedIons() const
+{
+  return msp_peptideSpectrumMatch.get()->getPeakIonIsotopeMatchList().size();
+}
+
+std::size_t
+pappso::PsmFeatures::getMaxConsecutiveIon(pappso::PeptideIon ion_type)
+{
+  std::size_t max = 0;
+  auto peak_ion_match_list =
+    msp_peptideSpectrumMatch.get()->getPeakIonIsotopeMatchList();
+
+  peak_ion_match_list.erase(
+    std::remove_if(
+      peak_ion_match_list.begin(),
+      peak_ion_match_list.end(),
+      [ion_type](const PeakIonIsotopeMatch &a) {
+        if(a.getPeptideIonType() != ion_type)
+          return true;
+        if(a.getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber() > 0)
+          return true;
+        return false;
+      }),
+    peak_ion_match_list.end());
+
+  peak_ion_match_list.sort(
+    [](const PeakIonIsotopeMatch &a, const PeakIonIsotopeMatch &b) {
+      if(a.getCharge() < b.getCharge())
+        return true;
+      if(a.getPeptideIonType() < b.getPeptideIonType())
+        return true;
+      if(a.getPeptideFragmentIonSp().get()->size() <
+         b.getPeptideFragmentIonSp().get()->size())
+        return true;
+      return false;
+    });
+
+  unsigned int charge = 0;
+  std::size_t size    = 0;
+  std::size_t count   = 0;
+  for(std::list<PeakIonIsotopeMatch>::iterator it = peak_ion_match_list.begin();
+      it != peak_ion_match_list.end();
+      it++)
+    {
+      qDebug()
+        << it->toString() << max << " " << it->getPeak().x << " "
+        << it->getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber();
+      count++;
+      if((charge != it->getCharge()) ||
+         (size != (it->getPeptideFragmentIonSp().get()->size() - 1)))
+        {
+          count  = 1;
+          charge = it->getCharge();
+        }
+      if(max < count)
+        max = count;
+
+      size = it->getPeptideFragmentIonSp().get()->size();
+    }
+
+  return max;
+}
+
+std::size_t
+pappso::PsmFeatures::getAaSequenceCoverage(pappso::PeptideIon ion_type)
+{
+  std::vector<bool> covered;
+  covered.resize(msp_peptide.get()->size(), false);
+
+  for(auto &peak : msp_peptideSpectrumMatch.get()->getPeakIonIsotopeMatchList())
+    {
+      if(peak.getPeptideIonType() == ion_type)
+        {
+          covered[peak.getPeptideFragmentIonSp().get()->size() - 1] = true;
+        }
+    }
+  return std::count(covered.begin(), covered.end(), true);
+}
+
+std::size_t
+pappso::PsmFeatures::getComplementPairsAaSequenceCoverage()
+{
+
+  std::vector<bool> covered;
+  covered.resize(msp_peptide.get()->size(), false);
+
+  for(auto &peak_pair : m_peakIonPairs)
+    {
+      std::size_t pos =
+        peak_pair.first.getPeptideFragmentIonSp().get()->size() - 1;
+      covered[pos]     = true;
+      covered[pos + 1] = true;
+    }
+  return std::count(covered.begin(), covered.end(), true);
+}
+
+
+double
+pappso::PsmFeatures::getMaxIntensityPeakIonMatch(
+  pappso::PeptideIon ion_type) const
+{
+  std::list<pappso::PeakIonIsotopeMatch> peak_ion_type =
+    msp_peptideSpectrumMatch.get()->getPeakIonIsotopeMatchList();
+
+  peak_ion_type.remove_if([ion_type](const PeakIonIsotopeMatch &a) {
+    return (a.getPeptideIonType() != ion_type);
+  });
+  auto peak_it = std::max_element(
+    peak_ion_type.begin(),
+    peak_ion_type.end(),
+    [](const PeakIonIsotopeMatch &a, const PeakIonIsotopeMatch &b) {
+      return (a.getPeak().y < b.getPeak().y);
+    });
+
+  if(peak_it == peak_ion_type.end())
+    return 0;
+  return peak_it->getPeak().y;
+}
+
+double
+pappso::PsmFeatures::getMaxIntensityMatchedIonComplementPairPrecursorMassDelta()
+  const
+{
+  auto peak_it = std::max_element(
+    m_peakIonPairs.begin(),
+    m_peakIonPairs.end(),
+    [](const std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>
+         &a,
+       const std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>
+         &b) {
+      return ((a.first.getPeak().y + a.second.getPeak().y) <
+              (b.first.getPeak().y + b.second.getPeak().y));
+    });
+
+  if(peak_it == m_peakIonPairs.end())
+    return 0;
+
+  return getIonPairPrecursorMassDelta(*peak_it);
+}
+
+double
+pappso::PsmFeatures::getIonPairPrecursorMassDelta(
+  const std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>
+    &ion_pair) const
+{
+  qDebug() << m_precursorTheoreticalMz << " " << ion_pair.first.getPeak().x
+           << " " << ion_pair.second.getPeak().x << " "
+           << ion_pair.second.getCharge() << " " << ion_pair.first.getCharge()
+           << " " << m_parentCharge;
+  double diff =
+    (m_precursorTheoreticalMass + (MHPLUS * ion_pair.first.getCharge())) /
+    ion_pair.first.getCharge();
+
+
+  return (diff - (ion_pair.first.getPeak().x + ion_pair.second.getPeak().x -
+                  ((MHPLUS * ion_pair.first.getCharge())) /
+                    ion_pair.first.getCharge()));
+}
+
+
+void
+pappso::PsmFeatures::findComplementIonPairs(const pappso::PeptideSp &peptideSp)
+{
+  std::size_t peptide_size = peptideSp.get()->size();
+  std::vector<PeakIonIsotopeMatch> ion_isotope_list(
+    msp_peptideSpectrumMatch.get()->getPeakIonIsotopeMatchList().begin(),
+    msp_peptideSpectrumMatch.get()->getPeakIonIsotopeMatchList().end());
+  for(const pappso::PeakIonIsotopeMatch &peak_ion_ext : ion_isotope_list)
+    {
+      if(peptideIonIsNter(peak_ion_ext.getPeptideIonType()))
+        {
+          auto it = findComplementIonType(ion_isotope_list.begin(),
+                                          ion_isotope_list.end(),
+                                          peak_ion_ext,
+                                          peptide_size);
+          if(it != ion_isotope_list.end())
+            { // contains the complementary ion
+              m_peakIonPairs.push_back({peak_ion_ext, *it});
+            }
+        }
+    }
+}
diff --git a/src/pappsomspp/psm/features/psmfeatures.h b/src/pappsomspp/psm/features/psmfeatures.h
index 734714524..69d6eea99 100644
--- a/src/pappsomspp/psm/features/psmfeatures.h
+++ b/src/pappsomspp/psm/features/psmfeatures.h
@@ -32,7 +32,8 @@
 #include "../../peptide/peptidefragmention.h"
 #include "../../processing/filters/filterchargedeconvolution.h"
 #include "../../processing/filters/filterexclusionmz.h"
-#include "../peptidespectrummatch.h"
+#include "../../processing/filters/filterresample.h"
+#include "../peptideisotopespectrummatch.h"
 
 namespace pappso
 {
@@ -42,33 +43,119 @@ namespace pappso
 class PMSPP_LIB_DECL PsmFeatures
 {
   public:
-  /**
-   * Default constructor
+  /** @brief compute psm features
+   * @param ms2precision precision of mass measurements for MS2 fragments
+   * @param minimumMz ignore mz values under this threshold
    */
-  PsmFeatures();
+  PsmFeatures(PrecisionPtr ms2precision, double minimumMz);
 
   /**
    * Destructor
    */
   ~PsmFeatures();
 
-  void setPeptideSpectrumCharge(pappso::PeptideSp peptideSp,
+  void setPeptideSpectrumCharge(const pappso::PeptideSp peptideSp,
                                 const MassSpectrum *p_spectrum,
                                 unsigned int parent_charge);
 
+  /** @brief get the sum of intensity of a specific ion
+   * @param ion_type ion species (y, b, ...)
+   */
   double getIntensityOfMatchedIon(PeptideIon ion_type);
-  double getTotalIntensity();
-  double getTotalIntensityOfMatchedIons();
+
+  /** @brief sum of all peak intensities (matched or not)
+   */
+  double getTotalIntensity() const;
+
+
+  /** @brief sum of matched peak intensities
+   */
+  double getTotalIntensityOfMatchedIons() const;
+
+  /** @brief number of matched ions (peaks)
+   */
+  std::size_t getNumberOfMatchedIons() const;
+
+  /** @brief count the number of matched ion complement
+   *
+   * matched ion complement are ions with a sum compatible to the precursor mass
+   *
+   */
+  std::size_t countMatchedIonComplementPairs() const;
+
+  /** @brief intensity of matched ion complement
+   */
+  double getTotalIntensityOfMatchedIonComplementPairs() const;
+
+  const std::vector<
+    std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>> &
+  getPeakIonPairs() const;
+
+
+  /** @brief get mean deviation of matched peak mass delta
+   */
+  double getMatchedMzDiffMean() const;
+
+
+  /** @brief get standard deviation of matched peak mass delta
+   */
+  double getMatchedMzDiffSd() const;
+
+
+  /** @brief get the precursor mass delta of the maximum intensity pair of
+   * complement ions
+   */
+  double getMaxIntensityMatchedIonComplementPairPrecursorMassDelta() const;
+
+
+  /** @brief get the maximum consecutive fragments of one ion type
+   * @param ion_type ion species (y, b, ...)
+   */
+  std::size_t getMaxConsecutiveIon(PeptideIon ion_type);
+
+  /** @brief number of amino acid covered by matched ions
+   */
+  std::size_t getAaSequenceCoverage(PeptideIon ion_type);
+
+
+  /** @brief number of amino acid covered by matched complement pairs of ions
+   */
+  std::size_t getComplementPairsAaSequenceCoverage();
+
+  double getMaxIntensityPeakIonMatch(PeptideIon ion_type) const;
+
+
+  double getIonPairPrecursorMassDelta(
+    const std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>
+      &ion_pair) const;
+
+
+  private:
+  void findComplementIonPairs(const pappso::PeptideSp &peptideSp);
 
   private:
   std::shared_ptr<FilterChargeDeconvolution> msp_filterChargeDeconvolution;
   std::shared_ptr<FilterMzExclusion> msp_filterMzExclusion;
+  std::shared_ptr<FilterResampleKeepGreater> msp_filterKeepGreater;
 
-  std::shared_ptr<PeptideSpectrumMatch> msp_peptideSpectrumMatch;
+  std::shared_ptr<PeptideIsotopeSpectrumMatch> msp_peptideSpectrumMatch;
+  pappso::PeptideSp msp_peptide;
 
   PrecisionPtr m_ms2precision;
   std::list<PeptideIon> m_ionList;
 
   double m_spectrumSumIntensity;
+
+  double m_precursorTheoreticalMz;
+  double m_precursorTheoreticalMass;
+  unsigned int m_parentCharge = 1;
+
+  std::vector<
+    std::pair<pappso::PeakIonIsotopeMatch, pappso::PeakIonIsotopeMatch>>
+    m_peakIonPairs;
+
+  double m_matchedMzDiffMean   = 0;
+  double m_matchedMzDiffMedian = 0;
+  double m_matchedMzDiffSd     = 0;
 };
 } // namespace pappso
diff --git a/src/pappsomspp/psm/peakionisotopematch.cpp b/src/pappsomspp/psm/peakionisotopematch.cpp
index f80c30b66..cf33efa73 100644
--- a/src/pappsomspp/psm/peakionisotopematch.cpp
+++ b/src/pappsomspp/psm/peakionisotopematch.cpp
@@ -26,6 +26,42 @@
 
 namespace pappso
 {
+std::vector<PeakIonIsotopeMatch>::iterator
+findComplementIonType(std::vector<PeakIonIsotopeMatch>::iterator begin,
+                      std::vector<PeakIonIsotopeMatch>::iterator end,
+                      const PeakIonIsotopeMatch &peak_ion,
+                      std::size_t peptide_size)
+{
+
+  return std::find_if(
+    begin,
+    end,
+    [peak_ion, peptide_size](const PeakIonIsotopeMatch &to_compare) {
+      if(to_compare.getCharge() == peak_ion.getCharge())
+        {
+          if((to_compare.getPeptideFragmentIonSp().get()->size() +
+              peak_ion.getPeptideFragmentIonSp().get()->size()) == peptide_size)
+            {
+              if(peptideIonTypeIsComplement(to_compare.getPeptideIonType(),
+                                            peak_ion.getPeptideIonType()))
+                {
+                  if(to_compare.getPeptideNaturalIsotopeAverageSp()
+                       .get()
+                       ->getIsotopeNumber() ==
+                     peak_ion.getPeptideNaturalIsotopeAverageSp()
+                       .get()
+                       ->getIsotopeNumber())
+                    {
+                      return true;
+                    }
+                }
+            }
+        }
+
+      return false;
+    });
+}
+
 
 PeakIonIsotopeMatch::PeakIonIsotopeMatch(
   const DataPoint &peak,
@@ -34,12 +70,20 @@ PeakIonIsotopeMatch::PeakIonIsotopeMatch(
   : PeakIonMatch(peak, ion_sp, naturalIsotopeAverageSp.get()->getCharge()),
     _naturalIsotopeAverageSp(naturalIsotopeAverageSp)
 {
+  qDebug();
 }
 
 PeakIonIsotopeMatch::PeakIonIsotopeMatch(const PeakIonIsotopeMatch &other)
-  : PeakIonMatch(other),
-    _naturalIsotopeAverageSp(other._naturalIsotopeAverageSp)
+  : PeakIonMatch(other)
 {
+  _naturalIsotopeAverageSp = other._naturalIsotopeAverageSp;
+}
+
+
+PeakIonIsotopeMatch::PeakIonIsotopeMatch(PeakIonIsotopeMatch &&other)
+  : PeakIonMatch(std::move(other))
+{
+  _naturalIsotopeAverageSp = other._naturalIsotopeAverageSp;
 }
 
 PeakIonIsotopeMatch::~PeakIonIsotopeMatch()
@@ -55,11 +99,21 @@ PeakIonIsotopeMatch::getPeptideNaturalIsotopeAverageSp() const
 PeakIonIsotopeMatch &
 PeakIonIsotopeMatch::operator=(const PeakIonIsotopeMatch &other)
 {
-
+  PeakIonMatch::operator   =(other);
   _naturalIsotopeAverageSp = other._naturalIsotopeAverageSp;
 
   return *this;
 }
 
 
+QString
+PeakIonIsotopeMatch::toString() const
+{
+  return QString("%1isotope%2r%3mz%4")
+    .arg(PeakIonMatch::toString())
+    .arg(_naturalIsotopeAverageSp.get()->getIsotopeNumber())
+    .arg(_naturalIsotopeAverageSp.get()->getIsotopeRank())
+    .arg(getPeak().x);
+}
+
 } // namespace pappso
diff --git a/src/pappsomspp/psm/peakionisotopematch.h b/src/pappsomspp/psm/peakionisotopematch.h
index 838c28e9b..ef79d1709 100644
--- a/src/pappsomspp/psm/peakionisotopematch.h
+++ b/src/pappsomspp/psm/peakionisotopematch.h
@@ -33,6 +33,16 @@ namespace pappso
 class PeakIonIsotopeMatch;
 typedef std::shared_ptr<const PeakIonIsotopeMatch> PeakIonIsotopeMatchCstSPtr;
 
+
+/** @brief find the first element containing the complementary ion
+ * complementary ion of y1 is b(n-1) for instance
+ * */
+PMSPP_LIB_DECL std::vector<PeakIonIsotopeMatch>::iterator
+findComplementIonType(std::vector<PeakIonIsotopeMatch>::iterator begin,
+                      std::vector<PeakIonIsotopeMatch>::iterator end,
+                      const PeakIonIsotopeMatch &peak_ion,
+                      std::size_t peptide_size);
+
 class PMSPP_LIB_DECL PeakIonIsotopeMatch : public PeakIonMatch
 {
   public:
@@ -41,6 +51,7 @@ class PMSPP_LIB_DECL PeakIonIsotopeMatch : public PeakIonMatch
     const PeptideNaturalIsotopeAverageSp &naturalIsotopeAverageSp,
     const PeptideFragmentIonSp &ion_sp);
   PeakIonIsotopeMatch(const PeakIonIsotopeMatch &other);
+  PeakIonIsotopeMatch(PeakIonIsotopeMatch &&other);
   virtual ~PeakIonIsotopeMatch();
 
   virtual const PeptideNaturalIsotopeAverageSp &
@@ -48,6 +59,7 @@ class PMSPP_LIB_DECL PeakIonIsotopeMatch : public PeakIonMatch
 
   PeakIonIsotopeMatch &operator=(const PeakIonIsotopeMatch &other);
 
+  virtual QString toString() const;
 
   private:
   PeptideNaturalIsotopeAverageSp _naturalIsotopeAverageSp;
diff --git a/src/pappsomspp/psm/peakionmatch.cpp b/src/pappsomspp/psm/peakionmatch.cpp
index 8419e6d6a..8344074ee 100644
--- a/src/pappsomspp/psm/peakionmatch.cpp
+++ b/src/pappsomspp/psm/peakionmatch.cpp
@@ -44,9 +44,63 @@ PeakIonMatch::PeakIonMatch(const PeakIonMatch &other)
 {
 }
 
+PeakIonMatch::PeakIonMatch(PeakIonMatch &&other)
+  : _peak(std::move(other._peak)),
+    _ion_sp(other._ion_sp),
+    _charge(std::move(other._charge))
+{
+}
+
 PeakIonMatch::~PeakIonMatch()
 {
 }
 
 
+PeakIonMatch &
+PeakIonMatch::operator=(const PeakIonMatch &other)
+{
+  _peak   = other._peak;
+  _ion_sp = other._ion_sp;
+  _charge = other._charge;
+
+  return *this;
+}
+
+const PeptideFragmentIonSp &
+PeakIonMatch::getPeptideFragmentIonSp() const
+{
+  return _ion_sp;
+}
+
+const DataPoint &
+PeakIonMatch::getPeak() const
+{
+  return _peak;
+}
+
+unsigned int
+PeakIonMatch::getCharge() const
+{
+  return _charge;
+}
+
+PeptideIon
+PeakIonMatch::getPeptideIonType() const
+{
+  return _ion_sp.get()->getPeptideIonType();
+}
+
+PeptideDirection
+PeakIonMatch::getPeptideIonDirection() const
+{
+  return _ion_sp.get()->getPeptideFragmentSp().get()->getPeptideIonDirection();
+}
+
+QString
+PeakIonMatch::toString() const
+{
+  return QString("%1").arg(
+    _ion_sp.get()->getCompletePeptideIonName(getCharge()));
+}
+
 } // namespace pappso
diff --git a/src/pappsomspp/psm/peakionmatch.h b/src/pappsomspp/psm/peakionmatch.h
index 287461e4d..f0f09291f 100644
--- a/src/pappsomspp/psm/peakionmatch.h
+++ b/src/pappsomspp/psm/peakionmatch.h
@@ -43,39 +43,22 @@ class PMSPP_LIB_DECL PeakIonMatch
                const PeptideFragmentIonSp &ion_sp,
                unsigned int charge);
   PeakIonMatch(const PeakIonMatch &other);
+  PeakIonMatch(PeakIonMatch &&other);
   virtual ~PeakIonMatch();
 
-  virtual const PeptideFragmentIonSp &
-  getPeptideFragmentIonSp() const
-  {
-    return _ion_sp;
-  };
+  PeakIonMatch &operator=(const PeakIonMatch &other);
 
-  const DataPoint &
-  getPeak() const
-  {
-    return _peak;
-  };
+  virtual const PeptideFragmentIonSp &getPeptideFragmentIonSp() const;
 
-  unsigned int
-  getCharge() const
-  {
-    return _charge;
-  };
+  const DataPoint &getPeak() const;
+
+  unsigned int getCharge() const;
+
+  PeptideIon getPeptideIonType() const;
+  PeptideDirection getPeptideIonDirection() const;
+
+  virtual QString toString() const;
 
-  PeptideIon
-  getPeptideIonType() const
-  {
-    return _ion_sp.get()->getPeptideIonType();
-  };
-  PeptideDirection
-  getPeptideIonDirection() const
-  {
-    return _ion_sp.get()
-      ->getPeptideFragmentSp()
-      .get()
-      ->getPeptideIonDirection();
-  };
 
   private:
   DataPoint _peak;
diff --git a/src/pappsomspp/psm/peptideisotopespectrummatch.cpp b/src/pappsomspp/psm/peptideisotopespectrummatch.cpp
index 93702f1b0..ec9dac65a 100644
--- a/src/pappsomspp/psm/peptideisotopespectrummatch.cpp
+++ b/src/pappsomspp/psm/peptideisotopespectrummatch.cpp
@@ -32,7 +32,7 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
   const PeptideSp &peptideSp,
   unsigned int parent_charge,
   PrecisionPtr precision,
-  std::list<PeptideIon> ion_type_list,
+  const std::list<PeptideIon> &ion_type_list,
   unsigned int max_isotope_number,
   [[maybe_unused]] unsigned int max_isotope_rank)
   : _precision(precision)
@@ -40,6 +40,7 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
 
   try
     {
+      _peak_ion_match_list.clear();
       qDebug() << "PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch "
                   "begin max_isotope_number="
                << max_isotope_number;
@@ -47,32 +48,26 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
       qDebug() << "PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch "
                   "peak_list spectrum.size="
                << spectrum.size();
-      std::list<DataPoint> peak_list(spectrum.begin(), spectrum.end());
-
-      qDebug() << "PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch "
-                  "ion_type_list";
+      std::vector<DataPoint> peak_list(spectrum.begin(), spectrum.end());
       for(auto ion_type : ion_type_list)
         {
           auto ion_list = fragmentIonList.getPeptideFragmentIonSp(ion_type);
-          qDebug() << "PeptideIsotopeSpectrumMatch::"
-                      "PeptideIsotopeSpectrumMatch fragmentIonList";
 
           for(unsigned int charge = 1; charge <= parent_charge; charge++)
             {
               for(auto &&ion : ion_list)
                 {
-                  unsigned int askedIsotopeRank = 1;
                   for(unsigned int isotope_number = 0;
                       isotope_number <= max_isotope_number;
                       isotope_number++)
                     {
-                      PeptideNaturalIsotopeAverage isotopeIon(ion,
-                                                              askedIsotopeRank,
-                                                              isotope_number,
-                                                              charge,
-                                                              precision);
+                      PeptideNaturalIsotopeAverage isotopeIon(
+                        ion, isotope_number, charge, precision);
+
+                      qDebug()
+                        << isotope_number << " " << isotopeIon.toString();
 
-                      std::list<DataPoint>::iterator it_peak =
+                      std::vector<DataPoint>::iterator it_peak =
                         getBestPeakIterator(peak_list, isotopeIon);
                       if(it_peak != peak_list.end())
                         {
@@ -81,13 +76,14 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
                             isotopeIon.makePeptideNaturalIsotopeAverageSp(),
                             ion));
                           peak_list.erase(it_peak);
+
+                          qDebug() << isotope_number << " "
+                                   << _peak_ion_match_list.back().toString();
                         }
                     }
                 }
             }
         }
-      qDebug()
-        << "PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch end";
     }
   catch(PappsoException &exception_pappso)
     {
@@ -120,7 +116,7 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
   PrecisionPtr precision)
   : _precision(precision)
 {
-  qDebug() << "PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch begin";
+  qDebug() << " begin";
   if(v_peptideIsotopeList.size() != v_peptideIonList.size())
     {
       throw PappsoException(
@@ -132,11 +128,11 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
 
   auto isotopeIt = v_peptideIsotopeList.begin();
   auto ionIt     = v_peptideIonList.begin();
-  std::list<DataPoint> peak_list(spectrum.begin(), spectrum.end());
+  std::vector<DataPoint> peak_list(spectrum.begin(), spectrum.end());
 
   while(isotopeIt != v_peptideIsotopeList.end())
     {
-      std::list<DataPoint>::iterator it_peak =
+      std::vector<DataPoint>::iterator it_peak =
         getBestPeakIterator(peak_list, *(isotopeIt->get()));
       if(it_peak != peak_list.end())
         {
@@ -147,7 +143,7 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
       isotopeIt++;
       ionIt++;
     }
-  qDebug() << "PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch end";
+  qDebug() << " end";
 }
 
 
@@ -156,6 +152,7 @@ PeptideIsotopeSpectrumMatch::PeptideIsotopeSpectrumMatch(
   : _precision(other._precision),
     _peak_ion_match_list(other._peak_ion_match_list)
 {
+  qDebug();
 }
 
 PeptideIsotopeSpectrumMatch::~PeptideIsotopeSpectrumMatch()
@@ -163,15 +160,15 @@ PeptideIsotopeSpectrumMatch::~PeptideIsotopeSpectrumMatch()
 }
 
 
-std::list<DataPoint>::iterator
+std::vector<DataPoint>::iterator
 PeptideIsotopeSpectrumMatch::getBestPeakIterator(
-  std::list<DataPoint> &peak_list,
+  std::vector<DataPoint> &peak_list,
   const PeptideNaturalIsotopeAverage &ion) const
 {
   // qDebug();
-  std::list<DataPoint>::iterator itpeak   = peak_list.begin();
-  std::list<DataPoint>::iterator itend    = peak_list.end();
-  std::list<DataPoint>::iterator itselect = peak_list.end();
+  std::vector<DataPoint>::iterator itpeak   = peak_list.begin();
+  std::vector<DataPoint>::iterator itend    = peak_list.end();
+  std::vector<DataPoint>::iterator itselect = peak_list.end();
 
   pappso_double best_intensity = 0;
 
@@ -197,5 +194,68 @@ PeptideIsotopeSpectrumMatch::getPeakIonIsotopeMatchList() const
   return _peak_ion_match_list;
 }
 
+std::size_t
+PeptideIsotopeSpectrumMatch::size() const
+{
+  return _peak_ion_match_list.size();
+}
+PeptideIsotopeSpectrumMatch::const_iterator
+PeptideIsotopeSpectrumMatch::begin() const
+{
+  return _peak_ion_match_list.begin();
+}
+PeptideIsotopeSpectrumMatch::const_iterator
+PeptideIsotopeSpectrumMatch::end() const
+{
+  return _peak_ion_match_list.end();
+}
 
+void
+PeptideIsotopeSpectrumMatch::dropPeaksLackingMonoisotope()
+{
+  qDebug();
+  _peak_ion_match_list.sort(
+    [](const PeakIonIsotopeMatch &a, const PeakIonIsotopeMatch &b) {
+      if(a.getPeptideIonType() < b.getPeptideIonType())
+        return true;
+      if(a.getPeptideFragmentIonSp().get()->size() <
+         b.getPeptideFragmentIonSp().get()->size())
+        return true;
+      if(a.getCharge() < b.getCharge())
+        return true;
+      if(a.getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber() <
+         b.getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber())
+        return true;
+      return false;
+    });
+  PeptideIon ion_type      = PeptideIon::b;
+  std::size_t nserie       = 0;
+  std::size_t isotopeserie = 0;
+  unsigned int charge      = 0;
+  for(std::list<PeakIonIsotopeMatch>::iterator it =
+        _peak_ion_match_list.begin();
+      it != _peak_ion_match_list.end();
+      it++)
+    {
+      if((nserie != it->getPeptideFragmentIonSp().get()->size()) ||
+         (ion_type != it->getPeptideIonType()) || (charge != it->getCharge()))
+        {
+          ion_type     = it->getPeptideIonType();
+          isotopeserie = 0;
+          nserie       = it->getPeptideFragmentIonSp().get()->size();
+          charge       = it->getCharge();
+        }
+      if(isotopeserie <=
+         it->getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber())
+        {
+          isotopeserie =
+            it->getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber();
+        }
+      else
+        {
+          it = _peak_ion_match_list.erase(it);
+        }
+    }
+  qDebug();
+}
 } // namespace pappso
diff --git a/src/pappsomspp/psm/peptideisotopespectrummatch.h b/src/pappsomspp/psm/peptideisotopespectrummatch.h
index 6c2297feb..8a627a817 100644
--- a/src/pappsomspp/psm/peptideisotopespectrummatch.h
+++ b/src/pappsomspp/psm/peptideisotopespectrummatch.h
@@ -53,7 +53,7 @@ class PMSPP_LIB_DECL PeptideIsotopeSpectrumMatch
                               const PeptideSp &peptide_sp,
                               unsigned int parent_charge,
                               PrecisionPtr precision,
-                              std::list<PeptideIon> ion_list,
+                              const std::list<PeptideIon> &ion_type_list,
                               unsigned int max_isotope_number,
                               unsigned int max_isotope_rank);
   PeptideIsotopeSpectrumMatch(
@@ -63,32 +63,22 @@ class PMSPP_LIB_DECL PeptideIsotopeSpectrumMatch
     PrecisionPtr precision);
   PeptideIsotopeSpectrumMatch(const PeptideIsotopeSpectrumMatch &other);
 
-  ~PeptideIsotopeSpectrumMatch();
+  virtual ~PeptideIsotopeSpectrumMatch();
 
   const std::list<PeakIonIsotopeMatch> &getPeakIonIsotopeMatchList() const;
 
 
   typedef std::list<PeakIonIsotopeMatch>::const_iterator const_iterator;
 
-  unsigned int
-  size() const
-  {
-    return _peak_ion_match_list.size();
-  }
-  const_iterator
-  begin() const
-  {
-    return _peak_ion_match_list.begin();
-  }
-  const_iterator
-  end() const
-  {
-    return _peak_ion_match_list.end();
-  }
+  std::size_t size() const;
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  void dropPeaksLackingMonoisotope();
 
   private:
-  virtual std::list<DataPoint>::iterator
-  getBestPeakIterator(std::list<DataPoint> &peak_list,
+  virtual std::vector<DataPoint>::iterator
+  getBestPeakIterator(std::vector<DataPoint> &peak_list,
                       const PeptideNaturalIsotopeAverage &ion) const;
 
   PrecisionPtr _precision;
diff --git a/src/pappsomspp/psm/peptidespectrummatch.h b/src/pappsomspp/psm/peptidespectrummatch.h
index 59ee54ea1..88ad0c261 100644
--- a/src/pappsomspp/psm/peptidespectrummatch.h
+++ b/src/pappsomspp/psm/peptidespectrummatch.h
@@ -61,7 +61,7 @@ class PMSPP_LIB_DECL PeptideSpectrumMatch
     PrecisionPtr precision);
   PeptideSpectrumMatch(const PeptideSpectrumMatch &other);
 
-  ~PeptideSpectrumMatch();
+  virtual ~PeptideSpectrumMatch();
 
   bool contains(const PeptideFragmentIon *peptideFragmentIonSp,
                 unsigned int z) const;
diff --git a/src/pappsomspp/psm/xtandem/xtandemhyperscore.cpp b/src/pappsomspp/psm/xtandem/xtandemhyperscore.cpp
index 743e723dd..2f0072887 100644
--- a/src/pappsomspp/psm/xtandem/xtandemhyperscore.cpp
+++ b/src/pappsomspp/psm/xtandem/xtandemhyperscore.cpp
@@ -262,9 +262,11 @@ XtandemHyperscore::getHyperscore() const
 {
   try
     {
-      qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__
-               << " _proto_hyperscore=" << _proto_hyperscore;
-      return (log10(_proto_hyperscore) * 4);
+      qDebug() << " _proto_hyperscore=" << _proto_hyperscore;
+      double hyperscore = (log10(_proto_hyperscore) * 4);
+      if(hyperscore < 0)
+        return 0;
+      return hyperscore;
     }
   catch(PappsoException &exception_pappso)
     {
diff --git a/src/pappsomspp/trace/trace.cpp b/src/pappsomspp/trace/trace.cpp
index 8ae85b2fb..8b2352b6f 100644
--- a/src/pappsomspp/trace/trace.cpp
+++ b/src/pappsomspp/trace/trace.cpp
@@ -323,6 +323,35 @@ areaTrace(std::vector<DataPoint>::const_iterator begin,
 }
 
 
+double
+areaTraceMinusBase(std::vector<DataPoint>::const_iterator begin,
+                   std::vector<DataPoint>::const_iterator end)
+{
+
+  if(begin == end)
+    return 0;
+  auto previous = begin;
+  auto next     = begin + 1;
+  auto last     = next;
+  double area   = 0;
+  while(next != end)
+    {
+      last = next;
+      area += ((next->x - previous->x) * (previous->y + next->y)) / (double)2;
+      previous++;
+      next++;
+    }
+  if(area > 0)
+    {
+      // remove base peak area
+      area -= (((last->y + begin->y) * (last->x - begin->x)) / 2);
+      if(area < 0)
+        return 0;
+    }
+  return area;
+}
+
+
 Trace
 flooredLocalMaxima(std::vector<DataPoint>::const_iterator begin,
                    std::vector<DataPoint>::const_iterator end,
diff --git a/src/pappsomspp/trace/trace.h b/src/pappsomspp/trace/trace.h
index 76c3f4476..7b34b8876 100644
--- a/src/pappsomspp/trace/trace.h
+++ b/src/pappsomspp/trace/trace.h
@@ -126,7 +126,6 @@ quantileYTrace(std::vector<DataPoint>::const_iterator begin,
 PMSPP_LIB_DECL double areaTrace(std::vector<DataPoint>::const_iterator begin,
                                 std::vector<DataPoint>::const_iterator end);
 
-
 PMSPP_LIB_DECL Trace
 flooredLocalMaxima(std::vector<DataPoint>::const_iterator begin,
                    std::vector<DataPoint>::const_iterator end,
@@ -210,14 +209,17 @@ class PMSPP_LIB_DECL Trace : public std::vector<DataPoint>
   virtual Trace &filter(const FilterInterface &filter) final;
   QString toString() const;
 
+  /** @brief find datapoint with exactly x value
+   */
+  std::vector<DataPoint>::const_iterator
+  dataPointCstIteratorWithX(pappso_double value) const;
+
   protected:
   //! Return a reference to the DataPoint instance that has its y member equal
   //! to \p value.
   // const DataPoint &dataPointWithX(pappso_double value) const;
   std::size_t dataPointIndexWithX(pappso_double value) const;
   std::vector<DataPoint>::iterator dataPointIteratorWithX(pappso_double value);
-  std::vector<DataPoint>::const_iterator
-  dataPointCstIteratorWithX(pappso_double value) const;
 };
 
 
diff --git a/src/pappsomspp/vendors/tims/timsframebase.cpp b/src/pappsomspp/vendors/tims/timsframebase.cpp
index 833706352..4754caa94 100644
--- a/src/pappsomspp/vendors/tims/timsframebase.cpp
+++ b/src/pappsomspp/vendors/tims/timsframebase.cpp
@@ -492,4 +492,69 @@ TimsFrameBase::getScanIntensities(std::size_t scanNum) const
       "ERROR unable to getScanIntensities in TimsFrameBase for scan number %1")
       .arg(scanNum));
 }
+
+Trace
+TimsFrameBase::getIonMobilityTraceByMzIndexRange(
+  std::size_t mz_index_lower_bound,
+  std::size_t mz_index_upper_bound,
+  XicExtractMethod method) const
+{
+  Trace im_trace;
+  DataPoint data_point;
+  for(quint32 i = 0; i < m_scanNumber; i++)
+    {
+      data_point.x = i;
+      data_point.y = 0;
+      qDebug() << "m_scanNumber=" << m_scanNumber << " i=" << i;
+      std::vector<quint32> index_list = getScanIndexList(i);
+      auto it_lower                   = std::find_if(index_list.begin(),
+                                   index_list.end(),
+                                   [mz_index_lower_bound](quint32 to_compare) {
+                                     if(to_compare < mz_index_lower_bound)
+                                       {
+                                         return false;
+                                       }
+                                     return true;
+                                   });
+
+
+      if(it_lower == index_list.end())
+        {
+        }
+      else
+        {
+
+
+          auto it_upper =
+            std::find_if(index_list.begin(),
+                         index_list.end(),
+                         [mz_index_upper_bound](quint32 to_compare) {
+                           if(mz_index_upper_bound >= to_compare)
+                             {
+                               return false;
+                             }
+                           return true;
+                         });
+          std::vector<quint32> intensity_list = getScanIntensities(i);
+          for(int j = std::distance(index_list.begin(), it_lower);
+              j < std::distance(index_list.begin(), it_upper);
+              j++)
+            {
+              if(method == XicExtractMethod::sum)
+                {
+                  data_point.y += intensity_list[j];
+                }
+              else
+                {
+                  data_point.y =
+                    std::max((double)intensity_list[j], data_point.y);
+                }
+            }
+        }
+      im_trace.push_back(data_point);
+    }
+  qDebug();
+  return im_trace;
+}
+// namespace pappso
 } // namespace pappso
diff --git a/src/pappsomspp/vendors/tims/timsframebase.h b/src/pappsomspp/vendors/tims/timsframebase.h
index 36e8158a4..ba9476ca5 100644
--- a/src/pappsomspp/vendors/tims/timsframebase.h
+++ b/src/pappsomspp/vendors/tims/timsframebase.h
@@ -213,6 +213,17 @@ class TimsFrameBase
    */
   virtual std::vector<quint32> getScanIntensities(std::size_t scanNum) const;
 
+  /** @brief get a mobility trace cumulating intensities inside the given mass
+   * index range
+   * @param mz_index_lower_bound raw mass index lower bound
+   * @param mz_index_upper_bound raw mass index upper bound
+   * @param method max or sum intensities
+   */
+  virtual Trace
+  getIonMobilityTraceByMzIndexRange(std::size_t mz_index_lower_bound,
+                                    std::size_t mz_index_upper_bound,
+                                    XicExtractMethod method) const;
+
 
   protected:
   /** @brief total number of scans contained in this frame
diff --git a/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.cpp b/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.cpp
index a2dfd20c9..2297de9c5 100644
--- a/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.cpp
+++ b/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.cpp
@@ -202,7 +202,9 @@ MassSpectrumWidget::peptideAnnotate()
                                                 _max_isotope_number,
                                                 _max_isotope_rank);
 
-          _peak_ion_isotope_match_list = psm_match.getPeakIonIsotopeMatchList();
+          _peak_ion_isotope_match_list = std::list<PeakIonIsotopeMatch>(
+            psm_match.getPeakIonIsotopeMatchList().begin(),
+            psm_match.getPeakIonIsotopeMatchList().end());
         }
       else
         {
@@ -318,11 +320,17 @@ MassSpectrumWidget::plot()
     }
   else
     {
+      qDebug();
       _peak_ion_isotope_match_list.sort(
         [](const PeakIonIsotopeMatch &a, const PeakIonIsotopeMatch &b) {
-          return a.getPeak().y > b.getPeak().y;
+          qDebug() << a.getPeak().y << " > ";
+          qDebug() << b.getPeak().y << " . ";
+          return (a.getPeak().y > b.getPeak().y);
         });
+      qDebug();
       unsigned int i = 0;
+
+      qDebug();
       for(const PeakIonIsotopeMatch &peak_ion_match :
           _peak_ion_isotope_match_list)
         {
@@ -358,6 +366,7 @@ MassSpectrumWidget::plot()
         }
     }
 
+  qDebug();
   _custom_plot->replot();
   qDebug();
 }
diff --git a/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.h b/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.h
index 29b6528ce..112beb401 100644
--- a/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.h
+++ b/src/pappsomspp/widget/massspectrumwidget/massspectrumwidget.h
@@ -1,5 +1,5 @@
 /**
- * \file pappsomspp/widget/spectrumwidget/massspectrumwidget.h
+ * \file pappsomspp/widget/massspectrumwidget/massspectrumwidget.h
  * \date 22/12/2017
  * \author Olivier Langella
  * \brief plot a sectrum and annotate with peptide
diff --git a/src/pappsomspp/widget/massspectrumwidget/qcpspectrum.cpp b/src/pappsomspp/widget/massspectrumwidget/qcpspectrum.cpp
index 12c82a750..00fea9913 100644
--- a/src/pappsomspp/widget/massspectrumwidget/qcpspectrum.cpp
+++ b/src/pappsomspp/widget/massspectrumwidget/qcpspectrum.cpp
@@ -300,8 +300,8 @@ QCPSpectrum::mousePressEvent(QMouseEvent *event)
            << xAxis->pixelToCoord(event->x()) << " "
            << yAxis->pixelToCoord(event->y());*/
   _click = true;
-  _old_x = event->x();
-  _old_y = yAxis->pixelToCoord(event->y());
+  _old_x = event->position().x();
+  _old_y = yAxis->pixelToCoord(event->position().y());
   if(_old_y < 0)
     _old_y = 0;
   /* qDebug() << "QCPSpectrum::mousePressEvent end";*/
@@ -318,13 +318,13 @@ QCPSpectrum::mouseReleaseEvent(QMouseEvent *event [[maybe_unused]])
 void
 QCPSpectrum::mouseMoveEvent(QMouseEvent *event)
 {
-  pappso::pappso_double x = xAxis->pixelToCoord(event->x());
+  pappso::pappso_double x = xAxis->pixelToCoord(event->position().x());
   if(_click)
     {
       /* qDebug() << "QCPSpectrum::mouseMoveEvent begin "
                 << xAxis->pixelToCoord(event->x()) << " "
                 << yAxis->pixelToCoord(event->y());*/
-      pappso::pappso_double y = yAxis->pixelToCoord(event->y());
+      pappso::pappso_double y = yAxis->pixelToCoord(event->position().y());
       if(y < 0)
         {
           y = 0;
@@ -339,9 +339,9 @@ QCPSpectrum::mouseMoveEvent(QMouseEvent *event)
       else
         {
           this->xAxis->moveRange(xAxis->pixelToCoord(_old_x) -
-                                 xAxis->pixelToCoord(event->x()));
+                                 xAxis->pixelToCoord(event->position().x()));
         }
-      _old_x = event->x();
+      _old_x = event->position().x();
       _old_y = y;
       replot();
       // qDebug() << "QCPSpectrum::mouseMoveEvent end";
diff --git a/src/pappsomspp/widget/plotwidget/basetraceplotwidget.cpp b/src/pappsomspp/widget/plotwidget/basetraceplotwidget.cpp
index 772ea7951..a8be4eaf2 100644
--- a/src/pappsomspp/widget/plotwidget/basetraceplotwidget.cpp
+++ b/src/pappsomspp/widget/plotwidget/basetraceplotwidget.cpp
@@ -132,7 +132,6 @@ BaseTracePlotWidget::setGraphData(QCPGraph *graph_p,
   QVector<double> key_qvector;
   QVector<double> value_qvector;
 
-#pragma GCC warning "Filippo Rusconi: Please check if the bug was fixed in Qt"
 
 #if 0
                   // Now replace the graph's data. Note that the data are
@@ -204,8 +203,6 @@ BaseTracePlotWidget::addTrace(const pappso::Trace &trace, const QColor &color)
   QVector<double> key_qvector;
   QVector<double> value_qvector;
 
-#pragma GCC warning "Filippo Rusconi: Please check if the bug was fixed in Qt"
-
 #if 0
                   // Now replace the graph's data. Note that the data are
                   // inherently sorted (true below).
diff --git a/src/pappsomspp/widget/xicwidget/qcpxic.cpp b/src/pappsomspp/widget/xicwidget/qcpxic.cpp
index 387b8d34f..86e9b4510 100644
--- a/src/pappsomspp/widget/xicwidget/qcpxic.cpp
+++ b/src/pappsomspp/widget/xicwidget/qcpxic.cpp
@@ -103,13 +103,11 @@ QCPXic::keyReleaseEvent(QKeyEvent *event)
 void
 QCPXic::mousePressEvent(QMouseEvent *event)
 {
-  qDebug() << "QCPXic::mousePressEvent begin "
-           << xAxis->pixelToCoord(event->x()) << " "
-           << yAxis->pixelToCoord(event->y());
+  qDebug() << " begin ";
   _mouse_move = false;
   _click      = true;
-  _old_x      = event->x();
-  _old_y      = yAxis->pixelToCoord(event->y());
+  _old_x      = event->position().x();
+  _old_y      = yAxis->pixelToCoord(event->position().y());
   if(_old_y < 0)
     {
       _old_y = 0;
@@ -123,8 +121,8 @@ void
 QCPXic::mouseReleaseEvent(QMouseEvent *event)
 {
   qDebug() << "QCPXic::mouseReleaseEvent begin "
-           << xAxis->pixelToCoord(event->x()) << " "
-           << yAxis->pixelToCoord(event->y());
+           << xAxis->pixelToCoord(event->position().x()) << " "
+           << yAxis->pixelToCoord(event->position().y());
   _click = false;
   if(_mouse_move)
     {
@@ -140,13 +138,13 @@ void
 QCPXic::mouseMoveEvent(QMouseEvent *event)
 {
   _mouse_move             = true;
-  pappso::pappso_double x = xAxis->pixelToCoord(event->x());
+  pappso::pappso_double x = xAxis->pixelToCoord(event->position().x());
   if(_click)
     {
       qDebug() << "QCPXic::mouseMoveEvent begin "
-               << xAxis->pixelToCoord(event->x()) << " "
-               << yAxis->pixelToCoord(event->y());
-      pappso::pappso_double y = yAxis->pixelToCoord(event->y());
+               << xAxis->pixelToCoord(event->position().x()) << " "
+               << yAxis->pixelToCoord(event->position().y());
+      pappso::pappso_double y = yAxis->pixelToCoord(event->position().y());
       if(y < 0)
         {
           y = 0;
@@ -161,9 +159,9 @@ QCPXic::mouseMoveEvent(QMouseEvent *event)
       else
         {
           this->xAxis->moveRange(xAxis->pixelToCoord(_old_x) -
-                                 xAxis->pixelToCoord(event->x()));
+                                 xAxis->pixelToCoord(event->position().x()));
         }
-      _old_x = event->x();
+      _old_x = event->position().x();
       _old_y = y;
       replot();
       qDebug() << "QCPXic::mouseMoveEvent end";
@@ -179,7 +177,7 @@ QCPXic::mouseMoveEvent(QMouseEvent *event)
     }
 }
 
-void
+QCPGraph *
 QCPXic::addXicP(const Xic *xic_p)
 {
 
@@ -207,6 +205,8 @@ QCPXic::addXicP(const Xic *xic_p)
       if(_intensity_range.upper < xic_p->maxYDataPoint().y)
         _intensity_range.upper = xic_p->maxYDataPoint().y;
     }
+
+  return graph_xic;
 }
 
 
diff --git a/src/pappsomspp/widget/xicwidget/qcpxic.h b/src/pappsomspp/widget/xicwidget/qcpxic.h
index a585ecfd7..a0be5db48 100644
--- a/src/pappsomspp/widget/xicwidget/qcpxic.h
+++ b/src/pappsomspp/widget/xicwidget/qcpxic.h
@@ -49,7 +49,7 @@ class QCPXic : public QCustomPlot
   protected:
   void clear();
   void rescale();
-  void addXicP(const Xic *xic_p);
+  QCPGraph *addXicP(const Xic *xic_p);
   void addMsMsEvent(const Xic *xic_p, pappso::pappso_double rt);
   void
   addXicPeakList(const Xic *xic_p,
diff --git a/src/pappsomspp/widget/xicwidget/xicwidget.cpp b/src/pappsomspp/widget/xicwidget/xicwidget.cpp
index 538ba9dd7..4593c1a3f 100644
--- a/src/pappsomspp/widget/xicwidget/xicwidget.cpp
+++ b/src/pappsomspp/widget/xicwidget/xicwidget.cpp
@@ -63,11 +63,11 @@ XicWidget::addMsMsEvent(const Xic *xic_p, pappso::pappso_double rt)
   _qcp_xic->addMsMsEvent(xic_p, rt);
   _map_xic_msms_event[xic_p] = rt;
 }
-void
-XicWidget::addXicSp(XicCstSPtr &xic_sp)
+QCPGraph *
+XicWidget::addXicSp(XicCstSPtr xic_sp)
 {
   _xic_sp_list.push_back(xic_sp);
-  _qcp_xic->addXicP(xic_sp.get());
+  return _qcp_xic->addXicP(xic_sp.get());
 }
 
 const QString &
diff --git a/src/pappsomspp/widget/xicwidget/xicwidget.h b/src/pappsomspp/widget/xicwidget/xicwidget.h
index 5038cc15a..fc0aa83c5 100644
--- a/src/pappsomspp/widget/xicwidget/xicwidget.h
+++ b/src/pappsomspp/widget/xicwidget/xicwidget.h
@@ -52,7 +52,7 @@ class PMSPP_LIB_DECL XicWidget : public GraphicDeviceWidget
   ~XicWidget();
 
 
-  void addXicSp(XicCstSPtr &xic_sp);
+  QCPGraph *addXicSp(XicCstSPtr xic_sp);
   void addMsMsEvent(const Xic *xic_p, pappso::pappso_double rt);
   void
   addXicPeakList(const Xic *xic_p,
diff --git a/src/pappsomspp/xic/xic.cpp b/src/pappsomspp/xic/xic.cpp
index c3cfcd874..98fb683b7 100644
--- a/src/pappsomspp/xic/xic.cpp
+++ b/src/pappsomspp/xic/xic.cpp
@@ -40,6 +40,10 @@ Xic::Xic()
   qDebug() << "Xic::Xic end";
 }
 
+Xic::Xic(const Trace &other) : Trace(other)
+{
+}
+
 Xic::~Xic()
 {
 }
diff --git a/src/pappsomspp/xic/xic.h b/src/pappsomspp/xic/xic.h
index 1b43e7519..34298c22c 100644
--- a/src/pappsomspp/xic/xic.h
+++ b/src/pappsomspp/xic/xic.h
@@ -44,6 +44,7 @@ class PMSPP_LIB_DECL Xic : public Trace
 {
   public:
   Xic();
+  Xic(const Trace & other);
   virtual ~Xic();
 
 
diff --git a/src/pappsomspp/xicextractor/msrunxicextractorfactory.cpp b/src/pappsomspp/xicextractor/msrunxicextractorfactory.cpp
index 5b15543ff..73d92ae86 100644
--- a/src/pappsomspp/xicextractor/msrunxicextractorfactory.cpp
+++ b/src/pappsomspp/xicextractor/msrunxicextractorfactory.cpp
@@ -72,8 +72,6 @@ MsRunXicExtractorInterfaceSp
 MsRunXicExtractorFactory::buildMsRunXicExtractorSp(
   MsRunReaderSPtr &msrun_reader) const
 {
-#if 0
-// Remove this section because it cripples my work on Qt6 build
 
   pappso::TimsMsRunReaderMs2 *tims2_reader =
     dynamic_cast<pappso::TimsMsRunReaderMs2 *>(msrun_reader.get());
@@ -116,7 +114,6 @@ MsRunXicExtractorFactory::buildMsRunXicExtractorSp(
       return (msrun_xic_extractor_sp);
     }
   return nullptr;
-#endif
 }
 
 
diff --git a/tests/test_psm.cpp b/tests/test_psm.cpp
index 2150cd2b3..e495e4ac5 100644
--- a/tests/test_psm.cpp
+++ b/tests/test_psm.cpp
@@ -27,11 +27,14 @@
  ******************************************************************************/
 
 // make test ARGS="-V -I 18,18"
+// ./tests/catch2-only-tests [psm] -s
+// ./tests/catch2-only-tests [psmfeature] -s
+#include <algorithm>
 
-#define CATCH_CONFIG_MAIN
 #include <catch2/catch.hpp>
 #include <pappsomspp/mzrange.h>
 #include <pappsomspp/psm/peptidespectrummatch.h>
+#include <pappsomspp/psm/features/psmfeatures.h>
 #include <iostream>
 #include <iomanip>
 #include <set>
@@ -83,5 +86,242 @@ TEST_CASE("psm test suite.", "[psm]")
       spectrum_simple, peptide_sp, 2, precision, ion_list);
     test_count = psmb.countTotalMatchedIons();
     REQUIRE(test_count == 0);
+
+
+    precision = PrecisionFactory::getDaltonInstance(0.02);
+    PeptideIsotopeSpectrumMatch psm_iso(
+      spectrum_simple, peptide_sp, 2, precision, ion_list, 2, 0);
+
+    std::list<PeakIonIsotopeMatch> peak_ion_isotope_match_list =
+      psm_iso.getPeakIonIsotopeMatchList();
+
+    for(auto peak : peak_ion_isotope_match_list)
+      {
+        qDebug() << peak.toString() << " "
+                 << peak.getPeptideNaturalIsotopeAverageSp().get();
+      }
+    REQUIRE(peak_ion_isotope_match_list.size() == 19);
+
+    psm_iso.dropPeaksLackingMonoisotope();
+    peak_ion_isotope_match_list = psm_iso.getPeakIonIsotopeMatchList();
+    for(auto peak : peak_ion_isotope_match_list)
+      {
+        qDebug() << peak.toString() << " "
+                 << peak.getPeptideNaturalIsotopeAverageSp().get();
+      }
+    REQUIRE(peak_ion_isotope_match_list.size() == 19);
+
+    qDebug() << peak_ion_isotope_match_list.size();
+    peak_ion_isotope_match_list.sort(
+      [](const PeakIonIsotopeMatch &a, const PeakIonIsotopeMatch &b) {
+        qDebug() << a.getPeak().y << " > ";
+        qDebug() << b.getPeak().y << " . ";
+        return (a.getPeak().y > b.getPeak().y);
+      });
+
+
+    spectrum_simple = readMgf(
+      QString(CMAKE_SOURCE_DIR).append("/tests/data/peaklist_15046.mgf"));
+
+    peptide_sp = Peptide("AIADGSLLDLLR").makePeptideSp();
+
+
+    precision = PrecisionFactory::getDaltonInstance(0.02);
+    qDebug();
+    PeptideIsotopeSpectrumMatch psm_iso_check(
+      spectrum_simple, peptide_sp, 2, precision, ion_list, 2, 0);
+
+    qDebug();
+    peak_ion_isotope_match_list = psm_iso_check.getPeakIonIsotopeMatchList();
+
+    REQUIRE(peak_ion_isotope_match_list.size() == 39);
+    qDebug();
+
+    for(auto &peak : peak_ion_isotope_match_list)
+      {
+        qDebug() << peak.toString() << " "
+                 << peak.getPeptideNaturalIsotopeAverageSp().get();
+      }
+
+
+    peak_ion_isotope_match_list.sort(
+      [](const PeakIonIsotopeMatch &a, const PeakIonIsotopeMatch &b) {
+        if(a.getPeptideIonType() < b.getPeptideIonType())
+          return true;
+        if(a.getPeptideFragmentIonSp().get()->size() <
+           b.getPeptideFragmentIonSp().get()->size())
+          return true;
+        if(a.getCharge() < b.getCharge())
+          return true;
+        if(a.getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber() <
+           b.getPeptideNaturalIsotopeAverageSp().get()->getIsotopeNumber())
+          return true;
+        return false;
+      });
+
+
+    auto it = peak_ion_isotope_match_list.begin();
+    REQUIRE(it->toString().toStdString() == "b2+isotope0r1mz185.128");
+    it++;
+    REQUIRE(it->toString().toStdString() == "b3+isotope0r1mz256.165");
+
+    for(auto peak : peak_ion_isotope_match_list)
+      {
+        qDebug() << peak.toString() << " "
+                 << peak.getPeptideNaturalIsotopeAverageSp().get();
+      }
+
+    psm_iso_check.dropPeaksLackingMonoisotope();
+    peak_ion_isotope_match_list = psm_iso_check.getPeakIonIsotopeMatchList();
+
+    for(auto peak : peak_ion_isotope_match_list)
+      {
+        qDebug() << peak.toString() << " "
+                 << peak.getPeptideNaturalIsotopeAverageSp().get();
+      }
+    REQUIRE(peak_ion_isotope_match_list.size() == 39);
+  }
+}
+
+
+TEST_CASE("psm features test suite.", "[psmfeature]")
+{
+  // Set the debugging message formatting pattern.
+  qSetMessagePattern(QString("%{file}@%{line}, %{function}(): %{message}"));
+
+  SECTION("..:: readMgf ::..", "[psm]")
+  {
+    cout << std::endl << "..:: readMgf ::.." << std::endl;
+    // bool refine_spectrum_synthesis = false;
+
+    MassSpectrum spectrum_simple =
+      readMgf(QString(CMAKE_SOURCE_DIR).append("/tests/data/scan_2016.mgf"));
+    //.applyCutOff(150).takeNmostIntense(100).applyDynamicRange(100);
+
+
+    Peptide peptide("EDKPQPPPEGR");
+    PeptideSp peptide_sp(peptide.makePeptideSp());
+    // peptide_sp.get()->addAaModification(AaModification::getInstance("MOD:00397"),
+    // 0);
+
+    PsmFeatures features(PrecisionFactory::getDaltonInstance(0.02), 150);
+
+    features.setPeptideSpectrumCharge(peptide_sp, &spectrum_simple, 3);
+
+    REQUIRE(features.getTotalIntensity() == Approx(248641.8659667977));
+    REQUIRE(features.getIntensityOfMatchedIon(PeptideIon::b) ==
+            Approx(1751.5864257813).epsilon(0.001));
+    REQUIRE(features.getIntensityOfMatchedIon(PeptideIon::y) ==
+            Approx(57112.2947998047).epsilon(0.001));
+
+
+    REQUIRE(features.countMatchedIonComplementPairs() == 0);
+
+
+    /*
+    <group id="15968" mh="1275.731419" z="2" rt="PT2843.58S" expect="1.7e-04"
+  label="GRMZM5G815453_P01 P00874 Ribulose bisphosphate carboxylase large chain
+  Precursor..." type="model" sumI="6.08" maxI="111642" fI="1116.42" act="0" >
+  <protein expect="-191.8" id="15968.1" uid="49237" label="GRMZM5G815453_P01
+  P00874 Ribulose bisphosphate carboxylase large chain Precursor..." sumI="8.97"
+  > <note label="description">GRMZM5G815453_P01 P00874 Ribulose bisphosphate
+  carboxylase large chain Precursor (RuBisCO large subunit)(EC 4.1.1.39)
+  seq=translation; coord=Pt:56824..58323:1; parent_transcript=GRMZM5G815453_T01;
+  parent_gene=GRMZM5G815453</note> <file type="peptide"
+  URL="/gorgone/pappso/formation/TD/Database/Genome_Z_mays_5a.fasta"/> <peptide
+  start="1" end="483"> <domain id="15968.1.1" start="347" end="357"
+  expect="1.7e-04" mh="1275.7311" delta="0.0003" hyperscore="29.0"
+  nextscore="10.8" y_score="10.5" y_ions="8" b_score="3.8" b_ions="1" pre="EGER"
+  post="DDFI" seq="EITLGFVDLLR" missed_cleavages="0">
+  </domain>
+  </peptide>
+  */
+    spectrum_simple =
+      readMgf(QString(CMAKE_SOURCE_DIR).append("/tests/data/scan_15968.mgf"));
+
+
+    peptide_sp = Peptide("EITLGFVDLLR").makePeptideSp();
+
+    features.setPeptideSpectrumCharge(peptide_sp, &spectrum_simple, 2);
+
+
+    REQUIRE(
+      features.getMaxIntensityMatchedIonComplementPairPrecursorMassDelta() ==
+      Approx(-0.0036778069).epsilon(0.00001));
+    REQUIRE(features.countMatchedIonComplementPairs() == 3);
+
+    REQUIRE(features.getPeakIonPairs().size() == 3);
+
+    REQUIRE(features.getPeakIonPairs()[0].first.toString().toStdString() ==
+            "b2+isotope0r1mz243.134");
+    REQUIRE(features.getPeakIonPairs()[0].second.toString().toStdString() ==
+            "y9+isotope0r1mz1033.61");
+
+    REQUIRE(features.getPeakIonPairs()[1].first.toString().toStdString() ==
+            "b6+isotope0r1mz661.367");
+    REQUIRE(features.getPeakIonPairs()[1].second.toString().toStdString() ==
+            "y5+isotope0r1mz615.383");
+
+    REQUIRE(features.getPeakIonPairs()[2].first.toString().toStdString() ==
+            "b7+isotope0r1mz760.435");
+    REQUIRE(features.getPeakIonPairs()[2].second.toString().toStdString() ==
+            "y4+isotope0r1mz516.315");
+
+
+    REQUIRE(
+      features.getIonPairPrecursorMassDelta(features.getPeakIonPairs()[0]) ==
+      Approx(-0.0036778069).epsilon(0.001));
+    REQUIRE(
+      features.getIonPairPrecursorMassDelta(features.getPeakIonPairs()[1]) ==
+      Approx(-0.0118262069).epsilon(0.001));
+    REQUIRE(
+      features.getIonPairPrecursorMassDelta(features.getPeakIonPairs()[2]) ==
+      Approx(-0.0114600069).epsilon(0.001));
+
+
+    REQUIRE(features.getMaxConsecutiveIon(PeptideIon::y) == 9);
+    REQUIRE(features.getMaxConsecutiveIon(PeptideIon::b) == 2);
+    REQUIRE(features.getMaxConsecutiveIon(PeptideIon::a) == 0);
+
+
+    spectrum_simple = readMgf(
+      QString(CMAKE_SOURCE_DIR).append("/tests/data/peaklist_15046.mgf"));
+
+    peptide_sp = Peptide("AIADGSLLDLLR").makePeptideSp();
+
+    features.setPeptideSpectrumCharge(peptide_sp, &spectrum_simple, 2);
+    REQUIRE(features.getMaxConsecutiveIon(PeptideIon::y) == 10);
+    REQUIRE(features.getMaxConsecutiveIon(PeptideIon::b) == 3);
+    REQUIRE(features.getAaSequenceCoverage(PeptideIon::y) == 10);
+    REQUIRE(features.getAaSequenceCoverage(PeptideIon::b) == 5);
+
+
+    REQUIRE(features.getIntensityOfMatchedIon(PeptideIon::y) ==
+            Approx(863068.6967769999));
+    REQUIRE(features.getMaxIntensityPeakIonMatch(PeptideIon::y) ==
+            Approx(114514.0625));
+
+    REQUIRE(features.getIntensityOfMatchedIon(PeptideIon::b) ==
+            Approx(254791.342651));
+    REQUIRE(features.getMaxIntensityPeakIonMatch(PeptideIon::b) ==
+            Approx(161016.984375));
+
+
+    // SeqCoverComplementPeaks
+    REQUIRE(features.getComplementPairsAaSequenceCoverage() == 5);
+    REQUIRE(((double)features.getComplementPairsAaSequenceCoverage() /
+             (double)peptide_sp.get()->size()) == Approx(5.0 / 12.0));
+    REQUIRE(((double)0 / (double)peptide_sp.get()->size()) == Approx(0));
+
+
+    REQUIRE((features.getTotalIntensityOfMatchedIonComplementPairs() /
+             features.getTotalIntensity()) == Approx(0.1727291768));
+
+    REQUIRE((features.getTotalIntensityOfMatchedIonComplementPairs() <
+             features.getTotalIntensity()));
+
+    REQUIRE(
+      features.getMaxIntensityMatchedIonComplementPairPrecursorMassDelta() ==
+      Approx(0.0008592852).epsilon(0.00001));
   }
 }
diff --git a/tests/test_xic.cpp b/tests/test_xic.cpp
index 8a12c625e..4bea25662 100644
--- a/tests/test_xic.cpp
+++ b/tests/test_xic.cpp
@@ -313,15 +313,15 @@ TEST_CASE("XIC test suite.", "[XIC]")
                xicprm_test);
 
     INFO("readOdsXic OK");
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     TraceDetectionZivy _zivy(2, 3, 3, 5000, 6000);
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     TraceDetectionMaxSink max_peak_tic;
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     try
       {
-        _zivy.detect(xicprm_test, max_peak_tic);
-        qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+        _zivy.detect(xicprm_test, max_peak_tic, true);
+        qDebug();
       }
     catch(PappsoException &error)
       {
@@ -339,41 +339,41 @@ TEST_CASE("XIC test suite.", "[XIC]")
     OdsDocWriter writer(&fileods);
     TracePeakOdsWriterSink ods_sink(writer);
 
-    _zivy.detect(xicprm_test, ods_sink);
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    _zivy.detect(xicprm_test, ods_sink, true);
+    qDebug();
     writer.close();
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     fileods.close();
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
 
     Xic realxic_test;
     readOdsXic(QString(CMAKE_SOURCE_DIR).append("/tests/data/xic/real_xic.ods"),
                realxic_test);
     INFO("readOdsXic OK");
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     QFile realfileods(
       QString(CMAKE_SOURCE_DIR).append("/tests/data/xic/real_xic_detect.ods"));
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     OdsDocWriter realwriter(&realfileods);
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     TracePeakOdsWriterSink real_ods_sink(realwriter);
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     //_zivy.setSink(&max_peak_tic);
     TraceDetectionZivy _zivyb(2, 4, 3, 30000, 50000);
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     try
       {
-        _zivyb.detect(realxic_test, real_ods_sink);
+        _zivyb.detect(realxic_test, real_ods_sink, true);
       }
     catch(PappsoException &error)
       {
         INFO("error TraceDetectionZivy : " << error.qwhat().toStdString());
         throw error;
       }
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
     realwriter.close();
     realfileods.close();
-    qDebug() << __FILE__ << " " << __FUNCTION__ << " " << __LINE__;
+    qDebug();
 
     QFile realfilemoulondetectods(
       QString(CMAKE_SOURCE_DIR)
@@ -383,7 +383,7 @@ TEST_CASE("XIC test suite.", "[XIC]")
 
     TraceDetectionMoulon moulon(4, 60000, 40000);
 
-    moulon.detect(realxic_test, real_detect_moulonods_sink);
+    moulon.detect(realxic_test, real_detect_moulonods_sink, true);
 
     realdetectmoulonwriter.close();
     realfilemoulondetectods.close();
@@ -453,25 +453,25 @@ TEST_CASE("test operations on tracepeaklist", "[tracepeaklist]")
     Xic empty_xic;
     TraceDetectionZivy _zivy(2, 3, 3, 5000, 6000);
     TracePeakList peak_list;
-    _zivy.detect(empty_xic, peak_list);
+    _zivy.detect(empty_xic, peak_list, true);
     REQUIRE(peak_list.size() == 0);
 
     empty_xic.resize(2);
     fill(empty_xic.begin(), empty_xic.end(), DataPoint(1, 1));
 
-    _zivy.detect(empty_xic, peak_list);
+    _zivy.detect(empty_xic, peak_list, true);
     REQUIRE(peak_list.size() == 0);
 
     empty_xic.resize(3);
     fill(empty_xic.begin(), empty_xic.end(), DataPoint(1, 1));
 
-    _zivy.detect(empty_xic, peak_list);
+    _zivy.detect(empty_xic, peak_list, true);
     REQUIRE(peak_list.size() == 0);
 
     empty_xic.resize(4);
     fill(empty_xic.begin(), empty_xic.end(), DataPoint(1, 1));
 
-    _zivy.detect(empty_xic, peak_list);
+    _zivy.detect(empty_xic, peak_list, true);
     REQUIRE(peak_list.size() == 0);
 
 
@@ -484,7 +484,7 @@ TEST_CASE("test operations on tracepeaklist", "[tracepeaklist]")
         i++;
       }
 
-    _zivy.detect(empty_xic, peak_list);
+    _zivy.detect(empty_xic, peak_list, true);
     REQUIRE(peak_list.size() == 0);
 
 
@@ -497,7 +497,7 @@ TEST_CASE("test operations on tracepeaklist", "[tracepeaklist]")
         i++;
       }
 
-    _zivy.detect(empty_xic, peak_list);
+    _zivy.detect(empty_xic, peak_list, true);
     REQUIRE(peak_list.size() == 0);
   }
   SECTION("test for masschroq issue#15", "[tracepeaklist]")
@@ -512,7 +512,7 @@ TEST_CASE("test operations on tracepeaklist", "[tracepeaklist]")
     TraceDetectionZivy zivy15(2, 4, 3, 5000, 3000);
     TracePeakList peak_list;
     qDebug();
-    zivy15.detect(xic, peak_list);
+    zivy15.detect(xic, peak_list, true);
     qDebug();
     REQUIRE(peak_list.size() == 0);
   }
@@ -528,8 +528,23 @@ TEST_CASE("test operations on tracepeaklist", "[tracepeaklist]")
     readOdsXic(QString(CMAKE_SOURCE_DIR).append("/tests/data/xic/real_xic.ods"),
                xicprm_test);
 
+    TracePeak peak(
+      xicprm_test.begin() + 9079, xicprm_test.begin() + 9142, false);
+
+    REQUIRE(peak.getArea() == Approx(96163224.06));
+
+    TracePeak peak_nobase(
+      xicprm_test.begin() + 9079, xicprm_test.begin() + 9142, true);
+
+    REQUIRE(peak_nobase.getArea() == Approx(76281621.60));
+
+    REQUIRE(
+      peak_nobase.getLeftBoundary().y *
+        (peak_nobase.getRightBoundary().x - peak_nobase.getLeftBoundary().x) ==
+      Approx(peak.getArea() - peak_nobase.getArea()));
+
     INFO("readOdsXic OK");
-    REQUIRE_NOTHROW(_zivy.detect(xicprm_test, peak_list));
+    REQUIRE_NOTHROW(_zivy.detect(xicprm_test, peak_list, true));
 
     REQUIRE(peak_list.size() == 64);
 
-- 
GitLab


From 40780727f82d0b3e40c0e9cf38ff16ef5e95156f Mon Sep 17 00:00:00 2001
From: "Filippo Rusconi (Uploading Debian Developer)" <lopippo@debian.org>
Date: Mon, 7 Nov 2022 17:12:45 +0100
Subject: [PATCH 2/6] Import last version from qt6olivier.

---
 CMakeLists.txt                           | 13 ++++++
 src/CMakeLists.txt                       | 34 +++++++-------
 src/pappsomspp/obo/obopsimodterm.cpp     | 37 ++++++++++++++++
 src/pappsomspp/obo/obopsimodterm.h       | 11 +++--
 src/pappsomspp/vendors/tims/timsdata.cpp | 56 ++++++++++++++----------
 src/pappsomspp/vendors/tims/timsdata.h   |  6 +--
 tests/CMakeLists.txt                     | 46 ++++++++++---------
 tests/test_psm.cpp                       |  4 +-
 tests/widget/main.cpp                    |  1 +
 9 files changed, 136 insertions(+), 72 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index be95412d7..c69c962bd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -85,6 +85,11 @@ add_definitions(-Wall)
 message(STATUS "${BoldGreen}Setting definition -Wextra.${ColourReset}")
 add_definitions(-Wextra)
 
+if(WARN_AS_ERROR)
+  message(STATUS "${BoldYellow}Setting definition -Werror.${ColourReset}")
+  add_definitions(-Werror)
+endif()
+
 message(STATUS "${BoldRed}CMAKE_SOURCE_DIR: ${CMAKE_SOURCE_DIR}${ColourReset}")
 
 
@@ -180,6 +185,14 @@ message(STATUS "Boost_INCLUDES: ${Boost_INCLUDE_DIRS}")
 message(STATUS "Boost_LIB_DIRS: ${Boost_LIBRARY_DIRS}")
 
 
+# QCustomPlotQt6
+if(QCustomPlotQt6_FOUND)
+else (QCustomPlotQt6_FOUND)
+  set(QCustomPlotQt6_DIR ${CMAKE_MODULE_PATH})
+  find_package(QCustomPlotQt6 REQUIRED)
+endif(QCustomPlotQt6_FOUND)
+
+
 if(Alglib_FOUND)
 else (Alglib_FOUND)
   set(Alglib_DIR ${CMAKE_MODULE_PATH})
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4babea01b..806a0883f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -57,7 +57,7 @@ set(CPP_FILES
   pappsomspp/processing/filters/filterceilingamplitudepercentage.cpp
   pappsomspp/processing/filters/filterlowintensitysignalremoval.cpp
 
-  #pappsomspp/processing/tandemwrapper/tandemwrapperrun.cpp
+  pappsomspp/processing/tandemwrapper/tandemwrapperrun.cpp
   pappsomspp/processing/tandemwrapper/wraptandeminput.cpp
   pappsomspp/processing/tandemwrapper/wraptandemresults.cpp
   pappsomspp/processing/tandemwrapper/xtandempresetreader.cpp
@@ -90,7 +90,7 @@ set(CPP_FILES
   pappsomspp/msfile/msfilereader.cpp
   pappsomspp/msfile/mzformatenumstr.cpp
   pappsomspp/msfile/pwizmsfilereader.cpp
-  #pappsomspp/msfile/timsmsfilereader.cpp
+  pappsomspp/msfile/timsmsfilereader.cpp
   pappsomspp/msfile/xymsfilereader.cpp
 
   pappsomspp/msrun/alignment/msrunretentiontime.cpp
@@ -102,9 +102,9 @@ set(CPP_FILES
   pappsomspp/msrun/msrunid.cpp
   pappsomspp/msrun/msrunreader.cpp
   pappsomspp/msrun/private/pwizmsrunreader.cpp
-  #pappsomspp/msrun/private/timsmsrunreader.cpp
-  #pappsomspp/msrun/private/timsmsrunreaderms2.cpp
-  #pappsomspp/msrun/private/timsmsrunreaderms2selected.cpp
+  pappsomspp/msrun/private/timsmsrunreader.cpp
+  pappsomspp/msrun/private/timsmsrunreaderms2.cpp
+  pappsomspp/msrun/private/timsmsrunreaderms2selected.cpp
   pappsomspp/msrun/xiccoord/xiccoord.cpp
   pappsomspp/msrun/xiccoord/xiccoordtims.cpp
   pappsomspp/msrun/xymsrunreader.cpp
@@ -159,18 +159,18 @@ set(CPP_FILES
   pappsomspp/trace/maptrace.cpp
   pappsomspp/trace/trace.cpp
 
-  #pappsomspp/vendors/tims/mzcalibration/mzcalibrationinterface.cpp
-  #pappsomspp/vendors/tims/mzcalibration/mzcalibrationmodel1.cpp
-  #pappsomspp/vendors/tims/mzcalibration/mzcalibrationstore.cpp
-  #pappsomspp/vendors/tims/xicextractor/timsdirectxicextractor.cpp
-  #pappsomspp/vendors/tims/xicextractor/timsxicextractorinterface.cpp
-  #pappsomspp/vendors/tims/timsbindec.cpp
-  #pappsomspp/vendors/tims/timsdata.cpp
-  #pappsomspp/vendors/tims/timsframe.cpp
-  #pappsomspp/vendors/tims/timsframerawdatachunck.cpp
-  #pappsomspp/vendors/tims/timsframebase.cpp
-  #pappsomspp/vendors/tims/timsframetype1.cpp
-  #pappsomspp/vendors/tims/timsms2centroidfilter.cpp
+  pappsomspp/vendors/tims/mzcalibration/mzcalibrationinterface.cpp
+  pappsomspp/vendors/tims/mzcalibration/mzcalibrationmodel1.cpp
+  pappsomspp/vendors/tims/mzcalibration/mzcalibrationstore.cpp
+  pappsomspp/vendors/tims/xicextractor/timsdirectxicextractor.cpp
+  pappsomspp/vendors/tims/xicextractor/timsxicextractorinterface.cpp
+  pappsomspp/vendors/tims/timsbindec.cpp
+  pappsomspp/vendors/tims/timsdata.cpp
+  pappsomspp/vendors/tims/timsframe.cpp
+  pappsomspp/vendors/tims/timsframerawdatachunck.cpp
+  pappsomspp/vendors/tims/timsframebase.cpp
+  pappsomspp/vendors/tims/timsframetype1.cpp
+  pappsomspp/vendors/tims/timsms2centroidfilter.cpp
 
   pappsomspp/xic/xic.cpp
   pappsomspp/xic/qualifiedxic.cpp
diff --git a/src/pappsomspp/obo/obopsimodterm.cpp b/src/pappsomspp/obo/obopsimodterm.cpp
index 2dd6a04f9..b126743b4 100644
--- a/src/pappsomspp/obo/obopsimodterm.cpp
+++ b/src/pappsomspp/obo/obopsimodterm.cpp
@@ -47,6 +47,43 @@ QRegularExpression OboPsiModTerm::m_findExactPsiModLabel(
 QRegularExpression OboPsiModTerm::m_findRelatedPsiMsLabel(
   "^(.*)\\sRELATED\\sPSI-MS-label\\s\\[\\]$");
 
+
+OboPsiModTerm::OboPsiModTerm()
+{
+}
+
+OboPsiModTerm::~OboPsiModTerm()
+{
+}
+OboPsiModTerm::OboPsiModTerm(const OboPsiModTerm &other)
+{
+  m_accession   = other.m_accession;
+  m_name        = other.m_name;
+  m_definition  = other.m_definition;
+  m_psiModLabel = other.m_psiModLabel;
+  m_psiMsLabel  = other.m_psiMsLabel;
+  m_diffFormula = other.m_diffFormula;
+  m_origin      = other.m_origin;
+
+  m_diffMono = other.m_diffMono;
+}
+
+OboPsiModTerm &
+OboPsiModTerm::operator=(const OboPsiModTerm &other)
+{
+  m_accession   = other.m_accession;
+  m_name        = other.m_name;
+  m_definition  = other.m_definition;
+  m_psiModLabel = other.m_psiModLabel;
+  m_psiMsLabel  = other.m_psiMsLabel;
+  m_diffFormula = other.m_diffFormula;
+  m_origin      = other.m_origin;
+
+  m_diffMono = other.m_diffMono;
+  return *this;
+}
+
+
 bool
 OboPsiModTerm::isValid() const
 {
diff --git a/src/pappsomspp/obo/obopsimodterm.h b/src/pappsomspp/obo/obopsimodterm.h
index f312dc77c..884b7c868 100644
--- a/src/pappsomspp/obo/obopsimodterm.h
+++ b/src/pappsomspp/obo/obopsimodterm.h
@@ -33,10 +33,10 @@ class PMSPP_LIB_DECL OboPsiModTerm
   friend OboPsiMod;
 
   public:
-  OboPsiModTerm()                      = default;
-  ~OboPsiModTerm()                     = default;
-  OboPsiModTerm(const OboPsiModTerm &) = default;
-  OboPsiModTerm &operator=(const OboPsiModTerm &) = default;
+  OboPsiModTerm();
+  virtual ~OboPsiModTerm();
+  OboPsiModTerm(const OboPsiModTerm &);
+  OboPsiModTerm &operator=(const OboPsiModTerm &);
 
   bool isValid() const;
 
@@ -49,7 +49,7 @@ class PMSPP_LIB_DECL OboPsiModTerm
   QString m_diffFormula;
   QString m_origin;
 
-  double m_diffMono;
+  double m_diffMono = 0;
 
   private:
   void parseLine(const QString &line);
@@ -63,5 +63,4 @@ class PMSPP_LIB_DECL OboPsiModTerm
 } // namespace pappso
 
 
-
 extern int oboPsiModTermMetaTypeId;
diff --git a/src/pappsomspp/vendors/tims/timsdata.cpp b/src/pappsomspp/vendors/tims/timsdata.cpp
index 75dde4a84..c72ccc367 100644
--- a/src/pappsomspp/vendors/tims/timsdata.cpp
+++ b/src/pappsomspp/vendors/tims/timsdata.cpp
@@ -966,7 +966,7 @@ void
 TimsData::getQualifiedMs1MassSpectrumByPrecursorId(
   const MsRunIdCstSPtr &msrun_id,
   QualifiedMassSpectrum &mass_spectrum,
-  SpectrumDescr &spectrum_descr,
+  const SpectrumDescr &spectrum_descr,
   bool want_binary_data)
 {
 
@@ -1410,7 +1410,7 @@ void
 TimsData::getQualifiedMs2MassSpectrumByPrecursorId(
   const MsRunIdCstSPtr &msrun_id,
   QualifiedMassSpectrum &mass_spectrum,
-  SpectrumDescr &spectrum_descr,
+  const SpectrumDescr &spectrum_descr,
   bool want_binary_data)
 {
   try
@@ -1799,9 +1799,10 @@ pappso::TimsData::ms2ReaderSpectrumCollectionByMsLevel(
 
 
       std::function<std::vector<QualifiedMassSpectrum>(
-        pappso::TimsData::SpectrumDescr &)>
-        generate_spectrum = [itself, msrun_id, pointer_handler, ms_level](
-                              pappso::TimsData::SpectrumDescr &spectrum_descr)
+        const pappso::TimsData::SpectrumDescr &)>
+        map_function_generate_spectrum =
+          [itself, msrun_id, pointer_handler, ms_level](
+            const pappso::TimsData::SpectrumDescr &spectrum_descr)
         -> std::vector<QualifiedMassSpectrum> {
         std::vector<QualifiedMassSpectrum> mass_spectrum_list;
         itself->ms2ReaderGenerateMS1MS2Spectrum(msrun_id,
@@ -1814,28 +1815,35 @@ pappso::TimsData::ms2ReaderSpectrumCollectionByMsLevel(
         return mass_spectrum_list;
       };
 
+      std::function<void(
+        std::size_t,
+        const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list)>
+        reduce_function_spectrum_list =
+          [pointer_handler, local_filepath](
+            std::size_t res,
+            const std::vector<QualifiedMassSpectrum> &qualified_spectrum_list) {
+            for(auto &qualified_spectrum : qualified_spectrum_list)
+              {
+                pointer_handler->setQualifiedMassSpectrum(qualified_spectrum);
+              }
+
+            if(pointer_handler->shouldStop())
+              {
+                qDebug() << "The operation was cancelled. Breaking the loop.";
+                throw ExceptionInterrupted(
+                  QObject::tr("reading TimsTOF job on %1 cancelled by the user")
+                    .arg(local_filepath));
+              }
+            res++;
+          };
+
+
       QFuture<std::size_t> res;
       res = QtConcurrent::mappedReduced<std::size_t>(
         spectrum_description_list.begin(),
         spectrum_description_list.end(),
-        generate_spectrum,
-        [pointer_handler, res, local_filepath](
-          std::size_t &result,
-          std::vector<QualifiedMassSpectrum> qualified_spectrum_list) {
-          for(auto &qualified_spectrum : qualified_spectrum_list)
-            {
-              pointer_handler->setQualifiedMassSpectrum(qualified_spectrum);
-            }
-
-          if(pointer_handler->shouldStop())
-            {
-              qDebug() << "The operation was cancelled. Breaking the loop.";
-              throw ExceptionInterrupted(
-                QObject::tr("reading TimsTOF job cancelled by the user :\n%1")
-                  .arg(local_filepath));
-            }
-          result++;
-        },
+        map_function_generate_spectrum,
+        reduce_function_spectrum_list,
         QtConcurrent::OrderedReduce);
       res.waitForFinished();
     }
@@ -1849,7 +1857,7 @@ pappso::TimsData::ms2ReaderGenerateMS1MS2Spectrum(
   const MsRunIdCstSPtr &msrun_id,
   std::vector<QualifiedMassSpectrum> &qualified_mass_spectrum_list,
   pappso::SpectrumCollectionHandlerInterface &handler,
-  pappso::TimsData::SpectrumDescr &spectrum_descr,
+  const pappso::TimsData::SpectrumDescr &spectrum_descr,
   unsigned int ms_level)
 {
 
diff --git a/src/pappsomspp/vendors/tims/timsdata.h b/src/pappsomspp/vendors/tims/timsdata.h
index de8a19f83..2434f8aa2 100644
--- a/src/pappsomspp/vendors/tims/timsdata.h
+++ b/src/pappsomspp/vendors/tims/timsdata.h
@@ -129,13 +129,13 @@ class PMSPP_LIB_DECL TimsData
   void
   getQualifiedMs2MassSpectrumByPrecursorId(const MsRunIdCstSPtr &msrun_id,
                                            QualifiedMassSpectrum &mass_spectrum,
-                                           SpectrumDescr &spectrum_descr,
+                                           const SpectrumDescr &spectrum_descr,
                                            bool want_binary_data);
 
   void
   getQualifiedMs1MassSpectrumByPrecursorId(const MsRunIdCstSPtr &msrun_id,
                                            QualifiedMassSpectrum &mass_spectrum,
-                                           SpectrumDescr &spectrum_descr,
+                                           const SpectrumDescr &spectrum_descr,
                                            bool want_binary_data);
 
   /** @brief filter interface to apply just after raw MS2 specturm extraction
@@ -282,7 +282,7 @@ class PMSPP_LIB_DECL TimsData
     const MsRunIdCstSPtr &msrun_id,
     std::vector<QualifiedMassSpectrum> &qualified_mass_spectrum_list,
     SpectrumCollectionHandlerInterface &handler,
-    SpectrumDescr &spectrum_descr,
+    const SpectrumDescr &spectrum_descr,
     unsigned int ms_level);
 
   void fillSpectrumDescriptionWithSqlRecord(SpectrumDescr &spectrum_descr,
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index e24a4e403..fa0e3bf7a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -32,6 +32,7 @@ if(MAKE_TESTS AND (WIN64 OR (UNIX AND NOT APPLE)))
 
   find_package(Catch2 REQUIRED)
 
+
   if(OdsStream_FOUND)
   else (OdsStream_FOUND)
     find_package(OdsStream REQUIRED)
@@ -150,17 +151,17 @@ if(MAKE_TESTS AND (WIN64 OR (UNIX AND NOT APPLE)))
   target_link_libraries(test_fasta_reader Qt6::Core pappsomspp-shared)
   add_test(test_fasta_reader "test_fasta_reader")
 
-  add_executable(test_protein test_protein.cpp)
-  target_link_libraries(test_protein Qt6::Core pappsomspp-shared)
-  add_test(test_protein "test_protein")
+  #add_executable(test_protein test_protein.cpp)
+  #target_link_libraries(test_protein Qt6::Core pappsomspp-shared)
+  #add_test(test_protein "test_protein")
 
   add_executable(test_massrange test_massrange.cpp)
   target_link_libraries(test_massrange Qt6::Core pappsomspp-shared)
   add_test(test_massrange "test_massrange")
 
-  add_executable(test_peptide test_peptide.cpp)
-  target_link_libraries(test_peptide Qt6::Core Qt6::Gui pappsomspp-shared)
-  add_test(test_peptide "test_peptide")
+  #add_executable(test_peptide test_peptide.cpp)
+  #target_link_libraries(test_peptide Qt6::Core Qt6::Gui pappsomspp-shared)
+  #add_test(test_peptide "test_peptide")
 
   add_executable(test_peptidenaturalisotopelist test_peptidenaturalisotopelist.cpp)
   target_link_libraries(test_peptidenaturalisotopelist Qt6::Core Qt6::Gui pappsomspp-shared)
@@ -179,9 +180,9 @@ if(MAKE_TESTS AND (WIN64 OR (UNIX AND NOT APPLE)))
   add_test(test_fragmentationcid "test_fragmentationcid")
 
   #IF (FALSE) 
-  add_executable(test_big_hyperscore test_big_hyperscore.cpp ${CPP_TEST_FILES})
-  target_link_libraries(test_big_hyperscore Qt6::Core Qt6::Gui Qt6::Xml pappsomspp-shared)
-  add_test(test_big_hyperscore "test_big_hyperscore")
+  #add_executable(test_big_hyperscore test_big_hyperscore.cpp ${CPP_TEST_FILES})
+  #target_link_libraries(test_big_hyperscore Qt6::Core Qt6::Gui Qt6::Xml pappsomspp-shared)
+  #add_test(test_big_hyperscore "test_big_hyperscore")
   #ENDIF(FALSE)
 
   add_executable(test_rawmasslist test_rawmasslist.cpp)
@@ -189,32 +190,35 @@ if(MAKE_TESTS AND (WIN64 OR (UNIX AND NOT APPLE)))
   add_test(test_rawmasslist "test_rawmasslist")
 
   add_executable(test_isotope_with_spectrum common.cpp test_isotope_with_spectrum.cpp)
-  target_link_libraries(test_isotope_with_spectrum Qt6::Core Qt6::Gui pappsomspp-shared  ${Boost_LIBRARIES})
+  target_link_libraries(test_isotope_with_spectrum Qt6::Core Qt6::Gui
+    QuaZip::QuaZip pappsomspp-shared  ${Boost_LIBRARIES})
   add_test(test_isotope_with_spectrum "test_isotope_with_spectrum")
   set(TEST_LIST ${TEST_LIST} test_isotope_with_spectrum)
 
   add_executable(test_hyperscore common.cpp test_hyperscore.cpp)
-  target_link_libraries(test_hyperscore Qt6::Core pappsomspp-shared Qt6::Gui  ${Boost_LIBRARIES})
+  target_link_libraries(test_hyperscore Qt6::Core pappsomspp-shared Qt6::Gui
+    QuaZip::QuaZip ${Boost_LIBRARIES})
   add_test(test_hyperscore "test_hyperscore")
   set(TEST_LIST ${TEST_LIST} test_hyperscore)
 
   add_executable(test_xtandem_spectrum common.cpp test_xtandem_spectrum.cpp)
-  target_link_libraries(test_xtandem_spectrum Qt6::Core pappsomspp-shared Qt6::Gui  ${Boost_LIBRARIES})
+  target_link_libraries(test_xtandem_spectrum Qt6::Core pappsomspp-shared
+    Qt6::Gui QuaZip::QuaZip ${Boost_LIBRARIES})
   add_test(test_xtandem_spectrum "test_xtandem_spectrum")
   set(TEST_LIST ${TEST_LIST} test_xtandem_spectrum)
 
   add_executable(test_scan_15968  common.cpp test_scan_15968.cpp)
-  target_link_libraries(test_scan_15968 Qt6::Core Qt6::Gui pappsomspp-shared  ${Boost_LIBRARIES})
+  target_link_libraries(test_scan_15968 Qt6::Core Qt6::Gui pappsomspp-shared QuaZip::QuaZip ${Boost_LIBRARIES})
   add_test(test_scan_15968 "test_scan_15968")
   set(TEST_LIST ${TEST_LIST} test_scan_15968)
 
   add_executable(test_psm common.cpp test_psm.cpp)
-  target_link_libraries(test_psm Qt6::Core pappsomspp-shared Qt6::Gui Qt6::Concurrent  ${Boost_LIBRARIES})
+  target_link_libraries(test_psm Qt6::Core pappsomspp-shared Qt6::Gui Qt6::Concurrent QuaZip::QuaZip ${Boost_LIBRARIES})
   add_test(test_psm "test_psm")
   set(TEST_LIST ${TEST_LIST} test_psm)
 
   add_executable(test_xicextractor test_xicextractor.cpp)
-  target_link_libraries(test_xicextractor Qt6::Core Qt6::Gui pappsomspp-shared  ${Boost_LIBRARIES} OdsStream::Core)
+  target_link_libraries(test_xicextractor Qt6::Core Qt6::Gui pappsomspp-shared  ${Boost_LIBRARIES} QuaZip::QuaZip OdsStream::Core)
   add_test(test_xicextractor "test_xicextractor")
   set(TEST_LIST ${TEST_LIST} test_xicextractor)
 
@@ -224,14 +228,14 @@ if(MAKE_TESTS AND (WIN64 OR (UNIX AND NOT APPLE)))
   set(TEST_LIST ${TEST_LIST} test_msrunoutput)
 
 
-  if(UNIX)
+  #if(UNIX)
 
-    set_property(TEST catch2-only-tests test_big_hyperscore test_fasta_reader 
-      test_massrange test_peptidenaturalisotopelist test_peptidefragment 
-      test_fragmentationcid ${TEST_LIST} test_natural_isotope_average test_rawmasslist 
-      PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:../src")
+  #set_property(TEST catch2-only-tests test_big_hyperscore test_fasta_reader 
+  #test_massrange test_peptidenaturalisotopelist test_peptidefragment 
+  #test_fragmentationcid ${TEST_LIST} test_natural_isotope_average test_rawmasslist 
+  #PROPERTY ENVIRONMENT "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:../src")
 
-  endif()
+  #endif()
 
   if(WIN32)
     set(ENV{PATH} "$ENV{PATH};..\\src")
diff --git a/tests/test_psm.cpp b/tests/test_psm.cpp
index e495e4ac5..1816cfece 100644
--- a/tests/test_psm.cpp
+++ b/tests/test_psm.cpp
@@ -29,8 +29,10 @@
 // make test ARGS="-V -I 18,18"
 // ./tests/catch2-only-tests [psm] -s
 // ./tests/catch2-only-tests [psmfeature] -s
-#include <algorithm>
 
+#define CATCH_CONFIG_MAIN
+
+#include <algorithm>
 #include <catch2/catch.hpp>
 #include <pappsomspp/mzrange.h>
 #include <pappsomspp/psm/peptidespectrummatch.h>
diff --git a/tests/widget/main.cpp b/tests/widget/main.cpp
index d18831695..e68322560 100644
--- a/tests/widget/main.cpp
+++ b/tests/widget/main.cpp
@@ -28,6 +28,7 @@
  ******************************************************************************/
 
 #include <QApplication>
+#include <QIODevice>
 #include <pappsomspp/pappsoexception.h>
 #include "testwidgetgui.h"
 
-- 
GitLab


From 337e8e9931ee2aa006fe405cd6a8e5aedc1873eb Mon Sep 17 00:00:00 2001
From: "Filippo Rusconi (Uploading Debian Developer)" <lopippo@debian.org>
Date: Mon, 7 Nov 2022 17:24:40 +0100
Subject: [PATCH 3/6] Merge the debian/changelog from qt6olivier.

---
 debian/changelog | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index a4b782d19..5787dfcbe 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,52 @@ libpappsomspp (0.9.0-1) unstable; urgency=low
 
  -- Filippo Rusconi <lopippo@debian.org>  Thu, 22 Sep 2022 18:35:01 +0200
 
+libpappsomspp (0.8.60-1~bullseye+1) bullseye; urgency=medium
+
+  * bullseye backport
+
+ -- Olivier Langella <olivier.langella@u-psud.fr>  Mon, 31 Oct 2022 09:06:33 +0100
+
+libpappsomspp (0.8.60-1) unstable; urgency=low
+
+  * Fix the distribution... was working too late at night...
+
+ -- Filippo Rusconi <lopippo@debian.org>  Fri, 28 Oct 2022 10:20:12 +0200
+
+libpappsomspp (0.8.59-1) bullseye; urgency=low
+
+  * New upstream version.
+
+  * Incidentally, previous version was to fix a bug that was published in
+    betwwen the previous version and this one: (Closes: #1022934).
+
+ -- Filippo Rusconi <lopippo@debian.org>  Fri, 28 Oct 2022 03:30:29 +0200
+
+libpappsomspp (0.8.58-1) bullseye; urgency=low
+
+  * New upstream version (see 0.8.57-1~bullseye+1).
+
+  * Standards-Version: 4.6.1.
+
+  * d/rules: Fix by Adrian Bunk to work around the excess precision of the x87
+    FPU that causes
+    https://buildd.debian.org/status/logs.php?pkg=libpappsomspp&arch=i386.
+
+ -- Filippo Rusconi <lopippo@debian.org>  Thu, 27 Oct 2022 10:38:00 +0200
+
+libpappsomspp (0.8.57-1~bullseye+1) bullseye; urgency=medium
+
+  [ Olivier Langella ]
+  * avoid nullptr calls in custom plot widgets
+  * new tims frame widget color map
+  * better tdf handler
+  * new tests for protein , enzyme, psm, psmfeaures
+  * new psm feature API
+  [ Filippo Rusconi ]
+  * refactoring work to compile using Qt6
+
+ -- Olivier Langella <olivier.langella@u-psud.fr>  Tue, 04 Oct 2022 17:02:43 +0200
+
 libpappsomspp (0.8.56-1) unstable; urgency=low
 
   * New version that implements features in the dt|rt,m/z color map realms.
-- 
GitLab


From 85006966037a47f65d8b54c8a1f7720265a31b54 Mon Sep 17 00:00:00 2001
From: "Filippo Rusconi (Uploading Debian Developer)" <lopippo@debian.org>
Date: Mon, 7 Nov 2022 17:25:44 +0100
Subject: [PATCH 4/6] Add dependency over zlib1g-dev.

---
 debian/control | 1 +
 1 file changed, 1 insertion(+)

diff --git a/debian/control b/debian/control
index f685fc065..23a624e0d 100644
--- a/debian/control
+++ b/debian/control
@@ -17,6 +17,7 @@ Build-Depends: debhelper-compat (= 12),
  libsqlite3-dev,
  libzstd-dev (>= 1.3.3),
  liblzf-dev,
+ zlib1g-dev,
  libboost-dev,
  libboost-iostreams-dev,
  libboost-thread-dev,
-- 
GitLab


From e906ca5b66ddd69b17f50f90fcd968bb29235d9c Mon Sep 17 00:00:00 2001
From: "Filippo Rusconi (Uploading Debian Developer)" <lopippo@debian.org>
Date: Mon, 7 Nov 2022 17:26:42 +0100
Subject: [PATCH 5/6] Add the fix for the i386 build.

---
 debian/rules | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/debian/rules b/debian/rules
index e36ef89d1..a9a11dccb 100755
--- a/debian/rules
+++ b/debian/rules
@@ -11,6 +11,12 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all
 DPKG_EXPORT_BUILDFLAGS = 1
 include /usr/share/dpkg/buildflags.mk
 
+ifneq (,$(filter $(DEB_HOST_ARCH_CPU), i386))
+  export DEB_CXXFLAGS_MAINT_APPEND += -ffloat-store
+endif
+
+
+
 %:
 	dh $@ --buildsystem=cmake
 
-- 
GitLab


From 9cfce0edf4dc3030cf084d5d9cce827ad2210b7e Mon Sep 17 00:00:00 2001
From: "Filippo Rusconi (Uploading Debian Developer)" <lopippo@debian.org>
Date: Mon, 7 Nov 2022 17:34:51 +0100
Subject: [PATCH 6/6] Better document the LOCAL_CMAKE_MODULE_PATH and use it.

---
 CMakeLists.txt | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index c69c962bd..12c1c5721 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -38,14 +38,19 @@ message(STATUS "CMAKE_INSTALL_FULL_INCLUDEDIR: ${CMAKE_INSTALL_FULL_INCLUDEDIR}"
 # Add folder where are supportive functions
 set(CMAKE_UTILS_PATH ${CMAKE_SOURCE_DIR}/CMakeStuff)
 set(CMAKE_TOOLCHAINS_PATH ${CMAKE_UTILS_PATH}/toolchains)
+
+# We need a variable that is not modified by CMake because we'll need to access
+# that specific directory later
 set(LOCAL_CMAKE_MODULE_PATH ${CMAKE_UTILS_PATH}/modules)
 message("CMakeLists.txt - LOCAL_CMAKE_MODULE_PATH:" ${LOCAL_CMAKE_MODULE_PATH})
-set(CMAKE_MODULE_PATH ${CMAKE_UTILS_PATH}/modules ${CMAKE_MODULE_PATH})
+
+# Now add our local path to the general path list.
+set(CMAKE_MODULE_PATH ${LOCAL_CMAKE_MODULE_PATH} ${CMAKE_MODULE_PATH})
 
 # This include must come before all the others
 # It must include the config-generated config.h file
 # before the others.
-#include_directories(${CMAKE_BINARY_DIR})
+include_directories(${CMAKE_BINARY_DIR})
 
 # Include the system's uname that fills in SYSTEM_UNAME_S.
 # Sets WIN64 if SYSTEM_UNAME_S is "^.*MING64.*"
-- 
GitLab