File indexing completed on 2024-05-12 15:28:17

0001 /***************************************************************************
0002     File                 : FitOptionsWidget.cc
0003     Project              : LabPlot
0004     Description          : widget for editing advanced fit options
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2014-2020 Alexander Semke (alexander.semke@web.de)
0007     Copyright            : (C) 2017-2018 Stefan Gerlach (stefan.gerlach@uni.kn)
0008 
0009  ***************************************************************************/
0010 
0011 /***************************************************************************
0012  *                                                                         *
0013  *  This program is free software; you can redistribute it and/or modify   *
0014  *  it under the terms of the GNU General Public License as published by   *
0015  *  the Free Software Foundation; either version 2 of the License, or      *
0016  *  (at your option) any later version.                                    *
0017  *                                                                         *
0018  *  This program is distributed in the hope that it will be useful,        *
0019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0021  *  GNU General Public License for more details.                           *
0022  *                                                                         *
0023  *   You should have received a copy of the GNU General Public License     *
0024  *   along with this program; if not, write to the Free Software           *
0025  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0026  *   Boston, MA  02110-1301  USA                                           *
0027  *                                                                         *
0028  ***************************************************************************/
0029 #include "FitOptionsWidget.h"
0030 #include "backend/worksheet/plots/cartesian/CartesianPlot.h"
0031 
0032 /*!
0033     \class FitOptionsWidget
0034     \brief Widget for editing advanced fit options.
0035 
0036     \ingroup kdefrontend
0037  */
0038 FitOptionsWidget::FitOptionsWidget(QWidget* parent, XYFitCurve::FitData* fitData, XYFitCurve* fitCurve) : QWidget(parent),
0039     m_fitData(fitData), m_fitCurve(fitCurve) {
0040     ui.setupUi(this);
0041     ui.pbApply->setIcon(QIcon::fromTheme("dialog-ok-apply"));
0042     ui.pbCancel->setIcon(QIcon::fromTheme("dialog-cancel"));
0043 
0044     //TODO: show "robust" option when robust fitting is possible
0045 //  ui.cbRobust->addItem(i18n("on"));
0046 //  ui.cbRobust->addItem(i18n("off"));
0047     ui.lRobust->setVisible(false);
0048     ui.cbRobust->setVisible(false);
0049 
0050     ui.leMaxIterations->setValidator( new QIntValidator(ui.leMaxIterations) );
0051     ui.leEps->setValidator( new QDoubleValidator(ui.leEps) );
0052     ui.leEvaluatedPoints->setValidator( new QIntValidator(ui.leEvaluatedPoints) );
0053 
0054     SET_NUMBER_LOCALE
0055     ui.leMaxIterations->setText(numberLocale.toString(m_fitData->maxIterations));
0056     ui.leEps->setText(numberLocale.toString(m_fitData->eps));
0057     ui.leEvaluatedPoints->setText(numberLocale.toString(static_cast<qulonglong>(m_fitData->evaluatedPoints)));
0058     ui.sbConfidenceInterval->setLocale(numberLocale);
0059 
0060     //range widgets
0061     const auto* plot = static_cast<const CartesianPlot*>(fitCurve->parentAspect());
0062     m_dateTimeRange = (plot->xRangeFormat() != CartesianPlot::RangeFormat::Numeric);
0063     if (!m_dateTimeRange) {
0064         ui.leMin->setText(numberLocale.toString(m_fitData->fitRange.min()));
0065         ui.leMax->setText(numberLocale.toString(m_fitData->fitRange.max()));
0066         ui.leEvalMin->setText(numberLocale.toString(m_fitData->evalRange.min()));
0067         ui.leEvalMax->setText(numberLocale.toString(m_fitData->evalRange.max()));
0068     } else {
0069         ui.dateTimeEditMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->fitRange.min()) );
0070         ui.dateTimeEditMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->fitRange.max()) );
0071         ui.dateTimeEditEvalMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->evalRange.min()) );
0072         ui.dateTimeEditEvalMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->evalRange.max()) );
0073     }
0074 
0075     ui.leMin->setVisible(!m_dateTimeRange);
0076     ui.leMax->setVisible(!m_dateTimeRange);
0077     ui.lXRange->setVisible(!m_dateTimeRange);
0078     ui.leEvalMin->setVisible(!m_dateTimeRange);
0079     ui.leEvalMax->setVisible(!m_dateTimeRange);
0080     ui.lEvalRange->setVisible(!m_dateTimeRange);
0081     ui.dateTimeEditMin->setVisible(m_dateTimeRange);
0082     ui.dateTimeEditMax->setVisible(m_dateTimeRange);
0083     ui.lXRangeDateTime->setVisible(m_dateTimeRange);
0084     ui.dateTimeEditEvalMin->setVisible(m_dateTimeRange);
0085     ui.dateTimeEditEvalMax->setVisible(m_dateTimeRange);
0086     ui.lEvalRangeDateTime->setVisible(m_dateTimeRange);
0087 
0088     //auto range
0089     ui.cbAutoRange->setChecked(m_fitData->autoRange);
0090     ui.cbAutoEvalRange->setChecked(m_fitData->autoEvalRange);
0091     this->autoRangeChanged();
0092     this->autoEvalRangeChanged();
0093 
0094     ui.cbUseDataErrors->setChecked(m_fitData->useDataErrors);
0095     ui.cbUseResults->setChecked(m_fitData->useResults);
0096     ui.cbPreview->setChecked(m_fitData->previewEnabled);
0097     ui.sbConfidenceInterval->setValue(m_fitData->confidenceInterval);
0098 
0099     //SLOTS
0100     connect(ui.leEps, &QLineEdit::textChanged, this, &FitOptionsWidget::changed);
0101     connect(ui.leMaxIterations, &QLineEdit::textChanged, this, &FitOptionsWidget::changed);
0102     connect(ui.leEvaluatedPoints, &QLineEdit::textChanged, this, &FitOptionsWidget::changed);
0103     connect(ui.cbUseDataErrors, &QCheckBox::clicked, this, &FitOptionsWidget::changed);
0104     connect(ui.cbUseResults, &QCheckBox::clicked, this, &FitOptionsWidget::changed);
0105     connect(ui.cbPreview, &QCheckBox::clicked, this, &FitOptionsWidget::changed);
0106     connect(ui.sbConfidenceInterval, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &FitOptionsWidget::changed);
0107     connect(ui.pbApply, &QPushButton::clicked, this, &FitOptionsWidget::applyClicked);
0108     connect(ui.pbCancel, &QPushButton::clicked, this, &FitOptionsWidget::finished);
0109     connect(ui.cbAutoRange, &QCheckBox::clicked, this, &FitOptionsWidget::autoRangeChanged);
0110     connect(ui.cbAutoEvalRange, &QCheckBox::clicked, this, &FitOptionsWidget::autoEvalRangeChanged);
0111     connect(ui.leMin, &QLineEdit::textChanged, this, &FitOptionsWidget::fitRangeMinChanged);
0112     connect(ui.leMax, &QLineEdit::textChanged, this, &FitOptionsWidget::fitRangeMaxChanged);
0113     connect(ui.dateTimeEditMin, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::fitRangeMinDateTimeChanged);
0114     connect(ui.dateTimeEditMax, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::fitRangeMaxDateTimeChanged);
0115     connect(ui.leEvalMin, &QLineEdit::textChanged, this, &FitOptionsWidget::evalRangeMinChanged);
0116     connect(ui.leEvalMax, &QLineEdit::textChanged, this, &FitOptionsWidget::evalRangeMaxChanged);
0117     connect(ui.dateTimeEditEvalMin, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::evalRangeMinDateTimeChanged);
0118     connect(ui.dateTimeEditEvalMax, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::evalRangeMaxDateTimeChanged);
0119 }
0120 
0121 void FitOptionsWidget::autoRangeChanged() {
0122     const bool autoRange = ui.cbAutoRange->isChecked();
0123     m_fitData->autoRange = autoRange;
0124 
0125     ui.leMin->setEnabled(!autoRange);
0126     ui.lXRange->setEnabled(!autoRange);
0127     ui.leMax->setEnabled(!autoRange);
0128     ui.dateTimeEditMin->setEnabled(!autoRange);
0129     ui.lXRange->setEnabled(!autoRange);
0130     ui.dateTimeEditMax->setEnabled(!autoRange);
0131 
0132     if (autoRange) {
0133         const AbstractColumn* xDataColumn = nullptr;
0134         if (m_fitCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet)
0135             xDataColumn = m_fitCurve->xDataColumn();
0136         else {
0137             if (m_fitCurve->dataSourceCurve())
0138                 xDataColumn = m_fitCurve->dataSourceCurve()->xColumn();
0139         }
0140 
0141         if (xDataColumn) {
0142             const double xMin = xDataColumn->minimum();
0143             const double xMax = xDataColumn->maximum();
0144             m_fitData->fitRange.setRange(xMin, xMax);
0145 
0146             SET_NUMBER_LOCALE
0147             if (!m_dateTimeRange) {
0148                 ui.leMin->setText(numberLocale.toString(xMin));
0149                 ui.leMax->setText(numberLocale.toString(xMax));
0150             } else {
0151                 ui.dateTimeEditMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xMin));
0152                 ui.dateTimeEditMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xMax));
0153             }
0154         }
0155     }
0156 }
0157 
0158 void FitOptionsWidget::autoEvalRangeChanged() {
0159     const bool autoRange = ui.cbAutoEvalRange->isChecked();
0160     m_fitData->autoEvalRange = autoRange;
0161 
0162     ui.leEvalMin->setEnabled(!autoRange);
0163     ui.lEvalRange->setEnabled(!autoRange);
0164     ui.leEvalMax->setEnabled(!autoRange);
0165     ui.dateTimeEditEvalMin->setEnabled(!autoRange);
0166     ui.lEvalRange->setEnabled(!autoRange);
0167     ui.dateTimeEditEvalMax->setEnabled(!autoRange);
0168 
0169     if (autoRange) {
0170         const AbstractColumn* xDataColumn = nullptr;
0171         if (m_fitCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet)
0172             xDataColumn = m_fitCurve->xDataColumn();
0173         else {
0174             if (m_fitCurve->dataSourceCurve())
0175                 xDataColumn = m_fitCurve->dataSourceCurve()->xColumn();
0176         }
0177 
0178         if (xDataColumn) {
0179             const double xMin = xDataColumn->minimum();
0180             const double xMax = xDataColumn->maximum();
0181             m_fitData->evalRange.setRange(xMin, xMax);
0182 
0183             SET_NUMBER_LOCALE
0184             if (!m_dateTimeRange) {
0185                 ui.leEvalMin->setText(numberLocale.toString(xMin));
0186                 ui.leEvalMax->setText(numberLocale.toString(xMax));
0187             } else {
0188                 ui.dateTimeEditEvalMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xMin));
0189                 ui.dateTimeEditEvalMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xMax));
0190             }
0191         }
0192     }
0193 }
0194 
0195 void FitOptionsWidget::fitRangeMinChanged() {
0196     SET_DOUBLE_FROM_LE(m_fitData->fitRange.min(), ui.leMin);
0197     changed();
0198 }
0199 void FitOptionsWidget::fitRangeMaxChanged() {
0200     SET_DOUBLE_FROM_LE(m_fitData->fitRange.max(), ui.leMax);
0201     changed();
0202 }
0203 
0204 void FitOptionsWidget::fitRangeMinDateTimeChanged(const QDateTime& dateTime) {
0205     m_fitData->fitRange.setMin(dateTime.toMSecsSinceEpoch());
0206     changed();
0207 }
0208 
0209 void FitOptionsWidget::fitRangeMaxDateTimeChanged(const QDateTime& dateTime) {
0210     m_fitData->fitRange.setMax(dateTime.toMSecsSinceEpoch());
0211     changed();
0212 }
0213 
0214 void FitOptionsWidget::evalRangeMinChanged() {
0215     SET_DOUBLE_FROM_LE(m_fitData->evalRange.min(), ui.leEvalMin);
0216     changed();
0217 }
0218 void FitOptionsWidget::evalRangeMaxChanged() {
0219     SET_DOUBLE_FROM_LE(m_fitData->evalRange.max(), ui.leEvalMax);
0220     changed();
0221 }
0222 
0223 void FitOptionsWidget::evalRangeMinDateTimeChanged(const QDateTime& dateTime) {
0224     m_fitData->evalRange.setMin(dateTime.toMSecsSinceEpoch());
0225     changed();
0226 }
0227 
0228 void FitOptionsWidget::evalRangeMaxDateTimeChanged(const QDateTime& dateTime) {
0229     m_fitData->evalRange.setMax(dateTime.toMSecsSinceEpoch());
0230     changed();
0231 }
0232 
0233 void FitOptionsWidget::applyClicked() {
0234     SET_INT_FROM_LE(m_fitData->maxIterations, ui.leMaxIterations);
0235     SET_DOUBLE_FROM_LE(m_fitData->eps, ui.leEps);
0236     SET_INT_FROM_LE(m_fitData->evaluatedPoints, ui.leEvaluatedPoints);
0237 
0238     m_fitData->useDataErrors = ui.cbUseDataErrors->isChecked();
0239     m_fitData->useResults = ui.cbUseResults->isChecked();
0240     m_fitData->previewEnabled = ui.cbPreview->isChecked();
0241     m_fitData->confidenceInterval = ui.sbConfidenceInterval->value();
0242 
0243     if (m_changed)
0244         emit optionsChanged();
0245 
0246     emit finished();
0247 }
0248 
0249 void FitOptionsWidget::changed() {
0250     m_changed = true;
0251 }