[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:28:42 UTC 2011


The following commit has been merged in the debian branch:
commit 906f095351bbee84ff8af2b66929d36ded05d72a
Author: Filippo Rusconi (Debian Maintainer) <rusconi-debian at laposte.net>
Date:   Thu Jun 16 23:23:09 2011 +0200

    First buildable version for the reimplementation of the isotopic pattern calculation stuff. Still lots to do.

diff --git a/gui/application.qrc b/gui/application.qrc
index 8337116..f3d0145 100644
--- a/gui/application.qrc
+++ b/gui/application.qrc
@@ -1,5 +1,5 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
+<RCC>
+  <qresource>
     <file>images/copy.png</file>
     <file>images/cut.png</file>
     <file>images/new.png</file>
@@ -10,5 +10,7 @@
     <file>images/redled.png</file>
     <file>images/splashscreen.png</file>
     <file>images/massxpert-icon-32.png</file>
-</qresource>
+    <file>images/smile-bad.png</file>
+    <file>images/smile-fine.png</file>
+  </qresource>
 </RCC>
diff --git a/gui/calculatorWnd.hpp b/gui/calculatorWnd.hpp
index 83be5c0..629ea02 100644
--- a/gui/calculatorWnd.hpp
+++ b/gui/calculatorWnd.hpp
@@ -93,7 +93,7 @@ namespace massXpert
 
     bool initialize();
   
-    const PolChemDef & polChemDef();
+    const PolChemDef &polChemDef();
     QString polChemDefName();
       
     void updateWindowTitle();
diff --git a/gui/isotopicPatternCalculationDlg.cpp b/gui/isotopicPatternCalculationDlg.cpp
index 7dbc785..1728fe7 100644
--- a/gui/isotopicPatternCalculationDlg.cpp
+++ b/gui/isotopicPatternCalculationDlg.cpp
@@ -78,22 +78,42 @@ namespace massXpert
 
   IsotopicPatternCalculationDlg::IsotopicPatternCalculationDlg 
  (QWidget *parent, const QList<Atom *> &atomList)
-    : QDialog(parent), m_atomList(atomList)
+   : QDialog(parent), m_atomList(atomList),
+     m_polChemDef(static_cast<CalculatorWnd *>(parent)->polChemDef())
   {
     Q_ASSERT(parent);
 
     m_aborted = false;
+    
+    // When the window is created the formula line edit is empty, so
+    // at least that data has an error. The ionization data is most
+    // probably not erroneous because it comes from the polymer
+    // chemistry definition or from the caller.
+    m_validationErrors = MXP_VALIDATION_FORMULA_ERRORS;
+    
     m_filePath = "";
   
     m_ui.setupUi(this);
 
     // Set the name of the polymer chemistry definition.
 
-    const PolChemDef & polChemDef = 
-      static_cast<CalculatorWnd *>(parent)->polChemDef();
-    m_ui.polChemDefLabel->setText(polChemDef.name());
+    m_ui.polChemDefLabel->setText(m_polChemDef.name());
   
-
+    // By default we want a gaussian-type curve.
+    m_curveType = MXP_CURVE_TYPE_GAUSSIAN;
+    
+    // Feed the ionizeRule widgets with the data. If there is an error
+    // the MXP_VALIDATION_IONIZERULE_ERRORS bit will be automatically set.
+    m_ionizeRule = m_polChemDef.ionizeRule();
+    m_ui.ionizationChargeSpinBox->setValue(m_ionizeRule.charge());
+    m_ui.ionizationLevelSpinBox->setValue(m_ionizeRule.level());
+    m_ui.ionizationFormulaLineEdit->setText(m_ionizeRule.formula());
+
+    // Calculate and show the resulting charge of the ionizable.
+    QString charge;
+    m_charge = m_ionizeRule.charge() * m_ionizeRule.level();
+    charge.setNum(m_charge);
+    m_ui.chargeLabel->setText(charge);
 
     m_ui.minimumProbabilityDoubleSpinBox->setRange(0, 1000000);
     m_ui.minimumProbabilityDoubleSpinBox->setValue(0.0001);
@@ -103,14 +123,16 @@ namespace massXpert
     m_ui.maximumPeaksSpinBox->setValue(1000);
     m_maximumPeaks = 1000;
   
-    m_ui.chargeSpinBox->setRange(0, 1000000);
-    m_ui.chargeSpinBox->setValue(1);
-    m_charge = 1;
-  
+    // Resolution and FWHM stuff
     m_ui.resolutionSpinBox->setRange(0, 1000000);
-    m_ui.resolutionSpinBox->setValue(15000);
-    m_resolution = 15000;
-  
+    m_ui.resolutionSpinBox->setValue(0);
+    m_resolution = 0;
+    m_fwhm = 0;
+    // Since both values above are not correct, set the corresponding
+    // bits to the validation error int.
+    m_validationErrors |= MXP_VALIDATION_RESOLUTION_ERRORS;
+    m_validationErrors |= MXP_VALIDATION_FWHM_ERRORS;
+        
     m_ui.progressBar->setRange(0, 100);
     m_ui.progressBar->setValue(0);
 
@@ -124,6 +146,36 @@ namespace massXpert
 
     settings.endGroup();
 
+    connect(m_ui.ionizationFormulaLineEdit,
+            SIGNAL(textChanged(const QString &)),
+            this,
+            SLOT(ionizationDataChanged()));
+        
+    connect(m_ui.ionizationChargeSpinBox,
+            SIGNAL(valueChanged(int)),
+            this,
+            SLOT(ionizationDataChanged()));
+    
+    connect(m_ui.ionizationLevelSpinBox,
+            SIGNAL(valueChanged(int)),
+            this,
+            SLOT(ionizationDataChanged()));
+    
+    connect(m_ui.formulaLineEdit,
+            SIGNAL(textChanged(const QString &)),
+            this,
+            SLOT(formulaChanged(const QString &)));
+
+    connect(m_ui.resolutionSpinBox,
+            SIGNAL(valueChanged(int)),
+            this,
+            SLOT(resolutionChanged(int)));
+
+    connect(m_ui.fwhmLineEdit,
+            SIGNAL(textEdited(const QString &)),
+            this,
+            SLOT(fwhmEdited(const QString &)));
+
     connect(m_ui.executePushButton,
 	     SIGNAL(clicked()),
 	     this,
@@ -162,8 +214,6 @@ namespace massXpert
 
   IsotopicPatternCalculationDlg::~IsotopicPatternCalculationDlg()
   {
-  
-  
   }
 
 
@@ -172,58 +222,46 @@ namespace massXpert
   {
     Application *application = static_cast<Application *>(qApp);
 
-    QString formula = m_ui.formulaLineEdit->text();
-  
-    if (!formula.isEmpty())
-      m_formula.setFormula(formula);
-    else
+    // 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).
+
+    if(m_validationErrors != MXP_VALIDATION_ERRORS_NONE)
       {
-	QMessageBox::warning(0,
-			      tr("massXpert: Isotopic Pattern Calculation"),
-			      tr("Enter a valid formula."),
-			      QMessageBox::Ok);
-	return false;
+        return false;
       }
-  
-    // We want to validate the formula and in the mean time construct
-    // the list of all the AtomCount objects(first true), and since
-    // the formula is reused we also ensure that that list is reset
-    //(second true).
-  
-    if (!m_formula.validate(m_atomList, true, true))
+    
+    // We still have to fetch a number of parameters.
+
+    // Get to know if we want gaussian or lorentzian curves.
+    if(m_ui.gaussianRadioButton->isChecked())
       {
-	QMessageBox::warning(0,
-			      tr("massXpert: Isotopic Pattern Calculation"),
-			      tr("Formula(%1) is not valid.")
-			      .arg(formula),
-			      QMessageBox::Ok);
-	return false;
+        m_curveType = MXP_CURVE_TYPE_GAUSSIAN;
       }
+    else
+      {
+        m_curveType = MXP_CURVE_TYPE_LORENTZIAN;
+      }
+  
   
     // Shall we use localization for all the numerical output?
-    bool locale = m_ui.localeCheckBox->checkState() == Qt::Checked ?
+    bool isUsingLocale = m_ui.localeCheckBox->checkState() == Qt::Checked ?
       true : false;
   
-
     int totAtoms = m_formula.totalAtoms();
     m_ui.progressBar->setRange(0, totAtoms);
   
     int totIsotopes = m_formula.totalIsotopes(m_atomList);
 
-    m_mono = 0;
-    m_avg = 0;
-  
-    if (!m_formula.accountMasses(m_atomList, &m_mono, &m_avg, 1))
-      return false;
-  
     QString textEditText;
 
-    if (locale)
+    if (isUsingLocale)
       textEditText += tr("INPUT\n=====\n\nformula: %1\n"
 			  "Mono Mass: %2 \t Avg mass: %3\n"
 			  "Total number of atoms: %4\n"
 			  "Total number of isotopes: %5")
-	.arg(formula)
+	.arg(m_formula.formula())
 	.arg(application->locale().
 	      toString(m_mono, 'f', MXP_OLIGOMER_DEC_PLACES))
 	.arg(application->locale().
@@ -234,7 +272,7 @@ namespace massXpert
       textEditText += tr("INPUT\n=====\n\nformula: %1\n"
 			  "Mono mass: %2 \t Avg mass: %3\n"
 			  "Total number of 1) atoms: %4 ; 2) isotopes: %5\n\n")
-	.arg(formula)
+	.arg(m_formula.formula())
 	.arg(QString().setNum(m_mono, 'f', MXP_OLIGOMER_DEC_PLACES))
 	.arg(QString().setNum(m_avg, 'f', MXP_OLIGOMER_DEC_PLACES))
 	.arg(totAtoms)
@@ -258,104 +296,500 @@ namespace massXpert
 	return false;
       }
 
-    m_charge = m_ui.chargeSpinBox->value();
-    m_resolution = m_ui.resolutionSpinBox->value();
+    // 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_points = m_ui.pointsSpinBox->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_points;
+
+    // First however, see if the user wants to use the FWHM value or
+    // the resolution.
+    
+    if(m_fwhm)
+      {
+        // FWHM is not zero, which means the user has set a value for
+        // it. Keep it.
+      }
+    else
+      {
+        // We have to compute the FWHM starting from the mz ratio and
+        // the resolution.
+        
+        m_fwhm = m_mono / m_resolution;
+      }
+
+    // Now set the increment.
+    m_increment = m_ui.incrementSpinBox->value();
+    if(!m_increment)
+      m_increment = 2*(m_fwhm / m_points);
+    
+    // Set the maximum number of peaks in the isotopic curve.
     m_maximumPeaks = m_ui.maximumPeaksSpinBox->value();
- 
-    textEditText += tr("Charge: %1 ; Resolution: %2 ; Maximum peaks: %3 ;")
-      .arg(m_charge)
-      .arg(m_resolution)
-      .arg(m_maximumPeaks);
+    QString fwhmString = m_ui.fwhmLineEdit->text();
     
+    // Set the minimum probability each isotopic peak must have to be
+    // retained in the final curve.
     m_minimumProbability = m_ui.minimumProbabilityDoubleSpinBox->value();
-    textEditText += tr(" Minimum probability: ");
-    if (locale)
-      textEditText += application->locale().
-	toString(m_minimumProbability, 'f', MXP_OLIGOMER_DEC_PLACES);
-    else
-      textEditText += QString().
-	setNum(m_minimumProbability, 'f', MXP_OLIGOMER_DEC_PLACES);;
-  
-    textEditText += 
-      tr("\n\nGaussian simulation of a single peak is performed by "
-	  "computing 25 points on each side of the isotopic mass "
-	  "according to the following exponential:\n"
-	  "f(x) = relativeIntensity * exp(( -(x - mono)^2 ) / c^2 )\n\n"
-	  "Full Width At Half Maximum = "
-	  "(mono / resolution) = 2 * sqrt(ln(2) * c \n");
+    
+    return true;
+  }
+
   
-    double fullWidthHalfMax = m_mono / m_resolution;
-    textEditText += tr("FWHM = ");
-    if (locale)
-      textEditText += application->locale().
-	toString(fullWidthHalfMax, 'f', MXP_OLIGOMER_DEC_PLACES);
-    else
-      textEditText += QString().
-	setNum(fullWidthHalfMax, 'f', MXP_OLIGOMER_DEC_PLACES);;
+  bool
+  IsotopicPatternCalculationDlg::fetchIonizationRuleData(IonizeRule *ionizeRule)
+  {
+    if(!ionizeRule)
+      qFatal("Fatal error at %s@%d.Aborting.", __FILE__, __LINE__);
+    
+    // We feed the ionizeRule instance with the currently inserted
+    // data in the ionize rule widgets.
+
+    QString text = m_ui.ionizationFormulaLineEdit->text();
+    Formula formula(text);
+    if (!formula.validate(m_atomList, false, true))
+      return false;
+    
+    int unitCharge = m_ui.ionizationChargeSpinBox->value();
+    int level = m_ui.ionizationLevelSpinBox->value();
+    
+    m_charge = unitCharge * level;
+    QString ionChargeString;
+    ionChargeString.setNum(m_charge);
+    m_ui.chargeLabel->setText(ionChargeString);
+    
+    ionizeRule->setFormula(text);
+    ionizeRule->setCharge(unitCharge);
+    ionizeRule->setLevel(level);
+
+    // Validate the ionization rule, because it might be set with
+    // m_isValid=false (in particular if the instance was constructed
+    // with non contructor parameters).
+
+    if(!ionizeRule->validate(m_atomList))
+      return false;
+        
+    return true;
+  }
   
-    textEditText += "\n";
 
-    double c = fullWidthHalfMax /(2 * sqrt(log(2)));
-    double c2 = pow(c, 2);
+  // Returns false if formula is bad or aborts if calculation fails..
+  bool
+  IsotopicPatternCalculationDlg::fetchFormulaMass(double *mono, double *avg)
+  {
+    // Check if there are currently errors set.
+    
+    if((m_validationErrors | MXP_VALIDATION_FORMULA_ERRORS) ==
+       MXP_VALIDATION_FORMULA_ERRORS)
+      return false;
+    
+    double monoMass = 0;
+    double avgMass = 0;
+    
+    // It is impossible that we have an error here, since the formula
+    // was previously validated (MXP_VALIDATION_FORMULA_ERRORS above).
+    if (!m_formula.accountMasses(m_atomList, &monoMass, &avgMass, 1))
+      qFatal("Fatal error at %s@%d.Aborting.", __FILE__, __LINE__);
+    
+    if(mono)
+      *mono = monoMass;
+    
+    if(avg)
+      *avg = avgMass;
+
+    // qDebug() << __FILE__ << __LINE__
+    //          << "Formula mono/avg masses:"
+    //          << monoMass << "/" << avgMass;
 
-    textEditText += tr("with c = ");
-    if (locale)
-      textEditText += application->locale().
-	toString(c, 'f', MXP_OLIGOMER_DEC_PLACES);
-    else
-      textEditText += QString().setNum(c, 'f', MXP_OLIGOMER_DEC_PLACES);;
+    return true;
+  }
+    
+  // Returns false if the formula is not validated and aborts if an
+  // error occurs while the formula was validated.
+  bool
+  IsotopicPatternCalculationDlg::fetchMzRatio(double *mono, double *avg)
+  {
+    // Check if there are currently errors set either in the formula
+    // or in the ionization rule.
+
+    // Show what's the value of the errors.
+    debugPutStdErr(__FILE__, __LINE__,
+                   m_validationErrors, "m_validationErrors");
+    
+    if((m_validationErrors | MXP_VALIDATION_FORMULA_ERRORS) ==
+       MXP_VALIDATION_FORMULA_ERRORS)
+      {
+        qDebug() << __FILE__ << __LINE__ 
+                 << "Returning false";
+        
+        return false;
+      }
+
+    if ((m_validationErrors | MXP_VALIDATION_IONIZERULE_ERRORS) ==
+        MXP_VALIDATION_IONIZERULE_ERRORS)
+      {
+        qDebug() << __FILE__ << __LINE__ 
+                 << "Returning false";
+        
+        return false;
+      }
+    
+    // The ionization data have already been automatically fetched and
+    // set to m_ionizeRule when the data in the widgets changed using
+    // the correponding slot.
+
+    // Same for the formula in m_formula.
+    
+    // We can compute the m/z ratio.
+    
+    double monoMass = 0;
+    double avgMass = 0;
+
+    fetchFormulaMass(&monoMass, &avgMass);
+
+    qDebug() << __FILE__ << __LINE__ 
+             << "monoMass:" << monoMass
+             << "avgMass:" << avgMass;
+    
+    // Note that the only acceptable value returned here is mono > 0,
+    // because the formula was validated and thus mass calculation
+    // should not fail. Indeed, if there is a failure in the called
+    // function, qFatal is triggered. No need, thus, to check the
+    // status of the call. It cannot fail.
+    
+    // Compute the m/z ratio.
+    
+    Ponderable ponderable(monoMass, avgMass);
+    
+    // We create an ionizable using the ponderable above, which has
+    // masses computed only with the formula, that is for a
+    // non-ionized molecule.
+    Ionizable ionizable(&m_polChemDef, QString("NOT_SET"),
+                        ponderable, m_ionizeRule, false);
+    
+    // Set the charge of the ionizable. That is not the charge of
+    // ionizeRule ! That is the real charge of the ion ! Get it out of
+    // the chargeLabel, which allows us to track if errors were
+    // silently passing by.
+
+    bool ok = false;
+    
+    int ionCharge = m_ui.chargeLabel->text().toInt(&ok);
+
+    if(!ionCharge && !ok)
+      qFatal("Fatal error at %s@%d.Aborting.", __FILE__, __LINE__);
+    
+    // qDebug() << __FILE__ << __LINE__
+    //          << "The ion whole charge is:" << ionCharge;
+
+    // The ionization will be performed automatically upon setting the
+    // charge of the ion !  The ionization above must perform
+    // correctly, because the ionizable was created not ionized. Thus
+    // the call below has to return 1.
+
+    int res = ionizable.setCharge(ionCharge);
+    
+    // qDebug() << __FILE__ << __LINE__
+    //          << "Ionization result: " << res;
+    
+    if (res != 1)
+      qFatal("Fatal error at %s@%d.Aborting.", __FILE__, __LINE__);
+    
+    // At this point the ionizable has the right mzRatio.
+    
+    if(mono)
+      *mono = ionizable.mono();
+    
+    if(avg)
+      *avg =  ionizable.mono();
+
+    return true;
+  }
   
-    textEditText += tr(" and c^2 = ");
-    if (locale)
-      textEditText += application->locale().
-	toString(c2, 'f', MXP_OLIGOMER_DEC_PLACES);
-    else
-      textEditText += QString().setNum(c2, 'f', MXP_OLIGOMER_DEC_PLACES);;
+
+  void
+  IsotopicPatternCalculationDlg::ionizationDataChanged()
+  {
+    // When text changes, we have to update the smiley to indicate if
+    // the formula is OK or not.
+    IonizeRule ionizeRule;
+    
+    // The call below will take care of setting m_charge to the proper
+    // value.
+    if(!fetchIonizationRuleData(&ionizeRule))
+      {
+        // Set the error bit.
+        m_validationErrors |= MXP_VALIDATION_IONIZERULE_ERRORS;
+
+        m_ui.monoMzRatioLineEdit->setText("0.000");
+        m_ui.chargeLabel->setText("0");
+        m_ui.inputDataFeedbackLineEdit->setText(tr("Ionization data error"));
+        
+        return ;
+      }
+    
+    // Clear the bit as there is no error here.
+    m_validationErrors &= ~MXP_VALIDATION_IONIZERULE_ERRORS;
+
+    m_ui.inputDataFeedbackLineEdit->setText(tr("Ionization data fine"));
+
+    // Now that we know the ionization rule is valid, set it to the
+    // member instance.
+    m_ionizeRule = ionizeRule;
+
+    updateMzRatio();
+    
+    return;
+  }
   
-    textEditText += "\n============================================\n\n";
+  void 
+  IsotopicPatternCalculationDlg::resolutionChanged(int value)
+  {
+    // 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
+    // will be the value taken into account.
+
+    if(value <= 0)
+      {
+        // Tell the user to set a valid FWHM value, then.
+        m_ui.inputDataFeedbackLineEdit->setText
+          (tr("Set a valid FWHM value"));
+            
+        m_ui.resolutionSpinBox->setValue(0);
+        
+        // Clear the bit as there is no error here.
+        m_validationErrors &= ~MXP_VALIDATION_RESOLUTION_ERRORS;
+
+        return;
+      }
+    
+    m_resolution = value;
+    
+    m_ui.inputDataFeedbackLineEdit->setText
+      (tr("Will use the resolution"));
+
+    // Clear the bit as there is no error here.
+    m_validationErrors &= ~MXP_VALIDATION_RESOLUTION_ERRORS;
+
+    // Clear the fwhm value, as we want to use the resolution and
+    // clear the error bit also, so we are all clean.
+
+    m_ui.fwhmLineEdit->setText("0");
+    m_fwhm = 0;
+    m_validationErrors &= ~MXP_VALIDATION_FWHM_ERRORS;
+    
+    return;
+  }
   
-    // Out put some text in the textEdit:
-    m_ui.resultTextEdit->append(textEditText);
+
+  void 
+  IsotopicPatternCalculationDlg::fwhmEdited(const QString &text)
+  {
+    // If the text was edited in the line edit, that means that the
+    // user wants the FWHM to be taken into account for calculation of
+    // the peak width, and not the resolution. Only if FWHM is set to
+    // 0, resolution will be the value taken into account.
     
-    return true;
+    QString txt = m_ui.fwhmLineEdit->text();
+    
+    bool ok = false;
+    
+    int fwhmValue = txt.toInt(&ok);
+    
+    if(!fwhmValue && !ok)
+      {
+        // Set the error bit.
+        m_validationErrors |= MXP_VALIDATION_FWHM_ERRORS;
+
+        m_ui.inputDataFeedbackLineEdit->setText
+          (tr("Fix the FWHM value, please"));
+        
+        return;
+      }
+    
+    // But the value might be faithfully 0, if the user is telling us
+    // that she wants to take the resolution into account and not the
+    // FWHM.
+
+    if(!fwhmValue)
+      {
+        m_ui.inputDataFeedbackLineEdit->setText
+          (tr("Set a valid resolution value"));
+
+        // Clear the bit as there is no error here.
+        m_validationErrors &= ~MXP_VALIDATION_FWHM_ERRORS;
+
+        return;
+      }
+    
+    // At this point we know that fwhmValue contains a proper value.
+    
+    m_ui.inputDataFeedbackLineEdit->setText
+      (tr("Will use the FWHM"));
+    
+    m_validationErrors &= ~MXP_VALIDATION_FWHM_ERRORS;
+
+    m_fwhm = fwhmValue;
+
+    // Set the resolution spinbox to 0 and clear the associated
+    // validation error bit.
+    m_resolution = 0;
+    m_ui.resolutionSpinBox->setValue(0);
+    m_validationErrors &= ~MXP_VALIDATION_RESOLUTION_ERRORS;
+    
+    return;
   }
 
+    
 
   void 
-  IsotopicPatternCalculationDlg::execute()
+  IsotopicPatternCalculationDlg::formulaChanged(const QString &text)
   {
+    // New text contains a new formula. Check it.
+    
+    if(text.isEmpty())
+      {
+        // Set the error bit.
+        m_validationErrors |= MXP_VALIDATION_FORMULA_ERRORS;
+
+        m_ui.monoMzRatioLineEdit->setText("0.000");
+        m_ui.inputDataFeedbackLineEdit->setText(tr("Formula error"));
+
+        return;
+      }
+          
+    Formula formula(text);
+
+    // Do not bother storing all the atoms in the formula, this is
+    // only a check (false param below).  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, false, true))
+      {
+        // Set the error bit.
+        m_validationErrors |= MXP_VALIDATION_FORMULA_ERRORS;
+
+        m_ui.monoMzRatioLineEdit->setText("0.000");
+        m_ui.inputDataFeedbackLineEdit->setText(tr("Formula error"));
+
+        return;
+      }
+    
+    // qDebug() << __FILE__ << __LINE__
+    //          << "Formula:" << formula.formula() << "validated." ;
+
+    // At this point we know we could actually validate the formula,
+    // so do that work with the member formula:
+
+    // We want to validate the formula and in the mean time construct
+    // the list of all the AtomCount objects(first true), and since
+    // the formula is reused we also ensure that that list is reset
+    // (second true). m_atomList is a reference to the atom list of
+    // the polymer chemistry definition currently used in the caller
+    // calculator window.
+
+    m_formula.setFormula(text);
+    m_formula.validate(m_atomList, true, true);
+    
+    // Clear the bit as there is no error here.
+    m_validationErrors &= ~MXP_VALIDATION_FORMULA_ERRORS;
+    
+    m_ui.inputDataFeedbackLineEdit->setText(tr("Formula fine"));
+    
+    // qDebug() << __FILE__ << __LINE__
+    //          << "Going to call updateMzRatio.";
+    
+    updateMzRatio();
+    
+    return;
+  }
+  
+
+  bool 
+  IsotopicPatternCalculationDlg::updateMzRatio()
+  {
+    // Set the mz ratio to our member data variable.
+    bool res = fetchMzRatio(&m_mono, &m_avg);
+    
+    // If res is falsed, that means that the formula is not validated
+    // at present. Silently return.
+    if(!res)
+      {
+        qDebug() << __FILE__ << __LINE__
+                 << "Failed to fetch mz ratio.";
+        
+      return false;
+      }
+    
     Application *application = static_cast<Application *>(qApp);
+    
+    QString mzRatio = application->locale().
+      toString(m_mono, 'f', MXP_OLIGOMER_DEC_PLACES);
+    
+    m_ui.monoMzRatioLineEdit->setText(mzRatio);
 
-    bool inserted = false;
-    int wholeCount = 0;
+    return true;
+  }
+  
+
+  void 
+  IsotopicPatternCalculationDlg::execute()
+  {
+    // We are asked to launch the calculation. But we ought to make
+    // sure that all the required data are set fine.
 
+    if(!fetchValidateInputData())
+      {
+        QMessageBox::warning(0, 
+                             tr("massXpert - Isotopic Pattern Calculation"),
+                             tr("Please fix the input data first."),
+                             QMessageBox::Ok);
+        return;
+      }
+    
     // Clear the textEdit widget so that we can start out-putting text
     // into it.
     m_ui.resultTextEdit->clear();
 
-    if (!fetchValidateInputData())
-      return;
-
-    double fullWidthHalfMax = m_mono / m_resolution;
-
+    // We start computing the peaks in the isotopic cluster.
+    m_ui.feedbackLineEdit->setText(tr("Computing the peaks in the cluster.")); 
+    
+    // We are going to compute a set of mzRatio/intensity pairs
+    // corresponding to the centroid of all the gaussian/lorentzian
+    // curves that will together make the isotopic cluster.
 
-    QList<IsotopicPeak *> oldPeakList;
+    // Each centroid peak will be stored in a list of peaks:
+    QList<IsotopicPeak *> centroidPeakList;
   
-    IsotopicPeak *firstPeak = new IsotopicPeak();
+    // Let's seed all the calculations with the first centroid peak.
+    IsotopicPeak *firstPeak = new IsotopicPeak(0, 0, 0, 0);
+
     firstPeak->setMass(0);
     firstPeak->setProbability(1);
-  
-    oldPeakList.append(firstPeak);
+    centroidPeakList.append(firstPeak);
 	  
-    // After the validation of the formula, it contains a list of
-    // allocated AtomCount objects. Get a handy shorthand to it.
+    // When the m_formula was validated, we had asked that the atoms
+    // be stored in its list. Get a handy shorthand to it.
 
     const QList<AtomCount *> &atomCountList = m_formula.atomCountList();
   
     QTime time;
     time.start();
-  
-    m_ui.feedbackLineEdit->setText(tr("Computing the peaks in the pattern."));  
+    
+    Application *application = static_cast<Application *>(qApp);
+
+    bool inserted = false;
+    int wholeCount = 0;
+
+    // Iterate in the list of AtomCount instances corresponding to the
+    // formula for which the isotopic cluster is to be computed.
 
     for (int iter = 0; iter < atomCountList.size(); ++iter)
       {
@@ -365,6 +799,12 @@ namespace massXpert
 	//       qDebug() << "Current atom:" << atomCount->symbol()
 	// 		<< "with" << isotopeCount << "isotope(s)";
       
+        // One atom count instance is a pair of values : an atom and
+        // the number of times that atom occurs in the formula. Each
+        // atom, in turn has a list of isotopes. We iterate in that
+        // list of isotopes and take them into account according to
+        // their abundance.
+
 	for(int jter = 0; jter < atomCount->count(); ++jter)
 	  {
 	    // 	  qDebug() << "Atom count:"<< atomCount->count()
@@ -379,28 +819,22 @@ namespace massXpert
 	  	  
 	    QList<IsotopicPeak *> newPeakList;
 
-	    for (int kter = 0; kter < oldPeakList.size(); ++kter)
+	    for (int kter = 0; kter < centroidPeakList.size(); ++kter)
 	      {
-		IsotopicPeak *peakListPeak = oldPeakList.at(kter);
+		IsotopicPeak *centroidPeak = centroidPeakList.at(kter);
 	      
 		for(int lter = 0; lter < isotopeCount; ++lter)
 		  {
 		    Isotope *isotope = atomCount->isotopeList().at(lter);
 		  
-		    // 		  qDebug() << "Current isotope:" << isotope->mass();
-		  
 		    IsotopicPeak *newPeak = 
-		      new IsotopicPeak(peakListPeak->mass() +
+		      new IsotopicPeak(centroidPeak->mass() +
 					isotope->mass(),
-					0,
-					peakListPeak->probability() *
-					(isotope->abundance() / 100),
-					0);
-		  
-		    // 		  qDebug() << "Newly created peak:"
-		    // 			    << newPeak->mass() << "--"
-		    // 			    << newPeak->probability();
-		  
+                                       0,
+                                       centroidPeak->probability() *
+                                       (isotope->abundance() / 100),
+                                       0);
+                    
 		    if (!newPeakList.size())
 		      {
 			newPeakList.append(newPeak);
@@ -456,24 +890,28 @@ namespace massXpert
 			// 				  << "--" 
 			// 				  << newPeakList.at(zter)->probability();
 		      }
-		  }
+                  }
+                // End of
+                // for(int lter = 0; lter < isotopeCount; ++lter)
 	      }
+            // End of
+            // for (int kter = 0; kter < centroidPeakList.size(); ++kter)
 	  
-	    qDeleteAll(oldPeakList);
-	    oldPeakList.clear();
+	    qDeleteAll(centroidPeakList);
+	    centroidPeakList.clear();
 	  
-	    oldPeakList = newPeakList;
+	    centroidPeakList = newPeakList;
 	    newPeakList.clear();
 	    
 	    // We now have to remove peaks that are too near one from
 	    // the other.
 	  
-	    for (int nter = 0; nter < oldPeakList.size() - 1; ++nter)
+	    for (int nter = 0; nter < centroidPeakList.size() - 1; ++nter)
 	      {
-		double absDiff = fabs(oldPeakList.at(nter)->mass() -
-				       oldPeakList.at(nter + 1)->mass());
+		double absDiff = fabs(centroidPeakList.at(nter)->mass() -
+				       centroidPeakList.at(nter + 1)->mass());
 	      
-		if(absDiff <= fullWidthHalfMax)
+		if(absDiff <= m_fwhm)
 		  {
 		    // 		  qDebug() << "absDiff is" << absDiff;
 		  
@@ -481,28 +919,28 @@ namespace massXpert
 		    // current one, but do not forget to account for
 		    // that one from the abundance point of vue.
 		  
-		    oldPeakList.at(nter)->
-		      incrementProbability(oldPeakList.at(nter + 1)->
+		    centroidPeakList.at(nter)->
+		      incrementProbability(centroidPeakList.at(nter + 1)->
 					    probability());
 
 		    // 		  qDebug() << "Removed peak"
-		    // 			    << oldPeakList.at(nter + 1)->mass() << "--"
-		    // 			    << oldPeakList.at(nter + 1)->probability();
+		    // 			    << centroidPeakList.at(nter + 1)->mass() << "--"
+		    // 			    << centroidPeakList.at(nter + 1)->probability();
 		  
-		    delete oldPeakList.takeAt(nter + 1);
+		    delete centroidPeakList.takeAt(nter + 1);
 		    --nter;
 		  } 
 	      }
 
-	    if (m_maximumPeaks >= 2 && oldPeakList.size() > m_maximumPeaks)
+	    if (m_maximumPeaks >= 2 && centroidPeakList.size() > m_maximumPeaks)
 	      {
 		// The user wants at most m_maximumPeaks peaks, which means
 		// we have to remove all the ones in excess.
 	      
 		for(int pter = m_maximumPeaks; 
-		     pter < oldPeakList.size(); ++pter)
+		     pter < centroidPeakList.size(); ++pter)
 		  {
-		    delete oldPeakList.takeAt(pter);
+		    delete centroidPeakList.takeAt(pter);
 		  }
 	      }
 	  }
@@ -510,8 +948,11 @@ namespace massXpert
 	if(m_aborted)
 	  break;
       }
+    // End of
+    // for (int iter = 0; iter < atomCountList.size(); ++iter)
+    
     m_aborted = false;
-  
+    
     m_ui.progressBar->setRange(0, 100);
     m_ui.progressBar->setValue(0);
 
@@ -528,13 +969,14 @@ namespace massXpert
     double sumProbabilities = 0;
     double greatestProbability = 0;
     
-    for (int iter = 0; iter < oldPeakList.size(); ++iter)
+    for (int iter = 0; iter < centroidPeakList.size(); ++iter)
       {
-	IsotopicPeak *isotopicPeak = oldPeakList.at(iter);
+	IsotopicPeak *isotopicPeak = centroidPeakList.at(iter);
       
 	isotopicPeak->setMass(isotopicPeak->mass() / m_charge);
       
 	sumProbabilities += isotopicPeak->probability();
+
 	if(isotopicPeak->probability() > greatestProbability)
 	  greatestProbability = isotopicPeak->probability();
       }
@@ -545,24 +987,24 @@ namespace massXpert
   
     if (m_charge > 1)
       {
-	for(int nter = 0; nter < oldPeakList.size() - 1; ++nter)
+	for(int nter = 0; nter < centroidPeakList.size() - 1; ++nter)
 	  {
-	    if (fabs(oldPeakList.at(nter)->mass() -
-		      oldPeakList.at(nter + 1)->mass()) <= fullWidthHalfMax)
+	    if (fabs(centroidPeakList.at(nter)->mass() -
+		      centroidPeakList.at(nter + 1)->mass()) <= m_fwhm)
 	      {
 		// Remove the forward peak that is too close to
 		// current one, but do not forget to account for
 		// that one from the abundance point of vue.
 	      
-		oldPeakList.at(nter)->
-		  incrementProbability(oldPeakList.at(nter + 1)->
+		centroidPeakList.at(nter)->
+		  incrementProbability(centroidPeakList.at(nter + 1)->
 					probability());
 	      
 		// qDebug() << "Removed peak"
-		// << oldPeakList.at(nter + 1)->mass() << "--"
-		// << oldPeakList.at(nter + 1)->probability();
+		// << centroidPeakList.at(nter + 1)->mass() << "--"
+		// << centroidPeakList.at(nter + 1)->probability();
 	      
-		delete oldPeakList.takeAt(nter + 1);
+		delete centroidPeakList.takeAt(nter + 1);
 	      } 
 	  }
       }
@@ -571,9 +1013,9 @@ namespace massXpert
 
     // Compute the relative intensity.
   
-    for (int iter = 0; iter < oldPeakList.size(); ++iter)
+    for (int iter = 0; iter < centroidPeakList.size(); ++iter)
       {
-	IsotopicPeak *isotopicPeak = oldPeakList.at(iter);
+	IsotopicPeak *isotopicPeak = centroidPeakList.at(iter);
       
 	double relativeIntensity = 
 	 ( isotopicPeak->probability() / greatestProbability) * 100;
@@ -584,43 +1026,36 @@ namespace massXpert
   
     int elapsedTime = time.elapsed() /(1000 * 60);
 
-    // And now we should do something with the peaks !!!
-
-    m_ui.feedbackLineEdit->setText(tr("Formatting the results"));
-
-    bool locale = m_ui.localeCheckBox->checkState() == Qt::Checked ?
+    // Shall we use localization for all the numerical output?
+    bool isUsingLocale = m_ui.localeCheckBox->checkState() == Qt::Checked ?
       true : false;
-    
-    double c = fullWidthHalfMax /(2 * sqrt(log(2)));
-    double c2 = pow(c, 2);
-    double increment = fullWidthHalfMax / 50;
 
     QString results(tr("RESULTS for this computation(duration: %1 min)\n"
 			 "====================================\n\n").
 		     arg(elapsedTime));
   
-    for (int oter = 0; oter < oldPeakList.size(); ++oter)
+    for (int oter = 0; oter < centroidPeakList.size(); ++oter)
       {
-	double mass = oldPeakList.at(oter)->mass();
-	double prob = oldPeakList.at(oter)->probability();
-	double relInt = oldPeakList.at(oter)->relativeIntensity();
+	double mass = centroidPeakList.at(oter)->mass();
+	double prob = centroidPeakList.at(oter)->probability();
+	double relInt = centroidPeakList.at(oter)->relativeIntensity();
       
 	if(prob > m_minimumProbability)
 	  {
 	    results += tr("Mass: ");
-	    if (locale)
+	    if(isUsingLocale)
 	      results += application->locale().
 		toString(mass, 'f', MXP_OLIGOMER_DEC_PLACES);
 	    else
 	      results += QString().setNum(mass, 'f', MXP_OLIGOMER_DEC_PLACES);
 	    results += tr(" -- Probability: ");
-	    if (locale)
+	    if(isUsingLocale)
 	      results += application->locale().
 		toString(prob, 'f', MXP_OLIGOMER_DEC_PLACES);
 	    else
 	      results += QString().setNum(prob, 'f', MXP_OLIGOMER_DEC_PLACES);
 	    results += tr(" -- Rel. intensity: ");
-	    if (locale)
+	    if(isUsingLocale)
 	      results += application->locale().
 		toString(relInt, 'f', MXP_OLIGOMER_DEC_PLACES);
 	    else
@@ -629,118 +1064,133 @@ namespace massXpert
 	    results += "\n";
 	  }
       }
-    
-    m_ui.resultTextEdit->append(results);
 
-    //   qDebug() << "fullWidthHalfMax" << fullWidthHalfMax
-    // 	    << "x-increment" << increment
-    // 	    << "c" << c
-    // 	    << "c^2" << c2;
-
-    // For each isotopic peak, compute a gaussian.
-    // Write the results to the file, peak after peak.
+    qDebug() << __FILE__ << __LINE__
+             << results;
+    
+    
+    // For each Centroid peak, we should make a real curve, that is
+    // created either a gaussian or a lorentzian curve.
 
-    QFile file(m_filePath);
-    QTextStream stream;
-  
-    bool ret = file.open(QIODevice::WriteOnly |
-			  QIODevice::Truncate | 
-			  QIODevice::Text);
-    if (ret)
+    QList<IsotopicCurve *>curveList;
+    
+    for (int iter = 0; iter < centroidPeakList.size(); ++iter)
       {
-	stream.setDevice(&file);
-	stream.setCodec("UTF-8");
+        IsotopicPeak *peak = centroidPeakList.at(iter);
+        
+	double mass = peak->mass();
+	double relInt = peak->relativeIntensity();
+        
+        IsotopicCurve *curve = new IsotopicCurve(mass, 
+                                                 relInt,
+                                                 m_fwhm, 
+                                                 m_points, 
+                                                 m_increment,
+                                                 1 /* normFactor */,
+                                                 m_curveType);
+        
+        curve->calculateCurve();
+        
+        curveList.append(curve);
       }
-    else
+    
+    // At this point, each Centroid peak, that is each mzRatio/intensity
+    // pair in centroidPeakList has given rise to a full
+    // gaussian/lorentzian curve that's been appended in curveList.
+
+    // We now have to perform the sum of all these curves so as to
+    // generate a single curve that encompasses all the isotopic
+    // cluster.
+
+    // First off, get the min/max mzRatio of all the curves.
+
+    int curveCount = curveList.size();
+
+    double tempMzRatio = 0;
+    double maxMzRatio = 0;
+    double minMzRatio = 1000000000;
+
+    for(int iter = 0; iter < curveCount ; ++iter)
       {
-	QMessageBox::warning(0, 
-			      tr("massXpert - Isotopic Pattern Calculation"),
-			      tr("Failed to export "
-				  "the data: file could not be opened."),
-			      QMessageBox::Ok);
+        IsotopicCurve *curve = curveList.at(iter);
+      
+        // Get to the list of points in 
+        const QList<IsotopicPeak *> &peakList =
+          curve->isotopicPeakList();
+
+        // Get first point of the curve.
+        IsotopicPeak *peak = peakList.first();
+
+        // Get the minimum mzRatio
+        tempMzRatio = peak->mass();
       
-	stream.setStatus(QTextStream::ReadCorruptData);
+        if(tempMzRatio < minMzRatio)
+          minMzRatio = tempMzRatio;
+
+        // Get last point of the curve.
+        peak = peakList.last();
+
+        // Get the maximum mzRatio
+        tempMzRatio = peak->mass();
+      
+        if(tempMzRatio > maxMzRatio)
+          maxMzRatio = tempMzRatio;
       }
   
-    for (int iter = 0; iter < oldPeakList.size(); ++iter)
+    // At this point we know that our absorption spectrum should range
+    // [minMzRatio -- maxMzRatio]. We can perform the actual sum of
+    // all the isotopic curves. First off, empty the m_isotopicCurve.
+    
+    m_isotopicCurve.emptyPeakList();
+    
+    double curMzRatio = minMzRatio;
+  
+    while(curMzRatio <= maxMzRatio)
       {
-	double prob = oldPeakList.at(iter)->probability();
-      
-	// If the formula has a big number of atoms, then the first few
-	// peaks will be of almost negligible probability, and we'll
-	// want to skip them.
-	if(prob < m_minimumProbability)
-	  continue;
-      
-	double mono = oldPeakList.at(iter)->mass();
-	double relInt = oldPeakList.at(iter)->relativeIntensity();
+        // curMzRatio now has a mzRatio value for which we have to
+        // sum all the intensities in each curve.
       
-	double leftPoint = mono -(2 * fullWidthHalfMax);
-	double rightPoint = mono +(2 * fullWidthHalfMax);
+        double summedIntensity = 0;
       
-	QString outputString;
-	stream << outputString;
-	outputString.clear();
+        for(int iter = 0; iter < curveCount ; ++iter)
+          {
+            IsotopicCurve *curve = curveList.at(iter);
+          
+            bool ok = false;
+          
+            summedIntensity += curve->intensityAt(curMzRatio, m_increment, &ok);
+          }
       
-	//       outputString += "#########";
-	//       if (locale)
-	// 	outputString += application->locale().toString(mono, 'f', 5);
-	//       else
-	// 	outputString += QString().setNum(mono, 'f', 5);
-	//       outputString += "--> [";
-	//       if (locale)
-	// 	outputString += application->locale().toString(leftPoint, 'f', 5);
-	//       else
-	// 	outputString += QString().setNum(leftPoint, 'f', 5);
-	//       outputString += "--";
-	//       if (locale)
-	// 	outputString += application->locale().toString(rightPoint, 'f', 5);
-	//       else
-	// 	outputString += QString().setNum(rightPoint, 'f', 5);
-	//       outputString += "]\n";
-      
-	for(double x = leftPoint; x <= rightPoint; x += increment)
-	  {
-	    double y = relInt * exp(( - pow((x - mono), 2) ) / c2);
-	  
-	    if (locale)
-	      outputString += application->locale().
-		toString(x, 'f', MXP_OLIGOMER_DEC_PLACES);
-	    else
-	      outputString += QString().
-		setNum(x, 'f', MXP_OLIGOMER_DEC_PLACES);
-	    outputString += "  ";
-	    if (locale)
-	      outputString += application->locale().
-		toString(y, 'f', MXP_OLIGOMER_DEC_PLACES);
-	    else
-	      outputString += QString().
-		setNum(y, 'f', MXP_OLIGOMER_DEC_PLACES);
-	    outputString += "\n";
-	  }
+        IsotopicPeak *newPeak = new IsotopicPeak(curMzRatio, summedIntensity, 0, 0);
+        
+        m_isotopicCurve.appendPeak(newPeak);
 
-	if(stream.status() == QTextStream::ReadCorruptData)
-	  m_ui.resultTextEdit->append(outputString);
-	else
-	  stream << outputString;       
-      
-	//       qDebug() << outputString;
-	outputString.clear();
+        curMzRatio += m_increment;
       }
-
-    m_ui.feedbackLineEdit->setText(tr(""));
-
-    // Finished sending all the peak data to the file. QFile will close
-    // itself.
+    
+    if(!m_filePath.isEmpty())
+      {
+        // Send all the data to the output file.
+        if (!m_isotopicCurve.dataToFile(m_filePath))
+          QMessageBox::warning(this, 
+                               tr("massXpert - Isotopic Pattern Calculation"),
+                               tr("Failed to export the curve data to file."),
+                               QMessageBox::Ok);
+        
+        return;
+      }
+    
+    // Send the data to the text edit widget.
+    m_ui.resultTextEdit->append(m_isotopicCurve.dataAsString());
   }
-
+    
 
   void 
   IsotopicPatternCalculationDlg::abort()
   {
     m_aborted = true;
   }
-
+  
 
   void 
   IsotopicPatternCalculationDlg::outputFile()
@@ -753,6 +1203,19 @@ namespace massXpert
 				    tr("Any file type(*)"));
   }
 
+  void 
+  IsotopicPatternCalculationDlg::debugPutStdErr(QString file, int line,
+                                                int value, const QString &text)
+  {
+    qDebug() << file << line
+             << "value " << text << ":" << value
+             << " -- bitset:" << GlobBinaryRepresentation(value)
+             << "\n";
+  }
+  
+} // namespace massXpert
+
+
 
 #if 0
   /***************************************************************************
@@ -1142,5 +1605,3 @@ namespace massXpert
     printf("-h show this text\n\n");
   }
 #endif
-
-} // namespace massXpert
diff --git a/gui/isotopicPatternCalculationDlg.hpp b/gui/isotopicPatternCalculationDlg.hpp
index 836cab7..14acacb 100644
--- a/gui/isotopicPatternCalculationDlg.hpp
+++ b/gui/isotopicPatternCalculationDlg.hpp
@@ -50,11 +50,23 @@
 #include "atom.hpp"
 #include "atomCount.hpp"
 #include "formula.hpp"
+#include "isotopicCurve.hpp"
+#include "globals.hpp"
 
 
 namespace massXpert
 {
 
+  enum ValidationError
+    {
+      MXP_VALIDATION_ERRORS_NONE = 0x0000,
+      MXP_VALIDATION_IONIZERULE_ERRORS = 1 << 0,
+      MXP_VALIDATION_FORMULA_ERRORS = 1 << 1,
+      MXP_VALIDATION_RESOLUTION_ERRORS = 1 << 2,
+      MXP_VALIDATION_FWHM_ERRORS = 1 << 3,
+    };
+  
+
   class IsotopicPatternCalculationDlg : public QDialog
   {
     Q_OBJECT
@@ -64,13 +76,33 @@ namespace massXpert
   
     const QList<Atom *> &m_atomList;
   
+    int m_validationErrors;
+    
     QString m_filePath;
     Formula m_formula;
+
+    double m_minimumProbability;
     int m_maximumPeaks;
-    int m_resolution;
+
+    double m_resolution;
+    double m_fwhm;
+
+    int m_points;
+    double m_increment;
+
     int m_charge;
-    double m_minimumProbability;
 
+    CurveType m_curveType;
+    
+    const PolChemDef &m_polChemDef;
+    IonizeRule m_ionizeRule;
+        
+    // The curve that will hold the sum of all the
+    // gaussians/lorentzian curves obtained for the single mass peaks
+    // of the isotopic cluster.
+
+    IsotopicCurve m_isotopicCurve;
+    
     double m_mono;
     double m_avg;
     
@@ -78,9 +110,26 @@ namespace massXpert
   
     void closeEvent(QCloseEvent *event); 
 
+    bool fetchIonizationRuleData(IonizeRule *);
+    bool fetchFormulaMass(double * = 0, double * = 0);
+    bool fetchMzRatio(double * = 0, double * = 0);
+        
     bool fetchValidateInputData();
-  
+    
+    void setInErrorStatus(const QString &);
+
+    bool updateMzRatio();
+    
+    void debugPutStdErr(QString /*file*/, int /*line*/, 
+                        int /*value*/, 
+                        const QString & = QString() /*descString*/);
+                            
+                    
   private slots:
+    void formulaChanged(const QString &);
+    void ionizationDataChanged();
+    void resolutionChanged(int);
+    void fwhmEdited(const QString &);
     void execute();
     void abort();
     void outputFile();
diff --git a/gui/ui/isotopicPatternCalculationDlg.ui b/gui/ui/isotopicPatternCalculationDlg.ui
index 6b179f2..d2a9c46 100644
--- a/gui/ui/isotopicPatternCalculationDlg.ui
+++ b/gui/ui/isotopicPatternCalculationDlg.ui
@@ -1,444 +1,549 @@
-<ui version="4.0" >
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
  <class>IsotopicPatternCalculationDlg</class>
- <widget class="QDialog" name="IsotopicPatternCalculationDlg" >
-  <property name="geometry" >
+ <widget class="QDialog" name="IsotopicPatternCalculationDlg">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>576</width>
-    <height>578</height>
+    <width>776</width>
+    <height>844</height>
    </rect>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>massXpert: Isotopic pattern calculator</string>
   </property>
-  <property name="windowIcon" >
-   <iconset resource="../application.qrc" >
+  <property name="windowIcon">
+   <iconset resource="../application.qrc">
     <normaloff>:/images/massxpert-icon-32.png</normaloff>:/images/massxpert-icon-32.png</iconset>
   </property>
