1 /***************************************************************************
2     File                 : PolynomFitDialog.cpp
3     Project              : QtiPlot
4     --------------------------------------------------------------------
5 	Copyright            : (C) 2006 - 2011 by Ion Vasilief
6     Email (use @ for *)  : ion_vasilief*yahoo.fr
7     Description          : Fit polynomial dialog
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *  This program is free software; you can redistribute it and/or modify   *
14  *  it under the terms of the GNU General Public License as published by   *
15  *  the Free Software Foundation; either version 2 of the License, or      *
16  *  (at your option) any later version.                                    *
17  *                                                                         *
18  *  This program is distributed in the hope that it will be useful,        *
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
21  *  GNU General Public License for more details.                           *
22  *                                                                         *
23  *   You should have received a copy of the GNU General Public License     *
24  *   along with this program; if not, write to the Free Software           *
25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
26  *   Boston, MA  02110-1301  USA                                           *
27  *                                                                         *
28  ***************************************************************************/
29 #include "PolynomFitDialog.h"
30 #include <PolynomialFit.h>
31 #include <Graph.h>
32 #include <ApplicationWindow.h>
33 #include <DoubleSpinBox.h>
34 #include <ColorButton.h>
35 #include <RangeSelectorTool.h>
36 
37 #include <QSpinBox>
38 #include <QCheckBox>
39 #include <QMessageBox>
40 #include <QLayout>
41 #include <QGroupBox>
42 #include <QPushButton>
43 #include <QLabel>
44 #include <QComboBox>
45 
46 PolynomFitDialog::PolynomFitDialog( QWidget* parent, Qt::WFlags fl )
47 : QDialog( parent, fl )
48 {
49     setObjectName( "PolynomFitDialog" );
50 	setWindowTitle(tr("QtiPlot - Polynomial Fit Options"));
51 	setAttribute(Qt::WA_DeleteOnClose);
52     setSizeGripEnabled( true );
53 
54     QGroupBox *gb1 = new QGroupBox();
55 	QGridLayout *gl1 = new QGridLayout(gb1);
56 	gl1->addWidget(new QLabel(tr("Polynomial Fit of")), 0, 0);
57 
58 	boxName = new QComboBox();
59     gl1->addWidget(boxName, 0, 1);
60 
61     gl1->addWidget(new QLabel( tr("Order (1 - 9, 1 = linear)")), 1, 0);
62 	boxOrder = new QSpinBox();
63     boxOrder->setRange(1, 9);
64 	boxOrder->setValue(2);
65     gl1->addWidget(boxOrder, 1, 1);
66 
67     gl1->addWidget(new QLabel( tr("Fit curve # pts")), 2, 0);
68 	boxPoints = new QSpinBox();
69     boxPoints->setRange(1, 1000);
70     boxPoints->setSingleStep(50);
71     boxPoints->setSpecialValueText(tr("Not enough points"));
72     gl1->addWidget(boxPoints, 2, 1);
73 
74 	ApplicationWindow *app = (ApplicationWindow *)parent;
75 
76     gl1->addWidget(new QLabel( tr("Fit curve Xmin")), 3, 0);
77 	boxStart = new DoubleSpinBox();
78 	boxStart->setDecimals(app->d_decimal_digits);
79 	boxStart->setLocale(app->locale());
80     gl1->addWidget(boxStart, 3, 1);
81 
82     gl1->addWidget(	new QLabel( tr("Fit curve Xmax")), 4, 0);
83 	boxEnd = new DoubleSpinBox();
84 	boxEnd->setDecimals(app->d_decimal_digits);
85 	boxEnd->setLocale(app->locale());
86     gl1->addWidget(boxEnd, 4, 1);
87 
88     gl1->addWidget(new QLabel( tr("Color")), 5, 0);
89 	boxColor = new ColorButton();
90 	boxColor->setColor(Qt::red);
91     gl1->addWidget(boxColor, 5, 1);
92 
93 	boxShowFormula = new QCheckBox(tr( "Show Formula on Graph?" ));
94 	boxShowFormula->setChecked( false );
95     gl1->addWidget(boxShowFormula, 6, 1);
96     gl1->setRowStretch(7, 1);
97 	gl1->setColumnStretch(1, 1);
98 
99 	buttonFit = new QPushButton(tr( "&Fit" ));
100 	buttonFit->setDefault( true );
101 
102 	buttonCancel = new QPushButton(tr( "&Close" ));
103 
104     QVBoxLayout* vl = new QVBoxLayout();
105     vl->addWidget(buttonFit);
106     vl->addWidget(buttonCancel);
107     vl->addStretch();
108 
109 	QHBoxLayout* hlayout = new QHBoxLayout(this);
110 	hlayout->addWidget(gb1, 1);
111 	hlayout->addLayout(vl);
112 
113 	connect( buttonFit, SIGNAL( clicked() ), this, SLOT( fit() ) );
114 	connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( close() ) );
115 	connect( boxName, SIGNAL( activated(const QString &) ), this, SLOT(activateCurve(const QString &)));
116 }
117 
118 void PolynomFitDialog::fit()
119 {
120 	QString curveName = boxName->currentText();
121 	QStringList curvesList = graph->analysableCurvesList();
122 	if (!curvesList.contains(curveName)){
123 		QMessageBox::critical(this, tr("QtiPlot - Warning"),
124 				tr("The curve <b> %1 </b> doesn't exist anymore! Operation aborted!").arg(curveName));
125 		boxName->clear();
126 		boxName->insertStringList(curvesList);
127 		return;
128 	}
129 
130 	curveName = curveName.left(curveName.indexOf(" ["));
131 
132 	ApplicationWindow *app = (ApplicationWindow *)this->parent();
133     PolynomialFit *fitter = new PolynomialFit(app, graph, boxOrder->value(), boxShowFormula->isChecked());
134 	if (fitter->setDataFromCurve((QwtPlotCurve *)graph->curve(curveName), boxStart->value(), boxEnd->value())){
135 		fitter->setColor(boxColor->color());
136         fitter->setOutputPrecision(app->fit_output_precision);
137 		fitter->generateFunction(app->generateUniformFitPoints, app->fitPoints);
138         fitter->fit();
139         delete fitter;
140 	}
141 }
142 
143 void PolynomFitDialog::setGraph(Graph *g)
144 {
145 	if (!g)
146 		return;
147 
148 	graph = g;
149 	boxName->addItems (g->analysableCurvesList());
150 
151 	if (g->rangeSelectorsEnabled())
152 		boxName->setCurrentIndex(boxName->findText(g->curveRange(g->rangeSelectorTool()->selectedCurve())));
153 
154 	activateCurve(boxName->currentText());
155 
156 	connect (graph, SIGNAL(destroyed()), this, SLOT(close()));
157 	connect (graph, SIGNAL(dataRangeChanged()), this, SLOT(changeDataRange()));
158 }
159 
160 void PolynomFitDialog::activateCurve(const QString& s)
161 {
162 	double start, end;
163 	int n_points = graph->range((QwtPlotCurve *)graph->curve(s.left(s.indexOf(" ["))), &start, &end);
164 
165 	boxStart->setValue(start);
166 	boxEnd->setValue(end);
167 	boxPoints->setValue(QMAX(n_points, 100));
168 }
169 
170 void PolynomFitDialog::changeDataRange()
171 {
172 	double start = graph->selectedXStartValue();
173 	double end = graph->selectedXEndValue();
174 	boxStart->setValue(QMIN(start, end));
175 	boxEnd->setValue(QMAX(start, end));
176 }
177