FitOptionsWidget.cpp 10.6 KB
Newer Older
1 2 3 4
/***************************************************************************
    File                 : FitOptionsWidget.cc
    Project              : LabPlot
    Description          : widget for editing advanced fit options
5
    --------------------------------------------------------------------
6
    Copyright            : (C) 2014-2020 Alexander Semke (alexander.semke@web.de)
7
    Copyright            : (C) 2017-2018 Stefan Gerlach (stefan.gerlach@uni.kn)
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  This program is free software; you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation; either version 2 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/
#include "FitOptionsWidget.h"
30
#include "backend/worksheet/plots/cartesian/CartesianPlot.h"
31 32 33 34 35 36 37

/*!
	\class FitOptionsWidget
	\brief Widget for editing advanced fit options.

	\ingroup kdefrontend
 */
38
FitOptionsWidget::FitOptionsWidget(QWidget* parent, XYFitCurve::FitData* fitData, XYFitCurve* fitCurve) : QWidget(parent),
39
	m_fitData(fitData), m_fitCurve(fitCurve) {
40
	ui.setupUi(this);
Garvit Khatri's avatar
Garvit Khatri committed
41 42
	ui.pbApply->setIcon(QIcon::fromTheme("dialog-ok-apply"));
	ui.pbCancel->setIcon(QIcon::fromTheme("dialog-cancel"));
43 44 45 46 47 48

	//TODO: show "robust" option when robust fitting is possible
// 	ui.cbRobust->addItem(i18n("on"));
// 	ui.cbRobust->addItem(i18n("off"));
	ui.lRobust->setVisible(false);
	ui.cbRobust->setVisible(false);
49

Alexander Semke's avatar
Alexander Semke committed
50 51
	ui.leEps->setValidator( new QDoubleValidator(ui.leEps) );
	ui.leMaxIterations->setValidator( new QIntValidator(ui.leMaxIterations) );
52
	ui.leEvaluatedPoints->setValidator( new QIntValidator(ui.leEvaluatedPoints) );
Alexander Semke's avatar
Alexander Semke committed
53

54 55
	ui.leEps->setText(QString::number(m_fitData->eps));
	ui.leMaxIterations->setText(QString::number(m_fitData->maxIterations));
56
	ui.leEvaluatedPoints->setText(QString::number(m_fitData->evaluatedPoints));
57 58 59

	//range widgets
	const auto* plot = static_cast<const CartesianPlot*>(fitCurve->parentAspect());
Stefan Gerlach's avatar
Stefan Gerlach committed
60
	m_dateTimeRange = (plot->xRangeFormat() != CartesianPlot::RangeFormat::Numeric);
61
	if (!m_dateTimeRange) {
Stefan Gerlach's avatar
Stefan Gerlach committed
62 63 64 65
		ui.leMin->setText(QString::number(m_fitData->fitRange.min()));
		ui.leMax->setText(QString::number(m_fitData->fitRange.max()));
		ui.leEvalMin->setText(QString::number(m_fitData->evalRange.min()));
		ui.leEvalMax->setText(QString::number(m_fitData->evalRange.max()));
66
	} else {
Stefan Gerlach's avatar
Stefan Gerlach committed
67 68 69 70
		ui.dateTimeEditMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->fitRange.min()) );
		ui.dateTimeEditMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->fitRange.max()) );
		ui.dateTimeEditEvalMin->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->evalRange.min()) );
		ui.dateTimeEditEvalMax->setDateTime( QDateTime::fromMSecsSinceEpoch(m_fitData->evalRange.max()) );
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
	}

	ui.leMin->setVisible(!m_dateTimeRange);
	ui.leMax->setVisible(!m_dateTimeRange);
	ui.lXRange->setVisible(!m_dateTimeRange);
	ui.leEvalMin->setVisible(!m_dateTimeRange);
	ui.leEvalMax->setVisible(!m_dateTimeRange);
	ui.lEvalRange->setVisible(!m_dateTimeRange);
	ui.dateTimeEditMin->setVisible(m_dateTimeRange);
	ui.dateTimeEditMax->setVisible(m_dateTimeRange);
	ui.lXRangeDateTime->setVisible(m_dateTimeRange);
	ui.dateTimeEditEvalMin->setVisible(m_dateTimeRange);
	ui.dateTimeEditEvalMax->setVisible(m_dateTimeRange);
	ui.lEvalRangeDateTime->setVisible(m_dateTimeRange);

	//auto range
87
	ui.cbAutoRange->setChecked(m_fitData->autoRange);
Stefan Gerlach's avatar
Stefan Gerlach committed
88
	ui.cbAutoEvalRange->setChecked(m_fitData->autoEvalRange);
89
	this->autoRangeChanged();
Stefan Gerlach's avatar
Stefan Gerlach committed
90
	this->autoEvalRangeChanged();