-  <layout class="QGridLayout" >
-   <property name="margin" >
-    <number>9</number>
-   </property>
-   <property name="spacing" >
-    <number>6</number>
-   </property>
-   <item row="3" column="0" >
-    <widget class="QGroupBox" name="groupBox_4" >
-     <property name="title" >
-      <string>Processing feedback</string>
+  <layout class="QGridLayout" name="gridLayout_8">
+   <item row="0" column="0">
+    <widget class="QSplitter" name="splitter">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
      </property>
-     <layout class="QGridLayout" >
-      <property name="margin" >
-       <number>9</number>
+     <widget class="QGroupBox" name="groupBox">
+      <property name="title">
+       <string/>
       </property>
-      <property name="spacing" >
-       <number>6</number>
-      </property>
-      <item row="0" column="1" >
-       <widget class="QProgressBar" name="progressBar" >
-        <property name="value" >
-         <number>24</number>
-        </property>
-        <property name="orientation" >
-         <enum>Qt::Horizontal</enum>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="0" >
-       <widget class="QLineEdit" name="feedbackLineEdit" >
-        <property name="font" >
-         <font>
-          <weight>75</weight>
-          <bold>true</bold>
-         </font>
-        </property>
-        <property name="frame" >
-         <bool>false</bool>
-        </property>
-        <property name="readOnly" >
-         <bool>true</bool>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item row="0" column="0" >
-    <layout class="QHBoxLayout" >
-     <property name="spacing" >
-      <number>6</number>
-     </property>
-     <property name="margin" >
-      <number>0</number>
-     </property>
-     <item>
-      <widget class="QLabel" name="label" >
-       <property name="text" >
-        <string>Polymer chemistry definition:</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <widget class="QLabel" name="polChemDefLabel" >
-       <property name="text" >
-        <string>polChemDefLabel</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer>
-       <property name="orientation" >
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeHint" stdset="0" >
-        <size>
-         <width>40</width>
-         <height>20</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-    </layout>
-   </item>
-   <item row="1" column="0" >
-    <widget class="QGroupBox" name="groupBox" >
-     <property name="title" >
-      <string>Input data</string>
-     </property>
-     <layout class="QGridLayout" >
-      <property name="margin" >
-       <number>9</number>
-      </property>
-      <property name="spacing" >
-       <number>6</number>
-      </property>
-      <item row="1" column="0" >
-       <layout class="QHBoxLayout" >
-        <property name="spacing" >
-         <number>6</number>
-        </property>
-        <property name="margin" >
-         <number>0</number>
-        </property>
-        <item>
-         <layout class="QHBoxLayout" >
-          <property name="spacing" >
-           <number>6</number>
-          </property>
-          <property name="margin" >
-           <number>0</number>
-          </property>
-          <item>
-           <widget class="QLabel" name="label_9" >
-            <property name="text" >
-             <string>&Min. probability:</string>
+      <layout class="QGridLayout" name="gridLayout_2">
+       <item row="0" column="0" colspan="2">
+        <widget class="QGroupBox" name="polChemDefGroupBox">
+         <property name="sizePolicy">
+          <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+           <horstretch>0</horstretch>
+           <verstretch>0</verstretch>
+          </sizepolicy>
+         </property>
+         <property name="title">
+          <string>Polymer chemistry definition</string>
+         </property>
+         <property name="alignment">
+          <set>Qt::AlignCenter</set>
+         </property>
+         <property name="flat">
+          <bool>false</bool>
+         </property>
+         <property name="checkable">
+          <bool>false</bool>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_7">
+          <item row="0" column="0">
+           <widget class="QLabel" name="polChemDefLabel">
+            <property name="text">
+             <string>polChemDefLabel</string>
             </property>
