[Debichem-commits] [SCM] massXpert mass spectrometry suite: debian packaging branch, debian, updated. upstream/3.2.0-1-g5564507

Filippo Rusconi (Debian Maintainer) rusconi-debian at laposte.net
Thu Nov 24 21:29:13 UTC 2011


The following commit has been merged in the debian branch:
commit 785f3626c0c6bd60ba5f17b11d580472b7e6cb06
Author: Filippo Rusconi (Debian Maintainer) <rusconi-debian at laposte.net>
Date:   Sun Aug 14 16:25:17 2011 +0200

    First implementation of the calculation of a spectrum made of isotopic cluster of a number of oligomers.

diff --git a/gui/calculatorWnd.cpp b/gui/calculatorWnd.cpp
index 37f04ca..d62df15 100644
--- a/gui/calculatorWnd.cpp
+++ b/gui/calculatorWnd.cpp
@@ -1166,6 +1166,7 @@ namespace massXpert
   {
     SpectrumCalculationDlg *dlg = 
       new SpectrumCalculationDlg(this, 
+                                 0 /* no polymer pointer in this casee */,
                                  m_polChemDef.atomList(),
                                  MXP_SPECTRUM_CALCULATION_MODE_CLUSTER);
   
diff --git a/gui/cleavageDlg.cpp b/gui/cleavageDlg.cpp
index de79c38..8e80cfc 100644
--- a/gui/cleavageDlg.cpp
+++ b/gui/cleavageDlg.cpp
@@ -49,6 +49,7 @@
 #include "peakCentroid.hpp"
 #include "peakShapeConfig.hpp"
 #include "isotopicPatternCalculator.hpp"
+#include "spectrumCalculationDlg.hpp"
 
 
 namespace massXpert
@@ -119,7 +120,8 @@ namespace massXpert
     comboBoxItemList 
       << tr("To Clipboard") 
       << tr("To File")
-      << tr("Select File");
+      << tr("Select File")
+      << tr("Calculate spectrum");
   
     m_ui.exportResultsComboBox->addItems(comboBoxItemList);
   
@@ -797,6 +799,10 @@ bool
       {
 	selectResultsFile();
       }
+    else if (index == 3)
+      {
+	calculateSpectrum();
+      }
     else 
       Q_ASSERT(0);
   
@@ -882,6 +888,29 @@ bool
 
     return true;
   }
+
+
+  bool
+  CleavageDlg::calculateSpectrum()
+  {
+    qDebug() << __FILE__ << __LINE__
+             << "calculateSpectrum";
+    
+    SpectrumCalculationDlg *dlg = 
+      new SpectrumCalculationDlg(this, 
+                                 mp_polymer,
+                                 mp_polChemDef->atomList(),
+                                 MXP_SPECTRUM_CALCULATION_MODE_SPECTRUM);
+
+    // We now have to prepare the land for the calculations.
+
+    dlg->setOligomerList(&m_oligomerList);
+        
+    dlg->show();
+
+    return true;
+  }
+  
   //////////////////////////////////// The results-exporting functions.
   //////////////////////////////////// The results-exporting functions.
   //////////////////////////////////// The results-exporting functions.
diff --git a/gui/cleavageDlg.hpp b/gui/cleavageDlg.hpp
index 9c8d5bd..4613132 100644
--- a/gui/cleavageDlg.hpp
+++ b/gui/cleavageDlg.hpp
@@ -114,6 +114,7 @@ namespace massXpert
     bool exportResultsToClipboard();
     bool exportResultsFile();
     bool selectResultsFile();
+    bool calculateSpectrum();
     //////////////////////////////////// The results-exporting functions.
 
   public slots:
diff --git a/gui/fragmentOligomerTableView.cpp b/gui/fragmentOligomerTableView.cpp
index 5677f9b..0fe1c59 100644
--- a/gui/fragmentOligomerTableView.cpp
+++ b/gui/fragmentOligomerTableView.cpp
@@ -426,7 +426,15 @@ namespace massXpert
       static_cast<FragmentOligomer *>(mp_oligomerList->at(row));
     
     SequenceEditorWnd *editorWnd = mp_parentDlg->editorWnd();
