Engauge Digitizer 2
Loading...
Searching...
No Matches
TestFitting.cpp
Go to the documentation of this file.
1#include "FittingStatistics.h"
2#include "Logger.h"
3#include "MainWindow.h"
4#include <qmath.h>
5#include <QPointF>
6#include <QtTest/QtTest>
7#include "Test/TestFitting.h"
8
10
11using namespace std;
12
13const int NOMINAL_ORDER = 6;
15
17 QObject(parent)
18{
19}
20
21void TestFitting::cleanupTestCase ()
22{
23
24}
25
26bool TestFitting::generalFunctionTest (int order,
27 int numPoints) const
28{
29 int orderReduced = qMin (order, numPoints - 1);
30
31 const double EPSILON = 0.0001;
33 double mse, rms, rSquared;
35
36 // Overfitting or underfitting?
37 bool isOverfitting = (order >= numPoints - 1);
38
39 // Create the points according to y = 0 + 1 * (x + 1) (x + 2) ... (x + order), with y=0 for order=0
41 for (int iPoint = 0; iPoint < numPoints; iPoint++) {
42 double x = iPoint; // Pick arbitrary x values that are near the zeros
43 double y = 0;
44 if (orderReduced > 0) {
45 y = 1; // Multiply this by successive terms
46 for (int ord = 0; ord < orderReduced; ord++) {
47 y *= (x + ord + 1);
48 }
49 }
50
51 points.append (QPointF (x, y));
52 }
53
54 fitting.calculateCurveFitAndStatistics (order,
55 points,
57 mse,
58 rms,
61
62 bool success = true;
63
64 // Expected coefficients are hardcoded
66 switch (orderReduced)
67 {
68 case 0: // y=0
70 break;
71 case 1: // y=(x+1)
74 break;
75 case 2: // y=(x+1)(x+2)
79 break;
80 case 3: // y=(x+1)(x+2)(x+3)
82 coefficientsExpected [1] = 11;
83 coefficientsExpected [2] = 6;
84 coefficientsExpected [3] = 1;
85 break;
86 case 4: // y=(x+1)(x+2)(x+3)(x+4)
87 coefficientsExpected [0] = 24;
88 coefficientsExpected [1] = 50;
89 coefficientsExpected [2] = 35;
90 coefficientsExpected [3] = 10;
92 break;
93 }
94
95 for (int coef = 0; coef < order + 1; coef++) {
96 double coefGot = coefficientsGot [coef];
97
98 double coefExpected = 0;
99 if (coef <= orderReduced) {
101 }
102
103 success = (success && ((qAbs (coefGot - coefExpected) < EPSILON)));
104 }
105
106 if (isOverfitting) {
107 // Overfitting case should always have an error of zero
108 success = (success && ((qAbs (mse) < EPSILON)));
109 }
110
111 return success;
112}
113
114bool TestFitting::generalNonFunctionTest () const
115{
116 const double EPSILON = 0.0001;
118 double mse, rms, rSquared;
120
121 // Create the points according to y = 0 + 1 * (x + 1) (x + 2) ... (x + order), with y=0 for order=0
123 const double Y1 = 1, Y2 = 2;
124 points.append (QPointF (1, Y1));
125 points.append (QPointF (1, Y2));
126
127 fitting.calculateCurveFitAndStatistics (1,
128 points,
130 mse,
131 rms,
132 rSquared,
134
135 bool success = true;
136
137 // Expected coefficients are hardcoded
139 coefficientsExpected [0] = (Y1 + Y2) / 2.0;
140 coefficientsExpected [1] = 0;
141
142 for (int coef = 0; coef < 2; coef++) {
143 double coefGot = coefficientsGot [coef];
144
146
147 success = (success && ((qAbs (coefGot - coefExpected) < EPSILON)));
148 }
149
150 return success;
151}
152
153void TestFitting::initTestCase ()
154{
155 const bool NO_DROP_REGRESSION = false;
158 const bool NO_GNUPLOT_LOG_FILES = false;
159 const bool NO_REGRESSION_IMPORT = false;
160 const bool NO_RESET = false;
161 const bool NO_EXPORT_ONLY = false;
162 const bool NO_EXTRACT_IMAGE_ONLY = false;
164 const bool DEBUG_FLAG = false;
167
168 initializeLogging ("engauge_test",
169 "engauge_test.log",
170 DEBUG_FLAG);
171
177 NO_RESET,
183 w.show ();
184}
185
186int TestFitting::orderReducedVersusOrderAndSignificantDigits (int order,
187 int significantDigits) const
188{
191
192 // Hyperbola points
194 for (double x = 1; x <= 10; x += 1) {
195 double y = 100.0 / x;
196 points.append (QPointF (x, y));
197 }
198
199 fittingStatistics.calculateCurveFit (order,
200 points,
202 significantDigits);
203
204 // Find first nonzero coefficient. Two cases for 0th order are y<>0 (not all coefficients are zero)
205 // and y=0 (all coefficients are zero). In all other cases the order is the highest nonzero coefficient
206 int orderReduced;
208 if (coefficients [orderReduced] != 0) {
209 return orderReduced;
210 }
211 }
212
213 return orderReduced;
214}
215
216void TestFitting::testFunctionExactFit01 ()
217{
218 QVERIFY (generalFunctionTest (0, 1));
219}
220
221void TestFitting::testFunctionExactFit12 ()
222{
223 QVERIFY (generalFunctionTest (1, 2));
224}
225
226void TestFitting::testFunctionExactFit23 ()
227{
228 QVERIFY (generalFunctionTest (2, 3));
229}
230
231void TestFitting::testFunctionExactFit34 ()
232{
233 QVERIFY (generalFunctionTest (3, 4));
234}
235
236void TestFitting::testFunctionOverfit11 ()
237{
238 QVERIFY (generalFunctionTest (1, 1));
239}
240
241void TestFitting::testFunctionOverfit22 ()
242{
243 QVERIFY (generalFunctionTest (2, 2));
244}
245
246void TestFitting::testFunctionOverfit33 ()
247{
248 QVERIFY (generalFunctionTest (3, 3));
249}
250
251void TestFitting::testFunctionOverfit44 ()
252{
253 QVERIFY (generalFunctionTest (4, 4));
254}
255
256void TestFitting::testFunctionUnderfit02 ()
257{
258 QVERIFY (generalFunctionTest (0, 2));
259}
260
261void TestFitting::testFunctionUnderfit13 ()
262{
263 QVERIFY (generalFunctionTest (1, 3));
264}
265
266void TestFitting::testFunctionUnderfit24 ()
267{
268 QVERIFY (generalFunctionTest (2, 4));
269}
270
271void TestFitting::testFunctionUnderfit35 ()
272{
273 QVERIFY (generalFunctionTest (3, 5));
274}
275
276void TestFitting::testNonFunction ()
277{
278 QVERIFY (generalNonFunctionTest ());
279}
280
281void TestFitting::testOrderReduced3 ()
282{
283 QVERIFY (orderReducedVersusOrderAndSignificantDigits (3, NOMINAL_SIGNIFICANT_DIGITS) == 3);
284}
285
286void TestFitting::testOrderReduced4 ()
287{
288 QVERIFY (orderReducedVersusOrderAndSignificantDigits (4, NOMINAL_SIGNIFICANT_DIGITS) == 4);
289}
290
291void TestFitting::testOrderReduced5 ()
292{
293 QVERIFY (orderReducedVersusOrderAndSignificantDigits (5, NOMINAL_SIGNIFICANT_DIGITS) == 5);
294}
295
296void TestFitting::testOrderReduced6 ()
297{
298 QVERIFY (orderReducedVersusOrderAndSignificantDigits (6, NOMINAL_SIGNIFICANT_DIGITS) == 6);
299}
300
301void TestFitting::testSignificantDigits3 ()
302{
303 QVERIFY (orderReducedVersusOrderAndSignificantDigits (NOMINAL_ORDER, 3) == NOMINAL_ORDER);
304}
305
306void TestFitting::testSignificantDigits4 ()
307{
308 QVERIFY (orderReducedVersusOrderAndSignificantDigits (NOMINAL_ORDER, 4) == NOMINAL_ORDER);
309}
310
311void TestFitting::testSignificantDigits5 ()
312{
313 QVERIFY (orderReducedVersusOrderAndSignificantDigits (NOMINAL_ORDER, 5) == NOMINAL_ORDER);
314}
315
316void TestFitting::testSignificantDigits6 ()
317{
318 QVERIFY (orderReducedVersusOrderAndSignificantDigits (NOMINAL_ORDER, 6) == NOMINAL_ORDER);
319}
const int INNER_RADIUS_MIN
const double EPSILON
QVector< double > FittingCurveCoefficients
Coefficients x0, x1, ... in y = a0 + a1 * x + a2 * x^2 + ...
QList< QPointF > FittingPointsConvenient
Array of (x,y) points in graph coordinates.
const int MAX_POLYNOMIAL_ORDER
void initializeLogging(const QString &name, const QString &filename, bool isDebug)
Definition Logger.cpp:21
const bool NO_EXPORT_ONLY
const QStringList NO_COMMAND_LINE
const QString NO_EXTRACT_IMAGE_EXTENSION
const QString NO_ERROR_REPORT_LOG_FILE
const bool NO_GNUPLOT_LOG_FILES
const QString NO_REGRESSION_OPEN_FILE
const QStringList NO_LOAD_STARTUP_FILES
const bool NO_REGRESSION_IMPORT
const bool NO_EXTRACT_IMAGE_ONLY
const bool NO_DROP_REGRESSION
const bool DEBUG_FLAG
const int NOMINAL_SIGNIFICANT_DIGITS
const int NOMINAL_ORDER
This class does the math to compute statistics for FittingWindow.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition MainWindow.h:92
Unit test of Fitting classes.
Definition TestFitting.h:8
TestFitting(QObject *parent=0)
Single constructor.