-            <property name="buddy" >
-             <cstring>minimumProbabilityDoubleSpinBox</cstring>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QGroupBox" name="groupBox_6">
+            <property name="title">
+             <string>Ionization</string>
             </property>
+            <layout class="QGridLayout" name="gridLayout_4">
+             <item row="0" column="0">
+              <layout class="QVBoxLayout" name="verticalLayout">
+               <item>
+                <widget class="QLabel" name="label_12">
+                 <property name="text">
+                  <string>Unitary formula</string>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <layout class="QHBoxLayout" name="horizontalLayout_2">
+                 <item>
+                  <widget class="QLineEdit" name="ionizationFormulaLineEdit">
+                   <property name="toolTip">
+                    <string>Ionization formula</string>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+              </layout>
+             </item>
+             <item row="0" column="1">
+              <layout class="QVBoxLayout" name="_3">
+               <property name="spacing">
+                <number>6</number>
+               </property>
+               <property name="margin">
+                <number>0</number>
+               </property>
+               <item>
+                <layout class="QHBoxLayout" name="_4">
+                 <property name="spacing">
+                  <number>6</number>
+                 </property>
+                 <property name="margin">
+                  <number>0</number>
+                 </property>
+                 <item>
+                  <widget class="QLabel" name="label_8">
+                   <property name="text">
+                    <string>Unitary charge</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QSpinBox" name="ionizationChargeSpinBox">
+                   <property name="toolTip">
+                    <string>Ionization unitary charge</string>
+                   </property>
+                   <property name="minimum">
+                    <number>1</number>
+                   </property>
+                   <property name="maximum">
+                    <number>1000000</number>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+               <item>
+                <layout class="QHBoxLayout" name="_5">
+                 <property name="spacing">
+                  <number>6</number>
+                 </property>
+                 <property name="margin">
+                  <number>0</number>
+                 </property>
+                 <item>
+                  <widget class="QLabel" name="label_11">
+                   <property name="text">
+                    <string>Ionization level</string>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <widget class="QSpinBox" name="ionizationLevelSpinBox">
+                   <property name="toolTip">
+                    <string>Ionization level</string>
+                   </property>
+                   <property name="minimum">
+                    <number>1</number>
+                   </property>
+                   <property name="value">
+                    <number>1</number>
+                   </property>
+                  </widget>
+                 </item>
+                </layout>
+               </item>
+              </layout>
+             </item>
+            </layout>
            </widget>
           </item>