-  
+
+    // The formula is not correct by now. The fragmentation formula
+    // does not seem to be taken into account. However, it works fine
+    // for oligomers computed from cleavage.
+    //
+    // QString formula = oligomer->elementalComposition();
+    // qDebug() << __FILE__ << __LINE__
+    //          << "Elemental composition: " << formula;
+    
     if (oligomer->startIndex() >= oligomer->polymer()->size() ||
         oligomer->endIndex() >= oligomer->polymer()->size())
       	  {
diff --git a/gui/spectrumCalculationDlg.cpp b/gui/spectrumCalculationDlg.cpp
index 8f49ea9..7f0b1dc 100644
--- a/gui/spectrumCalculationDlg.cpp
+++ b/gui/spectrumCalculationDlg.cpp
@@ -56,16 +56,19 @@ namespace massXpert
 {
 
   SpectrumCalculationDlg::SpectrumCalculationDlg 
-  (QWidget *parent, const QList<Atom *> &atomList,
+  (QWidget *parent, 
+   const Polymer *polymer,
+   const QList<Atom *> &atomList,
    SpectrumCalculationMode mode)
    : QDialog(parent), 
+     mp_polymer(polymer),
      m_mode(mode),
      m_atomList(atomList),
      m_polChemDef(static_cast<CalculatorWnd *>(parent)->polChemDef())
      {
     Q_ASSERT(parent);
 
-    setWindowTitle("massXpert: Isotopic pattern calculator");
+    setWindowTitle("massXpert: Spectrum Calculator");
     
     m_aborted = false;
     
@@ -76,9 +79,13 @@ namespace massXpert
     m_validationErrors = MXP_VALIDATION_FORMULA_ERRORS;
     
     m_filePath = "";
-  
+
     m_ui.setupUi(this);
 
+    // Set the oligomer list pointer to 0, so that we know if it was
+    // set or not later.
+    mp_oligomerList = 0;
+    
     setupDialog();
     
     QSettings settings 
@@ -118,6 +125,26 @@ namespace massXpert
             this,
             SLOT(fwhmEdited(const QString &)));
 
+    connect(m_ui.monoRadioButton,
+            SIGNAL(toggled(bool)),
+            this,
+            SLOT(massTypeRadioButtonToggled(bool)));
+    
+    connect(m_ui.avgRadioButton,
+            SIGNAL(toggled(bool)),
+            this,
+            SLOT(massTypeRadioButtonToggled(bool)));
+    
+    connect(m_ui.avgRadioButton,
+            SIGNAL(toggled(bool)),
+            this,
+            SLOT(massTypeRadioButtonToggled(bool)));
+    
+    connect(m_ui.isotopicClusterCheckBox,
+            SIGNAL(toggled(bool)),
+            this,
+            SLOT(isotopicClusterCheckBoxToggled(bool)));
+    
     connect(m_ui.executePushButton,
 	     SIGNAL(clicked()),
 	     this,
@@ -166,6 +193,16 @@ namespace massXpert
 
   
   void 
+  SpectrumCalculationDlg::setOligomerList(OligomerList *list)
+  {
+    if(!list)
+      qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__);
+
+    mp_oligomerList = list;
+  }
+  
+
+  void 
   SpectrumCalculationDlg::setupDialog()
   {
     // By default we want a gaussian-type shape.
@@ -204,25 +241,52 @@ namespace massXpert
     // Now, depending on the kind of operation required for the
     // dialog, adapt some behaviour.
 
+
     if(m_mode == MXP_SPECTRUM_CALCULATION_MODE_CLUSTER)
       {
         // In isotopic cluster calculation mode, the m/z calculated
         // starting from the formula and the charge is of course mono!
-        // Thus, we set it checked and disable mono and avg.
+        // Thus, we set it checked and disable the enclosing group box.
 
         m_ui.monoRadioButton->setChecked(true);
-        m_ui.monoRadioButton->setDisabled(true);
-        m_ui.avgRadioButton->setDisabled(true);
+        m_ui.massTypeGroupBox->setDisabled(true);
+
+        // Of course, the computeIsotopicClusterCheckBox should be
+        // checked and disabled.
+        m_ui.isotopicClusterCheckBox->setChecked(true);
+        m_ui.isotopicClusterCheckBox->setDisabled(true);
       }
-    
+    else if(m_mode == MXP_SPECTRUM_CALCULATION_MODE_SPECTRUM)
+      {
+        // In spectrum mode, the formula, z and m/z are not active.
+        m_ui.mzGroupBox->setDisabled(true);
 
+        // By default, we work on mono masses.
+        m_withMonoMass= true;
+        m_ui.monoRadioButton->setChecked(m_withMonoMass);
+      
+        // By default, we do not want isotopic cluster calculations.
+        m_withCluster = false;
+        m_ui.isotopicClusterCheckBox->setChecked(m_withCluster);
+      }
+  }
 
-}
-  
   
   bool
   SpectrumCalculationDlg::fetchValidateInputData()
   {
+    if(m_mode == MXP_SPECTRUM_CALCULATION_MODE_CLUSTER)
+      return fetchValidateInputDataIsotopicClusterMode();
+    else if(m_mode == MXP_SPECTRUM_CALCULATION_MODE_SPECTRUM)
+      return fetchValidateInputDataSpectrumMode();
+    else
+      return false;
+  }
+  
+
+  bool 
+  SpectrumCalculationDlg::fetchValidateInputDataIsotopicClusterMode()
+  {
     Application *application = static_cast<Application *>(qApp);
 
     // The ionization stuff, the formula for which the isotopic
@@ -255,9 +319,9 @@ namespace massXpert
     if (!m_formula.deepAtomCopy(m_atomList))
       {
 	QMessageBox::warning(0,
-			      tr("massXpert: Isotopic Pattern Calculation"),
-			      tr("Failed to deep-copy atom list."),
-			      QMessageBox::Ok);
+                             tr("massXpert: Spectrum Calculator"),
+                             tr("Failed to deep-copy atom list."),
+                             QMessageBox::Ok);
 
 	return false;
       }
@@ -296,9 +360,9 @@ namespace massXpert
         .arg(m_formula.formula())
 	.arg(m_charge)
         .arg(application->locale().
-	      toString(m_mono, 'f', MXP_OLIGOMER_DEC_PLACES))
+             toString(m_mono, 'f', MXP_OLIGOMER_DEC_PLACES))
 	.arg(application->locale().
-	      toString(m_avg, 'f', MXP_OLIGOMER_DEC_PLACES))
+             toString(m_avg, 'f', MXP_OLIGOMER_DEC_PLACES))
         .arg(totAtoms)
 	.arg(totIsotopes);
     else
@@ -351,7 +415,6 @@ namespace massXpert
 
     // Set the maximum number of peaks in the isotopic curve.
     m_maximumPeaks = m_ui.maximumPeaksSpinBox->value();
-    QString fwhmString = m_ui.fwhmLineEdit->text();
     
     // Set the minimum probability each isotopic peak must have to be
     // retained in the final curve.
@@ -364,7 +427,7 @@ namespace massXpert
     if(!minProb && !ok)
       {
 	QMessageBox::warning(0,
-                             tr("massXpert: Isotopic Pattern Calculation"),
+                             tr("massXpert: Spectrum Calculator"),
                              tr("Please, fix the minimum probability."),
                              QMessageBox::Ok);
         
@@ -375,9 +438,115 @@ namespace massXpert
     
     return true;
   }