91

92
	ui.cbUseDataErrors->setChecked(m_fitData->useDataErrors);
93
	ui.cbUseResults->setChecked(m_fitData->useResults);
94
	ui.cbPreview->setChecked(m_fitData->previewEnabled);
95
	ui.sbConfidenceInterval->setValue(m_fitData->confidenceInterval);
96 97

	//SLOTS
98
	connect(ui.leEps, &QLineEdit::textChanged, this, &FitOptionsWidget::changed);
99
	connect(ui.leMaxIterations, &QLineEdit::textChanged, this, &FitOptionsWidget::changed);
100 101 102 103
	connect(ui.leEvaluatedPoints, &QLineEdit::textChanged, this, &FitOptionsWidget::changed);
	connect(ui.cbUseDataErrors, &QCheckBox::clicked, this, &FitOptionsWidget::changed);
	connect(ui.cbUseResults, &QCheckBox::clicked, this, &FitOptionsWidget::changed);
	connect(ui.cbPreview, &QCheckBox::clicked, this, &FitOptionsWidget::changed);
104
	connect(ui.sbConfidenceInterval, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &FitOptionsWidget::changed);
105 106
	connect(ui.pbApply, &QPushButton::clicked, this, &FitOptionsWidget::applyClicked);
	connect(ui.pbCancel, &QPushButton::clicked, this, &FitOptionsWidget::finished);
107
	connect(ui.cbAutoRange, &QCheckBox::clicked, this, &FitOptionsWidget::autoRangeChanged);
108
	connect(ui.cbAutoEvalRange, &QCheckBox::clicked, this, &FitOptionsWidget::autoEvalRangeChanged);
109 110
	connect(ui.leMin, &QLineEdit::textChanged, this, &FitOptionsWidget::fitRangeMinChanged);
	connect(ui.leMax, &QLineEdit::textChanged, this, &FitOptionsWidget::fitRangeMaxChanged);
111 112
	connect(ui.dateTimeEditMin, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::fitRangeMinDateTimeChanged);
	connect(ui.dateTimeEditMax, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::fitRangeMaxDateTimeChanged);
113 114
	connect(ui.leEvalMin, &QLineEdit::textChanged, this, &FitOptionsWidget::evalRangeMinChanged);
	connect(ui.leEvalMax, &QLineEdit::textChanged, this, &FitOptionsWidget::evalRangeMaxChanged);
115 116
	connect(ui.dateTimeEditEvalMin, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::evalRangeMinDateTimeChanged);
	connect(ui.dateTimeEditEvalMax, &QDateTimeEdit::dateTimeChanged, this, &FitOptionsWidget::evalRangeMaxDateTimeChanged);
117 118
}

119 120 121 122
void FitOptionsWidget::autoRangeChanged() {
	const bool autoRange = ui.cbAutoRange->isChecked();
	m_fitData->autoRange = autoRange;

123 124 125 126 127 128
	ui.leMin->setEnabled(!autoRange);
	ui.lXRange->setEnabled(!autoRange);
	ui.leMax->setEnabled(!autoRange);
	ui.dateTimeEditMin->setEnabled(!autoRange);
	ui.lXRange->setEnabled(!autoRange);
	ui.dateTimeEditMax->setEnabled(!autoRange);
129

130
	if (autoRange) {
131
		const AbstractColumn* xDataColumn = nullptr;
Stefan Gerlach's avatar
Stefan Gerlach committed
132
		if (m_fitCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet)
133 134 135 136 137 138 139
			xDataColumn = m_fitCurve->xDataColumn();
		else {
			if (m_fitCurve->dataSourceCurve())
				xDataColumn = m_fitCurve->dataSourceCurve()->xColumn();
		}

		if (xDataColumn) {
140 141
			const double xMin = xDataColumn->minimum();
			const double xMax = xDataColumn->maximum();
142
			m_fitData->fitRange.setRange(xMin, xMax);
143 144 145 146 147 148 149 150

			if (!m_dateTimeRange) {
				ui.leMin->setText(QString::number(xMin));
				ui.leMax->setText(QString::number(xMax));
			} else {
				ui.dateTimeEditMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xMin));
				ui.dateTimeEditMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xMax));
			}
151 152
		}
	}
153
}
154 155 156 157 158