-          <item>
-           <widget class="QDoubleSpinBox" name="minimumProbabilityDoubleSpinBox" >
-            <property name="toolTip" >
-             <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum probability (or compounded abundance)  that a peak must have to be taken into account in the output.</p></body></html></string>
+          <item row="0" column="1">
+           <spacer name="horizontalSpacer">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
             </property>
-            <property name="decimals" >
-             <number>7</number>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
             </property>
-           </widget>
+           </spacer>
           </item>
          </layout>
-        </item>
-        <item>
-         <layout class="QHBoxLayout" >
-          <property name="spacing" >
-           <number>6</number>
-          </property>
-          <property name="margin" >
-           <number>0</number>
-          </property>
-          <item>
-           <widget class="QLabel" name="label_5" >
-            <property name="text" >
-             <string>&Resolution:</string>
-            </property>
-            <property name="buddy" >
-             <cstring>resolutionSpinBox</cstring>
+        </widget>
+       </item>
+       <item row="1" column="0" colspan="2">
+        <widget class="QGroupBox" name="inputDataGroupBox">
+         <property name="title">
+          <string>Input data</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_6">
+          <item row="0" column="0">
+           <widget class="QGroupBox" name="massConfigGroupBox">
+            <property name="title">
+             <string>Mass config.</string>
             </property>