+  
+  
+  bool 
+  SpectrumCalculationDlg::fetchValidateInputDataSpectrumMode()
+  {
+    // The ionization stuff, the formula for which the isotopic
+    // pattern is to be calculated, the mz ratio (in m_mono) all have
+    // been checked previously by automated procedures (see the
+    // "changed" slots). We have to make sure that either the
+    // resolution or the FWHM values are OK. All the other bits must
+    // be clear. Only either the RESOLUTION or the FWHM bit might be
+    // set.
+
+    int testBitset = 0;
+    testBitset |= MXP_VALIDATION_RESOLUTION_ERRORS;
+    testBitset |= MXP_VALIDATION_FWHM_ERRORS;
+    
+    // debugPutStdErrBitset(__FILE__, __LINE__,
+    //                      testBitset, "testBitset");
+
+    if(m_validationErrors == testBitset)
+      return false;
+      
+    // We do not care of the formula in our spectrum calculation
+    // situation. Each oligomer from a cleavage contains a chemical
+    // composition formula that we'll use each time.
+    
+    // We still have to fetch a number of parameters.
 
+    // Are we working on the mono or the avg masses of the oligomers?
+    
+    m_withMonoMass = m_ui.monoRadioButton->isChecked();
+    
+    // Get to know if we want gaussian or lorentzian shapes.
+    if(m_ui.gaussianRadioButton->isChecked())
+      {
+        m_config.setPeakShapeType(MXP_PEAK_SHAPE_TYPE_GAUSSIAN);
+      }
+    else
+      {
+        m_config.setPeakShapeType(MXP_PEAK_SHAPE_TYPE_LORENTZIAN);
+      }
+  
+    // At this point we have to sort out wether the user wants to use
+    // the resolution or the FWHM for the calculations. This is
+    // automatically known by looking at which value is 0 (see the
+    // corresponding changed() slots).
+
+    // Get the points value.
+    m_config.setPointNumber(m_ui.pointNumberSpinBox->value());
+    
+    // How about setting the increment, that is the size of the gap
+    // between two points ? If it is not set (its value is 0), then
+    // increment is fwhm() / m_pointNumber;
+
+    // First however, see if the user wants to use the FWHM value or
+    // the resolution.
+    
+    if(m_config.fwhm())
+      {
+        // FWHM is not zero, which means the user has set a value for
+        // it. Keep it.
+      }
+    else
+      {
+        // We cannot compute fwhm starting from the resolution because
+        // we cannot know what is the m/z of the oligomers beforehand.
+
+        // All we can check is that resolution is non-zero.
+
+        if(m_resolution <= 0)
+          {
+            QMessageBox::warning(0,
+                                 tr("massXpert: Spectrum Calculator"),
+                                 tr("Please, fix the resolution or the FWHM."),
+                                 QMessageBox::Ok);
+            
+            return false;
+          }
+      }
+    
+    // Set the maximum number of peaks in the isotopic curve.
+    m_maximumPeaks = m_ui.maximumPeaksSpinBox->value();
+    
+    // Set the minimum probability each isotopic peak must have to be
+    // retained in the final curve.
+
+    QString minProbString = m_ui.minimumProbabilityLineEdit->text();
+    bool ok = false;
+    
+    double minProb = minProbString.toDouble(&ok);
+    
+    if(!minProb && !ok)
+      {
+	QMessageBox::warning(0,
+                             tr("massXpert: Spectrum Calculator"),
+                             tr("Please, fix the minimum probability."),
+                             QMessageBox::Ok);
+        
+	return false;
+      }
+      
+    m_minimumProbability = minProb;
+    
+    return true;
+  }
   
-// Returns false if formula is bad or aborts if calculation fails..
+
+  // Returns false if formula is bad or aborts if calculation fails..
   bool
   SpectrumCalculationDlg::fetchFormulaMass(double *mono, double *avg)
   {
@@ -478,6 +647,35 @@ namespace massXpert
     return true;
   }
   
+  void 
+  SpectrumCalculationDlg::massTypeRadioButtonToggled(bool checked)
+  {
+    Q_UNUSED(checked);
+    
+    m_withMonoMass = m_ui.monoRadioButton->isChecked();
+
+    // If the mass type is average, then, of course, no isotopic
+    // cluster calculation can be required.
+
+    if(!m_withMonoMass)
+      m_ui.isotopicClusterCheckBox->setChecked(false);
+  }
+  
+  void
+  SpectrumCalculationDlg::isotopicClusterCheckBoxToggled(bool checked)
+  {
+    m_withCluster = checked;
+
+    if(checked)
+      {
+        // If the isotopic cluster is to be computed for each oligomer,
+        // then that means necessarily that the mass is mono!
+
+        m_withMonoMass = true;
+        m_ui.monoRadioButton->setChecked(true);
+      }
+  }
+  
 
   void 
   SpectrumCalculationDlg::formulaEdited(const QString &text)