void FitOptionsWidget::autoEvalRangeChanged() {
	const bool autoRange = ui.cbAutoEvalRange->isChecked();
	m_fitData->autoEvalRange = autoRange;

159 160 161 162 163 164
	ui.leEvalMin->setEnabled(!autoRange);
	ui.lEvalRange->setEnabled(!autoRange);
	ui.leEvalMax->setEnabled(!autoRange);
	ui.dateTimeEditEvalMin->setEnabled(!autoRange);
	ui.lEvalRange->setEnabled(!autoRange);
	ui.dateTimeEditEvalMax->setEnabled(!autoRange);
165

166
	if (autoRange) {
167
		const AbstractColumn* xDataColumn = nullptr;
Stefan Gerlach's avatar
Stefan Gerlach committed
168
		if (m_fitCurve->dataSourceType() == XYAnalysisCurve::DataSourceType::Spreadsheet)
169 170 171 172 173 174 175
			xDataColumn = m_fitCurve->xDataColumn();
		else {
			if (m_fitCurve->dataSourceCurve())
				xDataColumn = m_fitCurve->dataSourceCurve()->xColumn();
		}

		if (xDataColumn) {
176 177
			const double xMin = xDataColumn->minimum();
			const double xMax = xDataColumn->maximum();
178
			m_fitData->evalRange.setRange(xMin, xMax);
179 180 181 182 183 184 185 186

			if (!m_dateTimeRange) {
				ui.leEvalMin->setText(QString::number(xMin));
				ui.leEvalMax->setText(QString::number(xMax));
			} else {
				ui.dateTimeEditEvalMin->setDateTime(QDateTime::fromMSecsSinceEpoch(xMin));
				ui.dateTimeEditEvalMax->setDateTime(QDateTime::fromMSecsSinceEpoch(xMax));
			}
187 188 189 190
		}
	}
}

191
void FitOptionsWidget::fitRangeMinChanged() {
192
	const double xMin = ui.leMin->text().toDouble();
193

Stefan Gerlach's avatar
Stefan Gerlach committed
194
	m_fitData->fitRange.setMin(xMin);
195 196
	changed();
}
197
void FitOptionsWidget::fitRangeMaxChanged() {
198
	const double xMax = ui.leMax->text().toDouble();
199

Stefan Gerlach's avatar
Stefan Gerlach committed
200
	m_fitData->fitRange.setMax(xMax);
201 202 203
	changed();
}

204
void FitOptionsWidget::fitRangeMinDateTimeChanged(const QDateTime& dateTime) {
Stefan Gerlach's avatar
Stefan Gerlach committed
205
	m_fitData->fitRange.setMin(dateTime.toMSecsSinceEpoch());
206 207 208 209
	changed();
}

void FitOptionsWidget::fitRangeMaxDateTimeChanged(const QDateTime& dateTime) {
Stefan Gerlach's avatar
Stefan Gerlach committed
210
	m_fitData->fitRange.setMax(dateTime.toMSecsSinceEpoch());
211 212 213
	changed();
}

214
void FitOptionsWidget::evalRangeMinChanged() {
215
	const double xMin = ui.leEvalMin->text().toDouble();
216

Stefan Gerlach's avatar
Stefan Gerlach committed
217
	m_fitData->evalRange.setMin(xMin);
218 219 220
	changed();
}
void FitOptionsWidget::evalRangeMaxChanged() {
221
	const double xMax = ui.leEvalMax->text().toDouble();
222

Stefan Gerlach's avatar
Stefan Gerlach committed
223
	m_fitData->evalRange.setMax(xMax);
224 225
	changed();
}
226

227
void FitOptionsWidget::evalRangeMinDateTimeChanged(const QDateTime& dateTime) {
Stefan Gerlach's avatar
Stefan Gerlach committed
228
	m_fitData->evalRange.setMin(dateTime.toMSecsSinceEpoch());
229 230 231 232
	changed();
}

void FitOptionsWidget::evalRangeMaxDateTimeChanged(const QDateTime& dateTime) {
Stefan Gerlach's avatar
Stefan Gerlach committed
233
	m_fitData->evalRange.setMax(dateTime.toMSecsSinceEpoch());
234 235 236
	changed();
}

237
void FitOptionsWidget::applyClicked() {
Stefan Gerlach's avatar
Stefan Gerlach committed
238 239
	m_fitData->maxIterations = ui.leMaxIterations->text().toFloat();	//TODO: float?
	m_fitData->eps = ui.leEps->text().toFloat();	// TODO: float?
240
	m_fitData->evaluatedPoints = ui.leEvaluatedPoints->text().toInt();
241
	m_fitData->useDataErrors = ui.cbUseDataErrors->isChecked();
242
	m_fitData->useResults = ui.cbUseResults->isChecked();
243
	m_fitData->previewEnabled = ui.cbPreview->isChecked();
244
	m_fitData->confidenceInterval = ui.sbConfidenceInterval->value();
Alexander Semke's avatar
Fixes.  
Alexander Semke committed
245 246

	if (m_changed)
247
		emit optionsChanged();
Alexander Semke's avatar
Fixes.  
Alexander Semke committed
248

249
	emit finished();
250
}
Alexander Semke's avatar
Fixes.  
Alexander Semke committed
251 252 253 254

void FitOptionsWidget::changed() {
	m_changed = true;
}