+            <layout class="QGridLayout" name="gridLayout">
+             <item row="0" column="0" colspan="3">
+              <layout class="QHBoxLayout" name="horizontalLayout">
+               <item>
+                <widget class="QLabel" name="label_3">
+                 <property name="text">
+                  <string>Formula:</string>
+                 </property>
+                 <property name="buddy">
+                  <cstring>formulaLineEdit</cstring>
+                 </property>
+                </widget>
+               </item>
+               <item>
+                <widget class="QLineEdit" name="formulaLineEdit">
+                 <property name="toolTip">
+                  <string>Formula of the non-ionized analyte</string>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </item>
+             <item row="1" column="0">
+              <widget class="QLabel" name="label_10">
+               <property name="text">
+                <string>Charge: </string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1">
+              <widget class="QLabel" name="chargeLabel">
+               <property name="text">
+                <string>1</string>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="0">
+              <widget class="QLabel" name="label_4">
+               <property name="text">
+                <string>mz Ratio: </string>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="2">
+              <widget class="QLineEdit" name="monoMzRatioLineEdit"/>
+             </item>
+            </layout>
            </widget>
           </item>
-          <item>
-           <widget class="QSpinBox" name="resolutionSpinBox" >
-            <property name="toolTip" >
-             <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Resolution of the mass spectrometer.</p></body></html></string>
+          <item row="0" column="1">
+           <widget class="QGroupBox" name="resolutionConfigGroupBox">
+            <property name="title">
+             <string>Resolution config.</string>
             </property>