@@ -596,11 +794,6 @@ namespace massXpert
   void 
   SpectrumCalculationDlg::resolutionChanged(int value)
   {
-    // We only handle the automatic recalculations on the basis of
-    // this change if we are in a isotopic cluster calculation task.
-    if(m_mode != MXP_SPECTRUM_CALCULATION_MODE_CLUSTER)
-      return;
-
     // If the value changed, that means that the user wants the
     // resolution to be taken into account for calculation of the peak
     // width, and not the FWHM. Only if resolution is set to 0, FWHM
@@ -637,8 +830,15 @@ namespace massXpert
     // Clear the bit as there is no error here.
     m_validationErrors &= ~MXP_VALIDATION_RESOLUTION_ERRORS;
 
+    // We only handle the automatic recalculations on the basis of
+    // this change if we are in a isotopic cluster calculation task
+    // because only in that case do we know before starting the
+    // calculation what will be the mz.
+    if(m_mode != MXP_SPECTRUM_CALCULATION_MODE_CLUSTER)
+      return;
+    
     // We can try to compute the fwhm value corresponding to the
-    // current m_mono (m/z, really) value and the resolution.
+    // current mono m/z value and the resolution.
 
     double mono;
     double avg;
@@ -678,11 +878,6 @@ namespace massXpert
   void 
   SpectrumCalculationDlg::fwhmEdited(const QString &text)
   {
-    // We only handle the automatic recalculations on the basis of
-    // this change if we are in a isotopic cluster calculation task.
-    if(m_mode != MXP_SPECTRUM_CALCULATION_MODE_CLUSTER)
-      return;
-
     // Show what's the value of the errors.
     // debugPutStdErrBitset(__FILE__, __LINE__,
     //                      m_validationErrors, 
@@ -749,6 +944,13 @@ namespace massXpert
     //                      m_validationErrors, 
     //                      "m_validationErrors @ EXIT fwhmEdited");
 
+    // We only handle the automatic recalculation of the increment on
+    // the basis of this change if we are in a isotopic cluster
+    // calculation task because only in this case do we know the mono
+    // mz value.
+    if(m_mode != MXP_SPECTRUM_CALCULATION_MODE_CLUSTER)
+      return;
+
     updateIncrement();
     
     return;
@@ -771,7 +973,7 @@ namespace massXpert
     if(!res)
       {
         QMessageBox::warning(0, 
-                             tr("massXpert - Isotopic Pattern Calculation"),
+                             tr("massXpert - Spectrum Calculator"),
                              tr("Failed to fetch the mz ratio."),
                              QMessageBox::Ok);
         
@@ -863,6 +1065,22 @@ namespace massXpert
   void 
   SpectrumCalculationDlg::execute()
   {
+    // We might be called to perform two different things:
+    //
+    // 1. Calculate a single istotopic cluster pattern.
+    //
+    // 2. Calculate a spectrum for a whole set of oligomers.
+
+    if(m_mode == MXP_SPECTRUM_CALCULATION_MODE_CLUSTER)
+      return executeCluster();
+    else if(m_mode == MXP_SPECTRUM_CALCULATION_MODE_SPECTRUM)
+      return executeSpectrum();
+  }
+  
+    
+  void 
+  SpectrumCalculationDlg::executeCluster()
+  {
     Application *application = static_cast<Application *>(qApp);
 
     // Clear the textEdit widget so that we can start out-putting text
@@ -880,7 +1098,7 @@ namespace massXpert
     if(!fetchValidateInputData())
       {
         QMessageBox::warning(0, 
-                             tr("massXpert - Isotopic Pattern Calculation"),
+                             tr("massXpert - Spectrum Calculator"),
                              tr("Please fix the input data first."),
                              QMessageBox::Ok);
         return;
@@ -898,15 +1116,19 @@ namespace massXpert
     if (isUsingLocale)
       text->append(tr("FWHM: %1 \t Max. peaks %2 "
                       "\t Min. probability: %3\n\n")
-                   .arg(application->locale().toString(m_config.fwhm(), 'f', 4))
+                   .arg(application->locale().toString(m_config.fwhm(),
+                                                       'f', 4))
                    .arg(application->locale().toString(m_maximumPeaks))
-                   .arg(application->locale().toString(m_minimumProbability, 'f', 15)));
+                   .arg(application->locale().toString(m_minimumProbability,
+                                                       'f', 15)));
     else
       text->append(tr("FWHM: %1 \t Max. peaks %2 "
                       "\t Min. probability: %3\n\n")
-                   .arg(QString().setNum(m_config.fwhm(), 'f', 4))
+                   .arg(QString().setNum(m_config.fwhm(),
+                                         'f', 4))
                    .arg(QString().setNum(m_maximumPeaks))
-                   .arg(QString().setNum(m_minimumProbability, 'f', 15)));
+                   .arg(QString().setNum(m_minimumProbability,
+                                         'f', 15)));
     
     m_ui.resultTextEdit->append(*text);
     
@@ -924,22 +1146,21 @@ namespace massXpert
     connect(calculator,
             SIGNAL(isotopicCalculationProgressValueChanged(int)),
             this,
-            SLOT(isotopicCalculationProgressValueChanged(int)));
+            SLOT(spectrumCalculationProgressValueChanged(int)));
 
     connect(calculator,
             SIGNAL(isotopicCalculationMessageChanged(QString)),
             this,
-            SLOT(isotopicCalculationMessageChanged(QString)));
+            SLOT(spectrumCalculationMessageChanged(QString)));
     
     connect(this,
             SIGNAL(isotopicCalculationAborted()),
             calculator,
-            SLOT(isotopicCalculationAborted()));
+            SLOT(spectrumCalculationAborted()));
     
 
     // Perform the calculation...
-
-    calculator->calculateSpectrum();
+    calculator->sumPeakShapes();
 
     // Get the list of peaks as "1251.14 0.025" pairs.
     text = calculator->peakCentroidListAsString();
@@ -968,7 +1189,7 @@ namespace massXpert
     // QPointF instances in the calculator and send them either to the
     // file or to the text edit widget.
 
-    const QList<QPointF *> &spectrumPoints = calculator->spectrum();
+    const QList<QPointF *> &spectrumPoints = calculator->pointList();
     QString dataString;
     
     if(!m_filePath.isEmpty())
@@ -981,7 +1202,7 @@ namespace massXpert
         if(!file.open(QFile::WriteOnly | QFile::Truncate))
           {
             QMessageBox::warning(this, 
-                                 tr("massXpert - Isotopic Pattern Calculation"),
+                                 tr("massXpert - Spectrum Calculator"),
                                  tr("Failed to export the isotopic pattern "
                                     "data to file."),
                                  QMessageBox::Ok);
@@ -1027,6 +1248,287 @@ namespace massXpert
     delete calculator;
   }
   
