From 3b759b2bcc369381b36e68c19d40e35be30e3b0a Mon Sep 17 00:00:00 2001 From: Roman Tolchenov <roman.tolchenov@stfc.ac.uk> Date: Fri, 30 Jul 2010 12:41:36 +0000 Subject: [PATCH] Added the Plot Guess button to the fit browser, made possible to enter doubles in exponential notation, the number of decimal places can be set from the preferences dialog. re #1436 --- .../QtPropertyBrowser/qtpropertybrowser.pro | 6 +- .../src/DoubleEditorFactory.cpp | 63 +++++++++++++++++ .../src/DoubleEditorFactory.h | 34 +++++++++ .../src/qtpropertymanager.cpp | 5 +- Code/qtiplot/qtiplot/src/ConfigDialog.cpp | 46 +++++++++--- Code/qtiplot/qtiplot/src/ConfigDialog.h | 2 + .../qtiplot/src/Mantid/FitPropertyBrowser.cpp | 70 ++++++++++++++++--- .../qtiplot/src/Mantid/FitPropertyBrowser.h | 13 +++- .../qtiplot/src/Mantid/PropertyHandler.cpp | 12 +++- 9 files changed, 228 insertions(+), 23 deletions(-) create mode 100644 Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.cpp create mode 100644 Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.h diff --git a/Code/qtiplot/QtPropertyBrowser/qtpropertybrowser.pro b/Code/qtiplot/QtPropertyBrowser/qtpropertybrowser.pro index 1b508c637c6..7a05c5e0e81 100644 --- a/Code/qtiplot/QtPropertyBrowser/qtpropertybrowser.pro +++ b/Code/qtiplot/QtPropertyBrowser/qtpropertybrowser.pro @@ -13,7 +13,8 @@ SOURCES += src/qtpropertybrowser.cpp \ src/qtbuttonpropertybrowser.cpp \ src/qtgroupboxpropertybrowser.cpp \ src/qtpropertybrowserutils.cpp \ - src/FilenameEditorFactory.cpp + src/FilenameEditorFactory.cpp \ + src/DoubleEditorFactory.cpp HEADERS += src/qtpropertybrowser.h \ src/qtpropertymanager.h \ src/qteditorfactory.h \ @@ -22,7 +23,8 @@ HEADERS += src/qtpropertybrowser.h \ src/qtbuttonpropertybrowser.h \ src/qtgroupboxpropertybrowser.h \ src/qtpropertybrowserutils_p.h \ - src/FilenameEditorFactory.h + src/FilenameEditorFactory.h \ + src/DoubleEditorFactory.h RESOURCES += src/qtpropertybrowser.qrc win32 { diff --git a/Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.cpp b/Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.cpp new file mode 100644 index 00000000000..a2ae40280a6 --- /dev/null +++ b/Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.cpp @@ -0,0 +1,63 @@ +#include "DoubleEditorFactory.h" + +#include <QDoubleValidator> + +#include <iostream> +#include <cfloat> +#include <sstream> +#include <cmath> + +void DoubleEditorFactory::connectPropertyManager(QtDoublePropertyManager *manager) +{ +} + +QWidget* DoubleEditorFactory::createEditor(QtDoublePropertyManager *manager, QtProperty *property,QWidget *parent) +{ + return new DoubleEditor(property,parent); +} + +void DoubleEditorFactory::disconnectPropertyManager(QtDoublePropertyManager *manager) +{ +} + +DoubleEditor::DoubleEditor(QtProperty *property, QWidget *parent) +:QLineEdit(parent), +m_property(property) +{ + QtDoublePropertyManager* mgr = dynamic_cast<QtDoublePropertyManager*>(property->propertyManager()); + if (!mgr) + { + throw std::runtime_error("QtDoublePropertyManager expected as parent of DoubleEditor"); + } + + m_decimals = mgr->decimals(property); + setValidator(new QDoubleValidator( + mgr->minimum(property), + mgr->maximum(property), + 20, + this)); + connect(this,SIGNAL(editingFinished()),this,SLOT(updateProperty())); + double val = mgr->value(property); + setValue(mgr->value(property)); +} + +DoubleEditor::~DoubleEditor() +{ +} + +void DoubleEditor::setValue(const double& d) +{ + double absVal = fabs(d); + char format = absVal > 1e5 || (absVal != 0 && absVal < 1e-5) ? 'e' : 'f'; + setText(QString::number(d,format , m_decimals)); +} + +void DoubleEditor::updateProperty() +{ + QtDoublePropertyManager* mgr = dynamic_cast<QtDoublePropertyManager*>(m_property->propertyManager()); + if (mgr) + { + mgr->setValue(m_property,text().toDouble()); + } +} + diff --git a/Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.h b/Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.h new file mode 100644 index 00000000000..95f881e8a38 --- /dev/null +++ b/Code/qtiplot/QtPropertyBrowser/src/DoubleEditorFactory.h @@ -0,0 +1,34 @@ +#ifndef DOUBLEEDITORFACTORY_H +#define DOUBLEEDITORFACTORY_H + +#include "qtpropertymanager.h" + +#include <QLineEdit> + +class QT_QTPROPERTYBROWSER_EXPORT DoubleEditorFactory : public QtAbstractEditorFactory<QtDoublePropertyManager> +{ + Q_OBJECT +public: + DoubleEditorFactory(QObject *parent = 0): QtAbstractEditorFactory<QtDoublePropertyManager>(parent){} +protected: + void connectPropertyManager(QtDoublePropertyManager *manager); + QWidget *createEditor(QtDoublePropertyManager *manager, QtProperty *property, + QWidget *parent); + void disconnectPropertyManager(QtDoublePropertyManager *manager); +}; + +class QT_QTPROPERTYBROWSER_EXPORT DoubleEditor: public QLineEdit +{ + Q_OBJECT +public: + DoubleEditor(QtProperty *property, QWidget *parent); + ~DoubleEditor(); + void setValue(const double& d); +private slots: + void updateProperty(); +private: + QtProperty* m_property; + int m_decimals; +}; + +#endif // DOUBLEEDITORFACTORY_H diff --git a/Code/qtiplot/QtPropertyBrowser/src/qtpropertymanager.cpp b/Code/qtiplot/QtPropertyBrowser/src/qtpropertymanager.cpp index a225ef2ab3f..99b6894defe 100644 --- a/Code/qtiplot/QtPropertyBrowser/src/qtpropertymanager.cpp +++ b/Code/qtiplot/QtPropertyBrowser/src/qtpropertymanager.cpp @@ -102,6 +102,7 @@ #include <limits.h> #include <float.h> +#include <math.h> #if defined(Q_CC_MSVC) # pragma warning(disable: 4786) /* MS VS 6: truncating debug info after 255 characters */ @@ -1106,7 +1107,9 @@ QString QtDoublePropertyManager::valueText(const QtProperty *property) const const QtDoublePropertyManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); if (it == d_ptr->m_values.constEnd()) return QString(); - return QString::number(it.value().val, 'f', it.value().decimals); + double absVal = fabs(it.value().val); + char format = absVal > 1e5 || (absVal != 0 && absVal < 1e-5) ? 'e' : 'f'; + return QString::number(it.value().val,format , it.value().decimals); } /*! diff --git a/Code/qtiplot/qtiplot/src/ConfigDialog.cpp b/Code/qtiplot/qtiplot/src/ConfigDialog.cpp index 3a05b7970ba..5369c2f8186 100644 --- a/Code/qtiplot/qtiplot/src/ConfigDialog.cpp +++ b/Code/qtiplot/qtiplot/src/ConfigDialog.cpp @@ -35,6 +35,8 @@ #include "ColorBox.h" #include "pixmaps.h" #include "DoubleSpinBox.h" +#include "Mantid/MantidUI.h" +#include "Mantid/FitPropertyBrowser.h" #include <QLocale> #include <QPushButton> @@ -816,7 +818,15 @@ void ConfigDialog::initCurveFittingTab() findPeaksTolerance = new QSpinBox(); grid->addWidget(findPeaksTolerance, 4,1); - grid->setRowStretch(5,1); + grid->addWidget(new QLabel(tr("Peak Radius (in FWHM)")),5,0); + peakRadius = new QSpinBox(); + grid->addWidget(peakRadius, 5,1); + + grid->addWidget(new QLabel(tr("Double property decimals")),6,0); + decimals = new QSpinBox(); + grid->addWidget(decimals, 6,1); + + grid->setRowStretch(7,1); label = new QLabel("<span style=\"font-weight:600;\">Note: Changes will not take effect until MantidPlot has been restarted.</span>"); curveTabLayout->addWidget(label); @@ -841,7 +851,7 @@ void ConfigDialog::initCurveFittingTab() } // Set the correct default property - QString setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.AutoBackground")); + QString setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground")); QStringList value = setting.split(' '); int index(-1); if( value.isEmpty() ) @@ -867,7 +877,7 @@ void ConfigDialog::initCurveFittingTab() backgroundFunctions->setCurrentIndex(index); } - setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.DefaultPeak")); + setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.defaultPeak")); if (setting.isEmpty()) setting = "Gaussian"; index = defaultPeakShape->findText(setting); if (index >= 0) @@ -875,7 +885,7 @@ void ConfigDialog::initCurveFittingTab() defaultPeakShape->setCurrentIndex(index); } - setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.FindPeaksFWHM")); + setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksFWHM")); if (!setting.isEmpty()) { findPeaksFWHM->setValue(setting.toInt()); @@ -885,7 +895,7 @@ void ConfigDialog::initCurveFittingTab() findPeaksFWHM->setValue(7); } - setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.FindPeaksTolerance")); + setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksTolerance")); if (!setting.isEmpty()) { findPeaksTolerance->setValue(setting.toInt()); @@ -895,6 +905,18 @@ void ConfigDialog::initCurveFittingTab() findPeaksTolerance->setValue(4); } + setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.peakRadius")); + if (!setting.isEmpty()) + { + peakRadius->setValue(setting.toInt()); + } + else + { + peakRadius->setValue(5); + } + + ApplicationWindow *app = (ApplicationWindow *)parentWidget(); + decimals->setValue(app->mantidUI->fitFunctionBrowser()->getDecimals()); } @@ -1771,16 +1793,22 @@ void ConfigDialog::updateCurveFitSettings() setting += std::string(" ") + args.toStdString(); } - mantid_config.setString("CurveFitting.AutoBackground", setting); + mantid_config.setString("curvefitting.autoBackground", setting); setting = defaultPeakShape->currentText().toStdString(); - mantid_config.setString("CurveFitting.DefaultPeak", setting); + mantid_config.setString("curvefitting.defaultPeak", setting); setting = QString::number(findPeaksFWHM->value()).toStdString(); - mantid_config.setString("CurveFitting.FindPeaksFWHM", setting); + mantid_config.setString("curvefitting.findPeaksFWHM", setting); setting = QString::number(findPeaksTolerance->value()).toStdString(); - mantid_config.setString("CurveFitting.FindPeaksTolerance", setting); + mantid_config.setString("curvefitting.findPeaksTolerance", setting); + + setting = QString::number(peakRadius->value()).toStdString(); + mantid_config.setString("curvefitting.peakRadius", setting); + + ApplicationWindow *app = (ApplicationWindow *)parentWidget(); + app->mantidUI->fitFunctionBrowser()->setDecimals(decimals->value()); } diff --git a/Code/qtiplot/qtiplot/src/ConfigDialog.h b/Code/qtiplot/qtiplot/src/ConfigDialog.h index 11774673135..0e8d2c5522b 100644 --- a/Code/qtiplot/qtiplot/src/ConfigDialog.h +++ b/Code/qtiplot/qtiplot/src/ConfigDialog.h @@ -166,6 +166,8 @@ private: QLineEdit *functionArguments; QComboBox *defaultPeakShape; QSpinBox *findPeaksFWHM,*findPeaksTolerance; + QSpinBox *peakRadius; + QSpinBox *decimals; QPushButton* buttonAxesFont, *buttonNumbersFont, *buttonLegendFont, *buttonTitleFont, *fontsBtn; QCheckBox *boxSearchUpdates, *boxOrthogonal, *logBox, *plotLabelBox, *scaleErrorsBox; diff --git a/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.cpp b/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.cpp index 09a2aa6a144..a5706946f72 100644 --- a/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.cpp +++ b/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.cpp @@ -17,6 +17,7 @@ #include "MantidKernel/LibraryManager.h" #include "FilenameEditorFactory.h" +#include "DoubleEditorFactory.h" #include "qttreepropertybrowser.h" #include "qtpropertymanager.h" @@ -54,9 +55,10 @@ m_guessOutputName(true), m_changeSlotsEnabled(false), m_peakToolOn(false), m_auto_back(false), -m_autoBgName(QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.AutoBackground"))), +m_autoBgName(QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground"))), m_autoBackground(NULL), -m_logValue(NULL) +m_logValue(NULL), +m_decimals(-1) { // Make sure plugins are loaded std::string libpath = Mantid::Kernel::ConfigService::Instance().getString("plugins.directory"); @@ -77,13 +79,13 @@ m_logValue(NULL) setAutoBackgroundName(m_autoBgName); } - std::string def = Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.DefaultPeak"); + std::string def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.defaultPeak"); if (!def.empty()) { m_defaultPeak = def; } - def = Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.AutoBackground"); + def = Mantid::Kernel::ConfigService::Instance().getString("curvefitting.autoBackground"); if (!def.empty()) { m_defaultBackground = def; @@ -159,6 +161,7 @@ m_logValue(NULL) QtEnumEditorFactory *comboBoxFactory = new QtEnumEditorFactory(w); QtSpinBoxFactory *spinBoxFactory = new QtSpinBoxFactory(w); QtDoubleSpinBoxFactory *doubleSpinBoxFactory = new QtDoubleSpinBoxFactory(w); + DoubleEditorFactory *doubleEditorFactory = new DoubleEditorFactory(w); QtLineEditFactory *lineEditFactory = new QtLineEditFactory(w); FilenameEditorFactory* filenameEditFactory = new FilenameEditorFactory(w); @@ -166,10 +169,13 @@ m_logValue(NULL) m_browser->setFactoryForManager(m_enumManager, comboBoxFactory); m_browser->setFactoryForManager(m_boolManager, checkBoxFactory); m_browser->setFactoryForManager(m_intManager, spinBoxFactory); - m_browser->setFactoryForManager(m_doubleManager, doubleSpinBoxFactory); + //m_browser->setFactoryForManager(m_doubleManager, doubleSpinBoxFactory); + m_browser->setFactoryForManager(m_doubleManager, doubleEditorFactory); m_browser->setFactoryForManager(m_stringManager, lineEditFactory); m_browser->setFactoryForManager(m_filenameManager, filenameEditFactory); + updateDecimals(); + m_functionsGroup = m_browser->addProperty(functionsGroup); m_settingsGroup = m_browser->addProperty(settingsGroup); @@ -191,6 +197,10 @@ m_logValue(NULL) QPushButton* btnFindPeaks = new QPushButton("Find peaks"); connect(btnFindPeaks,SIGNAL(clicked()),this,SLOT(findPeaks())); + m_btnPlotGuess = new QPushButton("Plot guess"); + connect(m_btnPlotGuess,SIGNAL(clicked()),this,SLOT(plotOrRemoveGuessAll())); + m_btnPlotGuess->setEnabled(false); + m_tip = new QLabel("",w); buttonsLayout->addWidget(m_btnFit,0,0); @@ -198,6 +208,7 @@ m_logValue(NULL) buttonsLayout->addWidget(btnClear,0,2); buttonsLayout->addWidget(btnSeqFit,1,0); buttonsLayout->addWidget(btnFindPeaks,1,1); + buttonsLayout->addWidget(m_btnPlotGuess,1,2); layout->addLayout(buttonsLayout); layout->addWidget(m_tip); @@ -1643,6 +1654,18 @@ void FitPropertyBrowser::removeGuessAll() emit removeGuess(); } +void FitPropertyBrowser::plotOrRemoveGuessAll() +{ + if (getHandler()->hasPlot()) + { + removeGuessAll(); + } + else + { + plotGuessAll(); + } +} + /** Create a double property and set some settings * @param name The name of the new property * @return Pointer to the created property @@ -1650,7 +1673,8 @@ void FitPropertyBrowser::removeGuessAll() QtProperty* FitPropertyBrowser::addDoubleProperty(const QString& name)const { QtProperty* prop = m_doubleManager->addProperty(name); - m_doubleManager->setDecimals(prop,6); + m_doubleManager->setDecimals(prop,m_decimals); + m_doubleManager->setRange(prop,-DBL_MAX,DBL_MAX); return prop; } @@ -1946,10 +1970,10 @@ void FitPropertyBrowser::findPeaks() std::string smoothedName = wsName + "_SmoothedData_tmp"; int FWHM,Tolerance; - QString setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.FindPeaksFWHM")); + QString setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksFWHM")); FWHM = setting.isEmpty() ? 7 : setting.toInt(); - setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("CurveFitting.FindPeaksTolerance")); + setting = QString::fromStdString(Mantid::Kernel::ConfigService::Instance().getString("curvefitting.findPeaksTolerance")); Tolerance = setting.isEmpty() ? 4 : setting.toInt(); Mantid::API::IAlgorithm_sptr alg = Mantid::API::AlgorithmManager::Instance().create("FindPeaks"); @@ -1996,3 +2020,33 @@ void FitPropertyBrowser::findPeaks() QApplication::restoreOverrideCursor(); } + +void FitPropertyBrowser::setPeakToolOn(bool on) +{ + m_peakToolOn = on; + m_btnPlotGuess->setEnabled(on); +} + +void FitPropertyBrowser::updateDecimals() +{ + if (m_decimals < 0) + { + QSettings settings; + settings.beginGroup("Mantid/FitBrowser"); + m_decimals = settings.value("decimals",6).toInt(); + } + QSet<QtProperty *> props = m_doubleManager->properties(); + foreach(QtProperty *prop,props) + { + m_doubleManager->setDecimals(prop,m_decimals); + } +} + +void FitPropertyBrowser::setDecimals(int d) +{ + m_decimals = d; + QSettings settings; + settings.beginGroup("Mantid/FitBrowser"); + settings.setValue("decimals",d); + updateDecimals(); +} diff --git a/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.h b/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.h index 8ccf468a572..1e9ed406976 100644 --- a/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.h +++ b/Code/qtiplot/qtiplot/src/Mantid/FitPropertyBrowser.h @@ -163,13 +163,17 @@ public: void setAutoBackgroundName(const QString& aName); void refitAutoBackground(); + /// Number of decimal places in double properties + int getDecimals()const{return m_decimals;} + void setDecimals(int d); + public slots: void fit(); void sequentialFit(); void undoFit(); void clear(); void clearBrowser(); - void setPeakToolOn(bool on){m_peakToolOn = on;} + void setPeakToolOn(bool on); void findPeaks(); signals: @@ -218,10 +222,12 @@ private slots: void plotGuessAll(); void removeGuessCurrent(); void removeGuessAll(); + void plotOrRemoveGuessAll(); void saveFunction(); void loadFunction(); void copy();///< Copy the function string to the clipboard void paste();///< Paste a function string from the clipboard + void updateDecimals(); void popupMenu(const QPoint &); /* Context menu slots */ @@ -270,6 +276,8 @@ private: QPushButton* m_btnFit; /// Button for undoing fit QPushButton* m_btnUnFit; + /// Button for plotting the overall function + QPushButton* m_btnPlotGuess; /// To display a tip text QLabel* m_tip; @@ -358,6 +366,9 @@ private: /// Log names QStringList m_logs; + /// Number of decimal places in double properties + int m_decimals; + friend class PropertyHandler; friend class CreateAttributeProperty; friend class SetAttribute; diff --git a/Code/qtiplot/qtiplot/src/Mantid/PropertyHandler.cpp b/Code/qtiplot/qtiplot/src/Mantid/PropertyHandler.cpp index da77aa0e709..b9d821e56bd 100644 --- a/Code/qtiplot/qtiplot/src/Mantid/PropertyHandler.cpp +++ b/Code/qtiplot/qtiplot/src/Mantid/PropertyHandler.cpp @@ -1167,7 +1167,7 @@ void PropertyHandler::addConstraint(QtProperty* parProp,bool lo,bool up,double l ostr << loBound << "<"; if (!hasLo) { - cnew.first = m_browser->m_doubleManager->addProperty("LowerBound"); + cnew.first = m_browser->addDoubleProperty("LowerBound"); parProp->addSubProperty(cnew.first); } else @@ -1182,7 +1182,7 @@ void PropertyHandler::addConstraint(QtProperty* parProp,bool lo,bool up,double l ostr << "<" << upBound; if (!hasUp) { - cnew.second = m_browser->m_doubleManager->addProperty("UpperBound"); + cnew.second = m_browser->addDoubleProperty("UpperBound"); parProp->addSubProperty(cnew.second); } else @@ -1270,6 +1270,10 @@ void PropertyHandler::plot(Graph* g)const // Graph now owns m_curve. Use m_curve->removeMe() to remove (and delete) from Graph g->insertCurve(m_curve); connect(m_curve,SIGNAL(forgetMe(PlotCurve*)),this,SLOT(plotRemoved(PlotCurve*))); + if (this == m_browser->getHandler()) + { + m_browser->m_btnPlotGuess->setText("Remove guess"); + } } } @@ -1282,6 +1286,10 @@ void PropertyHandler::removePlot() { m_curve->removeMe(); m_curve = NULL; + if (this == m_browser->getHandler()) + { + m_browser->m_btnPlotGuess->setText("Plot guess"); + } } } -- GitLab