-            <property name="maximum" >
-             <number>100000</number>
-            </property>
-            <property name="singleStep" >
-             <number>1000</number>
-            </property>
-            <property name="value" >
-             <number>15000</number>
+            <layout class="QGridLayout" name="gridLayout_5">
+             <item row="0" column="0">
+              <widget class="QLabel" name="label_5">
+               <property name="text">
+                <string>&Resolution:</string>
+               </property>
+               <property name="buddy">
+                <cstring>resolutionSpinBox</cstring>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="0">
+              <widget class="QLabel" name="label_7">
+               <property name="text">
+                <string>FWHM:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="1">
+              <widget class="QLineEdit" name="fwhmLineEdit"/>
+             </item>
+             <item row="0" column="1">
+              <widget class="QSpinBox" name="resolutionSpinBox">
+               <property name="toolTip">
+                <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Resolution of the mass spectrometer.</p></body></html></string>
+               </property>
+               <property name="minimum">
+                <number>0</number>
+               </property>
+               <property name="maximum">
+                <number>1000000</number>
+               </property>
+               <property name="singleStep">
+                <number>1000</number>
+               </property>
+               <property name="value">
+                <number>0</number>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </widget>
+          </item>
+          <item row="0" column="2">
+           <widget class="QGroupBox" name="spectrumConfigGroupBox">
+            <property name="title">
+             <string>Spectrum config.</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>
+               <property name="buddy">
+                <cstring>minimumProbabilityDoubleSpinBox</cstring>
+               </property>
+              </widget>
+             </item>
+             <item row="3" column="1">
+              <widget class="QDoubleSpinBox" name="minimumProbabilityDoubleSpinBox">
+               <property name="toolTip">
+                <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Minimum probability (or compounded abundance)  that a peak must have to be taken into account in the output.</p></body></html></string>
+               </property>
+               <property name="decimals">
+                <number>7</number>
+               </property>
+               <property name="minimum">
+                <double>0.000100000000000</double>
+               </property>
+              </widget>
+             </item>
+             <item row="4" column="0">
+              <widget class="QLabel" name="label_6">
+               <property name="text">
+                <string>Max. &peaks:</string>
+               </property>
+               <property name="buddy">
+                <cstring>maximumPeaksSpinBox</cstring>
+               </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>25</number>
+               </property>
+               <property name="maximum">
+                <number>100000</number>
+               </property>
+               <property name="value">
+                <number>100</number>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="0">
+              <widget class="QLabel" name="label">
+               <property name="text">
+                <string>Points:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="1" column="1">
+              <widget class="QSpinBox" name="pointsSpinBox">
+               <property name="minimum">
+                <number>10</number>
+               </property>
+               <property name="value">
+                <number>50</number>
+               </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">
+                <string>Increment:</string>
+               </property>
+              </widget>
+             </item>
+             <item row="2" column="1">
+              <widget class="QSpinBox" name="incrementSpinBox">
+               <property name="toolTip">
+                <string>Gap between any two points in the curve</string>
+               </property>
+               <property name="maximum">
+                <number>1000000</number>
+               </property>
+              </widget>
+             </item>
+            </layout>
            </widget>
           </item>
          </layout>
-        </item>
-        <item>
-         <layout class="QHBoxLayout" >
-          <property name="spacing" >
-           <number>6</number>
-          </property>
-          <property name="margin" >
-           <number>0</number>
-          </property>
-          <item>
-           <widget class="QLabel" name="label_6" >
-            <property name="text" >
-             <string>Max. &peaks:</string>
+        </widget>
+       </item>
+       <item row="2" column="0">
+        <widget class="QGroupBox" name="actionsGroupBox">
+         <property name="title">
+          <string>Actions</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_3">
+          <item row="0" column="0">
+           <widget class="QPushButton" name="outputFilePushButton">
+            <property name="toolTip">
+             <string>Choose a file in which to store the data for the plotting of the isotopic peak. </string>
             </property>
-            <property name="buddy" >
-             <cstring>maximumPeaksSpinBox</cstring>
+            <property name="text">
+             <string>&Output file...</string>
             </property>
            </widget>
           </item>
-          <item>
-           <widget class="QSpinBox" name="maximumPeaksSpinBox" >
-            <property name="toolTip" >
-             <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Maximum number of peaks that must be calculated.</p></body></html></string>
+          <item row="0" column="1">
+           <widget class="QCheckBox" name="localeCheckBox">
+            <property name="toolTip">
+             <string>If checked all the numerical output will be generated with locale specificity.</string>
             </property>
-            <property name="maximum" >
-             <number>100000</number>
-            </property>
-            <property name="value" >
-             <number>100</number>
+            <property name="text">
+             <string>&Locale</string>
             </property>
            </widget>
           </item>
-         </layout>
-        </item>
-       </layout>
-      </item>
-      <item row="0" column="0" >
-       <layout class="QHBoxLayout" >
-        <property name="spacing" >
-         <number>6</number>
-        </property>
-        <property name="margin" >
-         <number>0</number>
-        </property>
-        <item>
-         <layout class="QHBoxLayout" >
-          <property name="spacing" >
-           <number>6</number>
-          </property>
-          <property name="margin" >
-           <number>0</number>
-          </property>
-          <item>
-           <widget class="QLabel" name="label_3" >
-            <property name="text" >
-             <string>&Formula:</string>
-            </property>
-            <property name="buddy" >
-             <cstring>formulaLineEdit</cstring>
+          <item row="0" column="2">
+           <widget class="QPushButton" name="executePushButton">
+            <property name="text">
+             <string>&Execute</string>
             </property>
            </widget>
           </item>
-          <item>
-           <widget class="QLineEdit" name="formulaLineEdit" />
-          </item>
-         </layout>
-        </item>
-        <item>
-         <layout class="QHBoxLayout" >
-          <property name="spacing" >
-           <number>6</number>
-          </property>
-          <property name="margin" >
-           <number>0</number>
-          </property>
-          <item>
-           <widget class="QLabel" name="label_10" >
-            <property name="text" >
-             <string>&Charge:</string>
+          <item row="0" column="3">
+           <widget class="QPushButton" name="abortPushButton">
+            <property name="toolTip">
+             <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Abort the ongoing computation. In this case, the data that will be displayed will be incomplete and are shown only for forensic tasks.</p></body></html></string>
             </property>
-            <property name="buddy" >
-             <cstring>chargeSpinBox</cstring>
+            <property name="text">
+             <string>&Abort</string>
             </property>
            </widget>
           </item>
-          <item>
-           <widget class="QSpinBox" name="chargeSpinBox" />
+         </layout>
+        </widget>
+       </item>
+       <item row="2" column="1">
+        <widget class="QGroupBox" name="feedbackGroupBox">
+         <property name="title">
+          <string>Feedback</string>
+         </property>
+         <layout class="QGridLayout" name="gridLayout_11">
+          <item row="0" column="0">
+           <layout class="QVBoxLayout" name="verticalLayout_2">
+            <item>
+             <widget class="QGroupBox" name="inputDataFeedbackGroupBox">
+              <property name="title">
+               <string>Input data</string>
+              </property>
+              <layout class="QGridLayout" name="gridLayout_9">
+               <item row="0" column="0">
+                <widget class="QLineEdit" name="inputDataFeedbackLineEdit"/>
+               </item>
+              </layout>
+             </widget>
+            </item>
+            <item>
+             <widget class="QGroupBox" name="processingFeedbackGroupBox">
+              <property name="title">
+               <string>Processing</string>
+              </property>
+              <layout class="QGridLayout" name="gridLayout_10">
+               <item row="0" column="0">
+                <widget class="QLineEdit" name="feedbackLineEdit">
+                 <property name="font">
+                  <font>
+                   <weight>75</weight>
+                   <bold>true</bold>
+                  </font>
+                 </property>
+                 <property name="frame">
+                  <bool>false</bool>
+                 </property>
+                 <property name="readOnly">
+                  <bool>true</bool>
+                 </property>
+                </widget>
+               </item>
+               <item row="0" column="1">
+                <widget class="QProgressBar" name="progressBar">
+                 <property name="value">
+                  <number>24</number>
+                 </property>
+                 <property name="orientation">
+                  <enum>Qt::Horizontal</enum>
+                 </property>
+                </widget>
+               </item>
+              </layout>
+             </widget>
+            </item>
+           </layout>
           </item>
          </layout>
-        </item>
-       </layout>
-      </item>
-     </layout>
-    </widget>
-   </item>
-   <item row="2" column="0" >
-    <layout class="QHBoxLayout" >
-     <property name="spacing" >
-      <number>6</number>
-     </property>
-     <property name="margin" >
-      <number>0</number>
-     </property>
-     <item>
-      <spacer>
-       <property name="orientation" >
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeHint" stdset="0" >
-        <size>
-         <width>16</width>
-         <height>25</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <widget class="QPushButton" name="outputFilePushButton" >
-       <property name="toolTip" >
-        <string>Choose a file in which to store the data for the plotting of the isotopic peak. </string>
-       </property>
-       <property name="text" >
-        <string>&Output file...</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer>
-       <property name="orientation" >
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeHint" stdset="0" >
-        <size>
-         <width>21</width>
-         <height>25</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <widget class="QCheckBox" name="localeCheckBox" >
-       <property name="toolTip" >
-        <string>If checked all the numerical output will be generated with locale specificity.</string>
-       </property>
-       <property name="text" >
-        <string>&Locale</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer>
-       <property name="orientation" >
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeHint" stdset="0" >
-        <size>
-         <width>21</width>
-         <height>25</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <widget class="QPushButton" name="executePushButton" >
-       <property name="text" >
-        <string>&Execute</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer>
-       <property name="orientation" >
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="sizeHint" stdset="0" >
-        <size>
-         <width>21</width>
-         <height>25</height>
-        </size>
-       </property>
-      </spacer>
-     </item>
-     <item>
-      <widget class="QPushButton" name="abortPushButton" >
-       <property name="toolTip" >
-        <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Abort the ongoing computation. In this case, the data that will be displayed will be incomplete and are shown only for forensic tasks.</p></body></html></string>
-       </property>
-       <property name="text" >
-        <string>&Abort</string>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <spacer>
-       <property name="orientation" >
-        <enum>Qt::Horizontal</enum>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QGroupBox" name="resultsGroupBox">
+      <property name="title">
+       <string>Results</string>
+      </property>
+      <layout class="QGridLayout">
+       <property name="margin">
+        <number>9</number>
        </property>
-       <property name="sizeHint" stdset="0" >
-        <size>
-         <width>21</width>
-         <height>25</height>
-        </size>
+       <property name="spacing">
+        <number>6</number>
        </property>