+
+  void 
+  SpectrumCalculationDlg::executeSpectrum()
+  {
+    // Verify that there are oligomers in the list.
+
+    if(!mp_oligomerList)
+      return;
+
+    if(mp_oligomerList->isEmpty())
+      return;
+
+    if(!fetchValidateInputData())
+      {
+        QMessageBox::warning(0, 
+                             tr("massXpert - Spectrum Calculator"),
+                             tr("Please fix the input data first."),
+                             QMessageBox::Ok);
+        return;
+      }
+
+    double minMz = 1000000000;
+    double maxMz = 0;
+    double curMz = 0;
+
+    // List of lists of QPointF, that is list of spectra.
+    QList<QList<QPointF *> *> pointListList;
+
+    // For each list of QPointF, that is for each spectrum, store the
+    // increment that was used to perform the calculation, as this is
+    // going to be needed later when performing the final spectrum
+    // summing merge.
+
+    QList<double> incrementList;
+        
+    for(int iter = 0,
+          size = mp_oligomerList->size(); iter < size; ++iter)
+      {
+        Oligomer *oligomer = mp_oligomerList->at(iter);
+        
+        // 1. Does the user want a isotopic cluster calculation for
+        // each oligomer in the list? If so we have to manage a list
+        // of IsotopicPatternCalculator instances.
+
+        if(m_withCluster)
+          {
+            // Since we have to perform an isotopic cluster
+            // calculation, retrieve the elemental composition.
+            StringProp *prop = 
+              static_cast<StringProp *>(oligomer->
+                                        prop("ELEMENTAL_COMPOSITION"));
+            
+            if(!prop)
+              qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__);
+            
+            QString *formulaString = static_cast<QString *>(prop->data());
+            
+            Formula formula(*formulaString);
+
+            // We want to validate the formula and in the mean time
+            // construct the list of all the AtomCount objects(first
+            // param true), and since the formula is never reused we
+            // do not need to reset (second param false). m_atomList
+            // is a reference to the atom list of the polymer
+            // chemistry definition currently used in the caller
+            // calculator window.
+            if(!formula.validate(m_atomList, true, false))
+              {
+                m_ui.inputDataFeedbackLineEdit->setText(tr("Formula error"));
+                
+                return;
+              }
+
+            double mono = oligomer->mono();
+            double charge = oligomer->charge();
+
+            // Because we have the mono m/z, we can compute the fwhm:
+            double fwhm = (mono / m_resolution);
+            m_config.setFwhm(fwhm);
+            
+            double increment = (MXP_FWHM_PEAK_SPAN_FACTOR * fwhm) / 
+              m_config.pointNumber();
+
+            // But we have to take into account the charge:
+            if(charge)
+              increment = increment / charge;
+            
+            m_config.setIncrement(increment);
+            
+            qDebug() << __FILE__ << __LINE__
+                     << "index:" << iter << "\n"
+                     << "formula: " << formula.formula() << "\n"
+                     << "charge:" << charge << "\n"
+                     << "mono m/z:" << mono << "\n"
+                     << "avg m/z:" << oligomer->avg() << "\n"
+                     << "resolution:" << m_resolution << "\n"
+                     << "fwhm:" << fwhm << "\n"
+                     << "Whole config:" << m_config.config();
+            
+            IsotopicPatternCalculator *calculator = 
+              new IsotopicPatternCalculator(formula, charge,
+                                            m_maximumPeaks, 
+                                            m_minimumProbability,
+                                            m_atomList, m_config);
+            
+            // Perform the calculation...
+            QList<QPointF *>  &pointList = calculator->sumPeakShapes();
+
+            if(pointList.isEmpty())
+              qFatal("Fatal error at %s@%d.Aborting.", __FILE__, __LINE__);
+            
+            // What's the first point of that spectrum? Store the
+            // smallest value for the full spectrum constitution
+            // later-on.
+            curMz = calculator->firstPoint()->x();
+            minMz = (curMz < minMz ? curMz : minMz);
+            
+            // What's the last point of that spectrum? Store the
+            // greatest value for the full spectrum constitution
+            // later-on.
+            curMz = calculator->lastPoint()->x();
+            maxMz = (curMz > maxMz ? curMz : maxMz);
+            
+            QList<QPointF *> *newPointList = new QList<QPointF *>;
+            
+            calculator->transferPoints(newPointList);
+            pointListList.append(newPointList);
+
+            // Store along with the point list, the increment that was
+            // used for that calculation. We'll need it later when
+            // computing the whole spectrum.
+
+            incrementList.append(m_config.increment());
+            
+            // At this point we have the points, we can delete the
+            // calculator.
+            delete calculator;
+          }
+        else
+          {
+            // Not asking for an isotopic cluster to be computed for
+            // each oligomer. We still have one alternative: either
+            // mono mz or avg mz should be used as centroid to compute
+            // the peak shape.
+
+          }
+      }
+    // End of 
+    // for(int iter = 0, 
+    //         size = mp_oligomerList->size(); iter < size; ++iter)
+    
+    // At this point, with one method or the other, we should have
+    // as many allocated QList<QPointF *> * instances as there are
+    // oligomers. Make that sanity check.
+
+    if(pointListList.size() < mp_oligomerList->size())
+      {
+        qDebug() << __FILE__ << __LINE__
+                 << "Generated less unitary spectra than "
+          "there are oligomers.";
+      }
+    else
+      {
+        qDebug() << __FILE__ << __LINE__
+                 << "Done generating the unitary spectra for each oligomer.";
+      }
+    
+    
+    // To compute the spectrum, we have to summ all the points of
+    //  all the pointLists together. We know that the start of the
+    //  mz axis is at minMz and the end is at maxMz.
+            
+    QList<QPointF *> finalSpectrum;
+        
+    curMz = minMz;
+            
+    while(curMz <= maxMz)
+      {
+        qDebug() << __FILE__ << __LINE__
+                 << "Handling mz value:" << curMz;
+        
+        // curMz now has a mz value for which we have to sum all the
+        // intensities in each pointList.
+      
+        double summedIntensity = 0;
+      
+        // Iterate in each spectrum of the list of spectra (that
+        // is each point list of the list of point lists and seek
+        // the intensity at curMz. when found add that intensity
+        // to summedIntensity.
+
+        double increment = 0;
+        
+        for(int jter = 0,
+              jSize = pointListList.size(); jter < jSize; ++jter)
+          {
+            increment = incrementList.at(jter);
+                
+            QList<QPointF *> *curList = pointListList.at(jter);
+                
+            // We are iterating in the list of points of a
+            // spectrum. What is the intensity of the point at x=curMz
+            // ? We provide a tolerance for x corresponding to
+            // (increment / 2).
+                
+            for(int kter = 0,
+                  kSize = curList->size(); kter < kSize; ++kter)
+              {
+                QPointF *point = curList->at(kter);
+                    
+                double mz = point->x();
+                    
+                if(mz <= (curMz + increment / 2) &&
+                   mz >= (curMz - increment / 2))
+                  {
+                    summedIntensity += point->y();
+                        
+                    break;
+                  }
+                // Else, go on to next point. If not point is
+                // found at all, then, ok, we do not increment the
+                // summedIntensity variable.
+              }
+            // At this point we have finished iterating in a given
+            // spectrum (that is a point list).
+          }
+        // We have finished iterarting in all the point
+        // lists. Make a point (curMz,summedIntensity).
+            
+        QPointF *newPoint = new QPointF(curMz, summedIntensity);
+
+        finalSpectrum.append(newPoint);
+
+        qDebug() << __FILE__ << __LINE__
+                 << "Added new point:"
+                 << "x:" << newPoint->x() << "," << "y:" << newPoint->y()
+                 << "\n";
+                    
+        curMz += increment;
+      }
+    // End of while(curMz <= maxMz). That is, we have finished
+    // creating (x,y) pairs for the whole x axis, that is the mz
+    // ratio axis.
+
+    qDebug() << __FILE__ << __LINE__
+             << "Ended the creation of the final spectrum.";
+    
+
+    // We have a bunch of data to free.
+    
+    QPointF *point = 0;
+
+    for(int iter = 0,
+          iSize = pointListList.size(); iter < iSize; ++iter)
+      {
+        QList<QPointF *> *curList = pointListList.at(iter);
+        
+        foreach(point, *curList)
+          delete point;
+        
+        curList->clear();
+
+        delete curList;
+      }
+
+    qDebug() << __FILE__ << __LINE__
+             << "Done freeing up material.";
+      
+    foreach(point, finalSpectrum)
+      {
+        qDebug() << point->x() << " " << point->y();
+        
+        delete point;
+      }
+        
+    finalSpectrum.clear();
+  }
+    
+  
+    
+    
   
   void 
   SpectrumCalculationDlg::spectrumCalculationProgressValueChanged
diff --git a/gui/spectrumCalculationDlg.hpp b/gui/spectrumCalculationDlg.hpp
index c593196..8a194f8 100644
--- a/gui/spectrumCalculationDlg.hpp
+++ b/gui/spectrumCalculationDlg.hpp
@@ -52,6 +52,7 @@
 #include "formula.hpp"
 #include "peakShape.hpp"
 #include "globals.hpp"
+#include "oligomerList.hpp"
 
 
 namespace massXpert
@@ -80,10 +81,16 @@ namespace massXpert
     private:
     Ui::SpectrumCalculationDlg m_ui;
 
+    // This pointer might be 0 if this dialog window is called from
+    // the XpertCalc window.
+    const Polymer *mp_polymer;
+    
     SpectrumCalculationMode m_mode;
-      
+
     const QList<Atom *> &m_atomList;
-  
+
+    OligomerList *mp_oligomerList;
+      
     int m_validationErrors;
     
     QString m_filePath;
@@ -97,7 +104,10 @@ namespace massXpert
     PeakShapeConfig m_config;
     
     int m_charge;
-    
+
+    bool m_withMonoMass;
+    bool m_withCluster;
+        
     const PolChemDef &m_polChemDef;
 
     QString m_resultsString;
@@ -121,6 +131,8 @@ namespace massXpert
     bool fetchMzRatio(double * = 0, double * = 0);
         
     bool fetchValidateInputData();
+    bool fetchValidateInputDataIsotopicClusterMode();
+    bool fetchValidateInputDataSpectrumMode();
     
     void setInErrorStatus(const QString &);
 
@@ -130,23 +142,32 @@ namespace massXpert
     void debugPutStdErrBitset(QString /*file*/, int /*line*/, 
                               int = 0 /*value*/, 
                               const QString & = QString() /*descString*/);
-                            
-                    
+                                                                         
+    void executeCluster();
+    void executeSpectrum();
+                          
   private slots:
+    void massTypeRadioButtonToggled(bool);
+    void isotopicClusterCheckBoxToggled(bool);
+    
     void formulaEdited(const QString &);
     void chargeChanged(int);
     void pointsChanged(int);
     void resolutionChanged(int);
     void fwhmEdited(const QString &);
+
     void execute();
     void abort();
     void outputFile();
   public:
     SpectrumCalculationDlg(QWidget *parent,
+                           const Polymer *,
                            const QList<Atom *> &,
                            SpectrumCalculationMode);
     ~SpectrumCalculationDlg();
 
+    void setOligomerList(OligomerList *);
+    
   signals:
     void spectrumCalculationAborted();
                                 
diff --git a/gui/ui/spectrumCalculationDlg.ui b/gui/ui/spectrumCalculationDlg.ui
index dbce5ff..a3e96d1 100644
--- a/gui/ui/spectrumCalculationDlg.ui
+++ b/gui/ui/spectrumCalculationDlg.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>622</width>
-    <height>337</height>
+    <height>348</height>
    </rect>
   </property>
   <property name="windowTitle">
@@ -45,14 +45,14 @@
          <property name="title">
           <string>Input data</string>
          </property>
-         <layout class="QGridLayout" name="gridLayout_2">
-          <item row="0" column="0">
-           <widget class="QGroupBox" name="mzConfigGroupBox">
+         <layout class="QGridLayout" name="gridLayout_11">
+          <item row="0" column="0" rowspan="2">
+           <widget class="QGroupBox" name="mzGroupBox">
             <property name="title">
-             <string>m/z config.</string>
+             <string>m/z</string>
             </property>
             <layout class="QGridLayout" name="gridLayout">
-             <item row="0" column="0" colspan="4">
+             <item row="0" column="0" colspan="3">
               <layout class="QHBoxLayout" name="horizontalLayout">
                <item>
                 <widget class="QLabel" name="label_3">
@@ -80,7 +80,7 @@
                </property>
               </widget>
              </item>
-             <item row="1" column="1" colspan="3">
+             <item row="1" column="1" colspan="2">
               <widget class="QSpinBox" name="chargeSpinBox">
                <property name="minimum">
                 <number>1</number>
@@ -100,23 +100,32 @@
                </property>
               </widget>
              </item>
-             <item row="2" column="1" colspan="3">
+             <item row="2" column="1" colspan="2">
               <widget class="QLineEdit" name="monoMzRatioLineEdit"/>
              </item>
-             <item row="3" column="0">
-              <spacer name="horizontalSpacer">
+             <item row="3" column="1">
+              <spacer name="verticalSpacer_2">
                <property name="orientation">
-                <enum>Qt::Horizontal</enum>
+                <enum>Qt::Vertical</enum>
                </property>
                <property name="sizeHint" stdset="0">
                 <size>
-                 <width>25</width>
-                 <height>20</height>
+                 <width>20</width>
+                 <height>40</height>
                 </size>
                </property>
               </spacer>
              </item>
-             <item row="3" column="1">
+            </layout>
+           </widget>
+          </item>
+          <item row="0" column="1">
+           <widget class="QGroupBox" name="massTypeGroupBox">
+            <property name="title">
+             <string>Mass type</string>
+            </property>
+            <layout class="QGridLayout" name="gridLayout_2">
+             <item row="0" column="0">
               <widget class="QRadioButton" name="monoRadioButton">
                <property name="text">
                 <string>Mono</string>
@@ -126,78 +135,46 @@
                </property>
               </widget>
              </item>
-             <item row="3" column="2">
-              <spacer name="horizontalSpacer_3">
-               <property name="orientation">
-                <enum>Qt::Horizontal</enum>
-               </property>
-               <property name="sizeHint" stdset="0">
-                <size>
-                 <width>10</width>
-                 <height>20</height>
-                </size>
-               </property>
-              </spacer>
-             </item>
-             <item row="3" column="3">
+             <item row="0" column="1">
               <widget class="QRadioButton" name="avgRadioButton">
                <property name="text">
                 <string>Avg</string>
                </property>
               </widget>
              </item>