-      </spacer>
-     </item>
-    </layout>
-   </item>
-   <item row="4" column="0" >
-    <widget class="QGroupBox" name="groupBox_2" >
-     <property name="title" >
-      <string>Results</string>
-     </property>
-     <layout class="QGridLayout" >
-      <property name="margin" >
-       <number>9</number>
-      </property>
-      <property name="spacing" >
-       <number>6</number>
-      </property>
-      <item row="0" column="0" >
-       <widget class="QTextEdit" name="resultTextEdit" >
-        <property name="toolTip" >
-         <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
+       <item row="0" column="0">
+        <widget class="QTextEdit" name="resultTextEdit">
+         <property name="toolTip">
+          <string><html><head><meta name="qrichtext" content="1" /><style type="text/css">
 p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Will display data about the isotopic peaks.</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note that if no file was chosen to write the plotting data, these data will be output in this text edit widget also.</p></body></html></string>
-        </property>
-       </widget>
-      </item>
-     </layout>
+</style></head><body style=" font-family:'Sans Serif'; font-size:6pt; font-weight:400; font-style:normal; text-decoration:none;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Will display data about the isotopic peaks.</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note that if no file was chosen to write the plotting data, these data will be output in this text edit widget also.</p></body></html></string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
-   <item row="5" column="0" >
-    <widget class="QLabel" name="label_2" >
-     <property name="font" >
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="font">
       <font>
        <pointsize>5</pointsize>
       </font>
      </property>
-     <property name="text" >
+     <property name="text">
       <string>Credit: the algorithm was partly adapted from the work of Dirk Nolting (nolting at uni-duesseldorf.de)</string>
      </property>
     </widget>
@@ -447,18 +552,12 @@ p, li { white-space: pre-wrap; }
  </widget>
  <tabstops>
   <tabstop>formulaLineEdit</tabstop>
-  <tabstop>chargeSpinBox</tabstop>
   <tabstop>minimumProbabilityDoubleSpinBox</tabstop>
-  <tabstop>resolutionSpinBox</tabstop>
   <tabstop>maximumPeaksSpinBox</tabstop>
-  <tabstop>outputFilePushButton</tabstop>
-  <tabstop>localeCheckBox</tabstop>
-  <tabstop>executePushButton</tabstop>
-  <tabstop>abortPushButton</tabstop>
   <tabstop>resultTextEdit</tabstop>
  </tabstops>
  <resources>
-  <include location="../application.qrc" />
+  <include location="../application.qrc"/>
  </resources>
  <connections/>
 </ui>
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 39933a6..749e7eb 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -33,6 +33,7 @@ SET (masslib_SRCS
   ionizable.cpp
   ionizeRule.cpp
   isotope.cpp
+  isotopicCurve.cpp
   isotopicPeak.cpp
   massList.cpp
   modif.cpp
diff --git a/lib/globals.cpp b/lib/globals.cpp
index d5eda96..69668d5 100644
--- a/lib/globals.cpp
+++ b/lib/globals.cpp
@@ -57,3 +57,12 @@ GlobUnspacifyQString(QString &src)
 }
 
 
+QString
+GlobBinaryRepresentation(int value)
+{
+  QString string;
+  string = QString("%1")
+    .arg(value, 10, 2);
+
+  return string;
+}
diff --git a/lib/globals.hpp b/lib/globals.hpp
index bbd45f5..0373c1d 100644
--- a/lib/globals.hpp
+++ b/lib/globals.hpp
@@ -117,6 +117,11 @@ enum PolymerChemEnt
      MXT_POLYMER_CHEMENT_FORCE_RIGHT_END_MODIF)
   };
 
+enum CurveType
+  {
+    MXP_CURVE_TYPE_GAUSSIAN = 1 << 0,
+    MXP_CURVE_TYPE_LORENTZIAN = 1 << 1,
+  };
 
 extern int MXP_ATOM_DEC_PLACES;
 extern int MXP_OLIGOMER_DEC_PLACES;
@@ -129,6 +134,8 @@ extern int MXP_PH_PKA_DEC_PLACES;
 QString &
 GlobUnspacifyQString(QString &);
 
+QString
+GlobBinaryRepresentation(int);
 
 
 #endif // GLOBALS_HPP
diff --git a/lib/ionizable.cpp b/lib/ionizable.cpp
index 19ce46e..3ad501b 100644
--- a/lib/ionizable.cpp
+++ b/lib/ionizable.cpp
@@ -342,18 +342,29 @@ namespace massXpert
   int 
   Ionizable::ionize()
   {
-    if (m_isIonized)
-      return 0;
-    
     if (!m_ionizeRule.isValid())
       return -1;
     
+    if (m_isIonized)
+      return 0;
+    
     // At this point perform the ionization proper.
     
     Formula formula(m_ionizeRule.formula());
     
     Ponderable temp(*this);
     
+    // qDebug() << __FILE__ << __LINE__ 
+    //          << "Before ionization:\n"
+    //          << "Ionizable's charge / level:"
+    //          << m_ionizeRule.charge() << "/" <<  m_ionizeRule.level()
+    //          << " -- "
+    //          << "Ionizable's whole charge:"
+    //          << m_ionizeRule.charge() * m_ionizeRule.level()
+    //          << " -- "
+    //          << "Mono:" << temp.mono() << "Avg:" << temp.avg()
+    //          << "\n\n";
+    
     double localMono = 0;
     double localAvg = 0;
 
@@ -370,24 +381,34 @@ namespace massXpert
     // charge and level values of m_ionizeRule cannot be <= 0 because
     // otherwise the m_ionizRule would not have validated.
     
+    int ionCharge = m_ionizeRule.charge() * m_ionizeRule.level();
+
     m_mono += localMono;
-    m_mono = m_mono /(m_ionizeRule.charge() * m_ionizeRule.level());
+    m_mono = m_mono /ionCharge;
 
     m_avg += localAvg;
-    m_avg = m_avg /(m_ionizeRule.charge() * m_ionizeRule.level());
+    m_avg = m_avg / ionCharge;
     
     // Of course, we now are ionized.
     m_isIonized = true;
     
-//     qDebug() << __FILE__ << __LINE__ 
-// 	      << "Total charge:"
-// 	      << m_ionizeRule.charge() * m_ionizeRule.level()
-// 	      << "After ionization: Mono:" << m_mono << "Avg:" << m_avg;
-
+    // qDebug() << __FILE__ << __LINE__ 
+    //          << "After ionization:\n"
+    //          << "Ionizable's charge / level:"
+    //          << m_ionizeRule.charge() << "/" <<  m_ionizeRule.level() 
+    //          << " -- "
+    //          << "Ionizable's whole charge:"
+    //          << m_ionizeRule.charge() * m_ionizeRule.level()
+    //          << " -- "
+    //          << "Mono:" << m_mono << "Avg:" << m_avg
+    //          << "\n\n";
+    
     // If something changed in the masses, then return 1, otherwise
     // return 0.
-    if (temp != *this)
-      return 1;
+    if (temp != static_cast<Ponderable>(*this))
+      {
+        return 1;
+      }
     
     return 0;
   }
@@ -509,8 +530,6 @@ namespace massXpert
   int 
   Ionizable::ionize(Ionizable *ionizable, const IonizeRule &ionizeRule)
   {
-    Q_ASSERT(ionizable);
-    
     if (!ionizeRule.isValid())
       return -1;
     
diff --git a/lib/isotopicPeak.cpp b/lib/isotopicPeak.cpp
index b106d64..221bcb6 100644
--- a/lib/isotopicPeak.cpp
+++ b/lib/isotopicPeak.cpp
@@ -56,18 +56,21 @@ namespace massXpert
     \param relIntensity relative intensity. Defaults to 0. Cannot be
     negative.
   */
-  IsotopicPeak::IsotopicPeak(double mass, double abundance,
-			      double probability, double relIntensity)
+  IsotopicPeak::IsotopicPeak(double mass, double relIntensity,
+                             double probability, double abundance)
   {
+    qDebug() << __FILE__ << __LINE__
+             << "relIntensity:" << relIntensity;
+    
     Q_ASSERT(mass >= 0);
-    Q_ASSERT(abundance >= 0);
-    Q_ASSERT(probability >= 0);
     Q_ASSERT(relIntensity >= 0);
+    Q_ASSERT(probability >= 0);
+    Q_ASSERT(abundance >= 0);
 
     m_mass = mass;
-    m_abundance = abundance;
-    m_probability = probability;
     m_relativeIntensity = relIntensity;
+    m_probability = probability;
+    m_abundance = abundance;
   }
 
 
diff --git a/lib/isotopicPeak.hpp b/lib/isotopicPeak.hpp
index 14396be..ebe23e9 100644
--- a/lib/isotopicPeak.hpp
+++ b/lib/isotopicPeak.hpp
@@ -72,8 +72,9 @@ namespace massXpert
     double m_relativeIntensity;
   
   public:
-    IsotopicPeak(double = 0, double = 0, double = 0, double = 0);
-    IsotopicPeak(Isotope &, double = 0, double = 0);
+    IsotopicPeak(double /* mass */, double /* relIntensity */,
+                 double /* probability */, double /* abundance */);
+    IsotopicPeak(Isotope &, double, double);
     IsotopicPeak(const IsotopicPeak &);
 
     virtual IsotopicPeak * clone() const;
diff --git a/lib/ponderable.cpp b/lib/ponderable.cpp
index 97dabab..d08bf65 100644
--- a/lib/ponderable.cpp
+++ b/lib/ponderable.cpp
@@ -37,7 +37,7 @@
 
 /////////////////////// Qt includes
 #include <QtGlobal>
-
+#include <QDebug>
 
 /////////////////////// Local includes
 #include "ponderable.hpp"
@@ -478,8 +478,19 @@ namespace massXpert
   Ponderable::operator !=(const Ponderable &other) const
   {
     if (m_mono != other.m_mono || m_avg != other.m_avg)
-      return true;
-
+      {
+        // qDebug() << __FILE__ << __LINE__ 
+        //          << "m_mono:" << m_mono 
+        //          << "/" 
+        //          << "other.m_mono:" << other.m_mono
+        //          << "--"
+        //          << "m_avg:" << m_avg
+        //          << "/" 
+        //          << "other.m_avg:" << other.m_avg;
+        
+        return true;
+      }
+    
     return false;
   }
 

-- 
massXpert mass spectrometry suite: debian packaging



More information about the Debichem-commits mailing list