-             <item row="3" column="4">
-              <spacer name="horizontalSpacer_2">
-               <property name="orientation">
-                <enum>Qt::Horizontal</enum>
-               </property>
-               <property name="sizeHint" stdset="0">
-                <size>
-                 <width>10</width>
-                 <height>20</height>
-                </size>
+             <item row="1" column="0">
+              <widget class="QCheckBox" name="isotopicClusterCheckBox">
+               <property name="text">
+                <string>Isotopic cluster</string>
                </property>
-              </spacer>
+              </widget>
              </item>
             </layout>
            </widget>
           </item>
-          <item row="0" column="1" rowspan="2">
-           <widget class="QGroupBox" name="spectrumConfigGroupBox">
+          <item row="1" column="1" rowspan="2">
+           <widget class="QGroupBox" name="spectrumGroupBox">
             <property name="title">
-             <string>Spectrum config.</string>
+             <string>Spectrum</string>
             </property>
             <layout class="QFormLayout" name="formLayout_3">
-             <item row="3" column="0">
-              <widget class="QLabel" name="label_9">
-               <property name="text">
-                <string>Min. probability:</string>
-               </property>
-              </widget>
-             </item>
-             <item row="4" column="0">
-              <widget class="QLabel" name="label_6">
+             <property name="fieldGrowthPolicy">
+              <enum>QFormLayout::ExpandingFieldsGrow</enum>
+             </property>
+             <item row="0" column="0">
+              <widget class="QRadioButton" name="gaussianRadioButton">
                <property name="text">
-                <string>Max. &peaks:</string>
+                <string>gaussian</string>
                </property>
-               <property name="buddy">
-                <cstring>maximumPeaksSpinBox</cstring>
+               <property name="checked">
+                <bool>true</bool>
                </property>
               </widget>
              </item>
-             <item row="4" column="1">
-              <widget class="QSpinBox" name="maximumPeaksSpinBox">
-               <property name="toolTip">
-                <string>Maximum number of peaks that must be calculated</string>
-               </property>
-               <property name="minimum">
-                <number>20</number>
-               </property>
-               <property name="maximum">
-                <number>100000</number>
-               </property>
-               <property name="value">
-                <number>20</number>
+             <item row="0" column="1">
+              <widget class="QRadioButton" name="lorentzianRadioButton">
+               <property name="text">
+                <string>lorentzian</string>
                </property>
               </widget>
              </item>
@@ -221,23 +198,6 @@
                </property>
               </widget>
              </item>
-             <item row="0" column="0">
-              <widget class="QRadioButton" name="gaussianRadioButton">
-               <property name="text">
-                <string>gaussian</string>
-               </property>
-               <property name="checked">
-                <bool>true</bool>
-               </property>
-              </widget>
-             </item>
-             <item row="0" column="1">
-              <widget class="QRadioButton" name="lorentzianRadioButton">
-               <property name="text">
-                <string>lorentzian</string>
-               </property>
-              </widget>
-             </item>
              <item row="2" column="0">
               <widget class="QLabel" name="label_13">
                <property name="text">
@@ -255,6 +215,13 @@
                </property>
               </widget>
              </item>
+             <item row="3" column="0">
+              <widget class="QLabel" name="label_9">
+               <property name="text">
+                <string>Min. probability:</string>
+               </property>
+              </widget>
+             </item>
              <item row="3" column="1">
               <widget class="QLineEdit" name="minimumProbabilityLineEdit">
                <property name="toolTip">
@@ -262,26 +229,39 @@
                </property>
               </widget>
              </item>
-             <item row="5" column="1">
-              <spacer name="verticalSpacer_3">
-               <property name="orientation">
-                <enum>Qt::Vertical</enum>
+             <item row="4" column="0">
+              <widget class="QLabel" name="label_6">
+               <property name="text">
+                <string>Max. &peaks:</string>
                </property>
-               <property name="sizeHint" stdset="0">
-                <size>
-                 <width>20</width>
-                 <height>40</height>
-                </size>
+               <property name="buddy">
+                <cstring>maximumPeaksSpinBox</cstring>
                </property>
-              </spacer>
+              </widget>
+             </item>
+             <item row="4" column="1">
+              <widget class="QSpinBox" name="maximumPeaksSpinBox">
+               <property name="toolTip">
+                <string>Maximum number of peaks that must be calculated</string>
+               </property>
+               <property name="minimum">
+                <number>20</number>
+               </property>
+               <property name="maximum">
+                <number>100000</number>
+               </property>
+               <property name="value">
+                <number>20</number>
+               </property>
+              </widget>
              </item>
             </layout>
            </widget>
           </item>
-          <item row="1" column="0">
-           <widget class="QGroupBox" name="resolutionConfigGroupBox">
+          <item row="2" column="0">
+           <widget class="QGroupBox" name="resolutionGroupBox">
             <property name="title">
-             <string>Resolution config.</string>
+             <string>Resolution</string>
             </property>
             <layout class="QGridLayout" name="gridLayout_5">
              <item row="0" column="0">
@@ -434,6 +414,19 @@ p, li { white-space: pre-wrap; }
             </property>
            </widget>
           </item>
+          <item row="2" column="1">
+           <spacer name="verticalSpacer">
+            <property name="orientation">
+             <enum>Qt::Vertical</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>20</width>
+              <height>40</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
          </layout>
         </widget>
        </item>
diff --git a/lib/isotopicPatternCalculator.cpp b/lib/isotopicPatternCalculator.cpp
index 7c0aebb..d3f894c 100644
--- a/lib/isotopicPatternCalculator.cpp
+++ b/lib/isotopicPatternCalculator.cpp
@@ -144,7 +144,7 @@ namespace massXpert
     freeClearPeakCentroidList();
     freeClearTempPeakCentroidList();
     freeClearPeakShapeList();
-    freeClearSpectrum();
+    freeClearPointList();
   }
 
 
@@ -164,9 +164,9 @@ namespace massXpert
 
 
   const QList<QPointF *> &
-  IsotopicPatternCalculator::spectrum() const
+  IsotopicPatternCalculator::pointList() const
   {
-    return m_spectrum;
+    return m_pointList;
   }
   
 
@@ -236,12 +236,12 @@ namespace massXpert
   
   
   void
-  IsotopicPatternCalculator::freeClearSpectrum()
+  IsotopicPatternCalculator::freeClearPointList()
   {
-    while(!m_spectrum.isEmpty())
-      delete m_spectrum.takeFirst();
+    while(!m_pointList.isEmpty())
+      delete m_pointList.takeFirst();
 
-    m_spectrum.clear();
+    m_pointList.clear();
   }
   
   
@@ -349,10 +349,10 @@ namespace massXpert
   
 
   QList<QPointF *>  &
-  IsotopicPatternCalculator::calculateSpectrum()
+  IsotopicPatternCalculator::sumPeakShapes()
   {
-    // Clear the spectrum.
-    freeClearSpectrum();
+    // Clear the point list.
+    freeClearPointList();
     
     // Make sure that we have computed each individual peak shape for
     // the centroids. If not, then do it first.
@@ -362,7 +362,7 @@ namespace massXpert
     if(!peakShapeListSize)
       {
         if(!calculatePeakShapes())
-          return m_spectrum;
+          return m_pointList;
 
         peakShapeListSize = m_peakShapeList.size();
       }
@@ -380,10 +380,10 @@ namespace massXpert
     // curves.
 
     // Peak shapes should be generated from left to right in the
-    // spectrum view, that is from lowest mz to higest mz. So,
-    // logically, the first point of the first peak shape should be
-    // the point of lowest mz. Likewise, the last point of the last
-    // peak shape should be the highest mz.
+    // pointList spectral view, that is from lowest mz to higest
+    // mz. So, logically, the first point of the first peak shape
+    // should be the point of lowest mz. Likewise, the last point of
+    // the last peak shape should be the highest mz.
     
     PeakShape *peakShape = 0;
     QPointF *point = 0;
@@ -434,10 +434,10 @@ namespace massXpert
       }
 #endif
 
-    // At this point we know that our mass spectrum should range
-    // [minMz -- maxMz]. We can perform the actual sum of all the peak
-    // shapes. The result of the sum should go into the spectrum list
-    // of points.
+    // At this point we know that our mass point list (the spectral
+    // view of the isotopic cluster) should range [minMz -- maxMz]. We
+    // can perform the actual sum of all the peak shapes. The result
+    // of the sum should go into the spectral list of points.
 
     double curMz = minMz;
   
@@ -461,24 +461,24 @@ namespace massXpert
       
         QPointF *point = new QPointF(curMz, summedIntensity);
         
-        m_spectrum.append(point);
+        m_pointList.append(point);
 
         curMz += m_config.increment();
       }
     
-    return m_spectrum;
+    return m_pointList;
   }
   
   
   QString *
-  IsotopicPatternCalculator::spectrumAsString() const
+  IsotopicPatternCalculator::pointListAsString() const
   {
     QString *text = new QString();
     
-    for(int iter = 0, size = m_spectrum.size();
+    for(int iter = 0, size = m_pointList.size();
         iter < size ; ++iter)
       {
-        QPointF *point = m_spectrum.at(iter);
+        QPointF *point = m_pointList.at(iter);
         
         text->append(QString().setNum(point->x(), 'f', 10));
         text->append(" ");
@@ -489,6 +489,54 @@ namespace massXpert
     return text;
   }
   
+  
+  QList<QPointF *> *
+  IsotopicPatternCalculator::duplicatePointList() const
+  {
+    QList<QPointF *> *pointList = new QList<QPointF *>;
+    
+    for(int iter = 0, size = m_pointList.size();
+        iter < size ; ++iter)
+      {
+        QPointF *point = new QPointF(*(m_pointList.at(iter)));
+        pointList->append(point);
+      }
+    
+    return pointList;
+  }
+  
+
+  int
+  IsotopicPatternCalculator::transferPoints(QList<QPointF *> *pointList)
+  {
+    if(!pointList)
+      qFatal("Fatal error at %s@%d.Aborting.", __FILE__, __LINE__);
+
+    int count = 0;
+    
+    while(m_pointList.size())
+      {
+        pointList->append(m_pointList.takeFirst());
+        ++count;
+      }
+    
+    return count;
+  }
+  
+  
+  QPointF *
+  IsotopicPatternCalculator::firstPoint() const
+  {
+    return m_pointList.first();
+  }
+  
+
+  QPointF *
+  IsotopicPatternCalculator::lastPoint() const
+  {
+    return m_pointList.last();
+  }
+  
 
   int
   IsotopicPatternCalculator::accountAtomCount(const AtomCount *atomCount)
diff --git a/lib/isotopicPatternCalculator.hpp b/lib/isotopicPatternCalculator.hpp
index bb8ed44..ca97dcf 100644
--- a/lib/isotopicPatternCalculator.hpp
+++ b/lib/isotopicPatternCalculator.hpp
@@ -59,7 +59,7 @@ namespace massXpert
         
     const QList<Atom *> &m_atomRefList;
     
-    QList<QPointF *> m_spectrum;
+    QList<QPointF *> m_pointList;
     
     PeakShapeConfig m_config;
 
@@ -80,7 +80,7 @@ namespace massXpert
     void freeClearPeakCentroidList();
     void freeClearTempPeakCentroidList();
     void freeClearPeakShapeList();
-    void freeClearSpectrum();
+    void freeClearPointList();
     
     int accountAtomCount(const AtomCount *);
     int updatePeakCentroidListWithAtom(const Atom *);
@@ -105,12 +105,17 @@ namespace massXpert
     const QList<PeakCentroid *> &peakCentroidList() const;
     QString *peakCentroidListAsString() const;
 
-    const QList<QPointF *> &spectrum() const;
-    QString *spectrumAsString() const;
+    const QList<QPointF *> &pointList() const;
+    QString *pointListAsString() const;
+    QList<QPointF *> *duplicatePointList() const;
+    int transferPoints(QList<QPointF *> *);
+    
+    QPointF *firstPoint() const;
+    QPointF *lastPoint() const;
     
     int calculatePeakCentroids();
     int calculatePeakShapes();
-    QList<QPointF *> &calculateSpectrum();
+    QList<QPointF *> &sumPeakShapes();
     
 
   signals:

-- 
massXpert mass spectrometry suite: debian packaging



More information about the Debichem-commits mailing list