Engauge Digitizer  2
TestFitting.cpp
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 
9 QTEST_MAIN (TestFitting)
10 
11 using namespace std;
12 
13 const int SIGNIFICANT_DIGITS = 7;
14 
15 TestFitting::TestFitting(QObject *parent) :
16  QObject(parent)
17 {
18 }
19 
20 void TestFitting::cleanupTestCase ()
21 {
22 
23 }
24 
25 bool TestFitting::generalFunctionTest (int order,
26  int numPoints) const
27 {
28  int orderReduced = qMin (order, numPoints - 1);
29 
30  const double EPSILON = 0.0001;
31  FittingStatistics fitting;
32  double mse, rms, rSquared;
33  FittingCurveCoefficients coefficientsGot (MAX_POLYNOMIAL_ORDER + 1);
34 
35  // Overfitting or underfitting?
36  bool isOverfitting = (order >= numPoints - 1);
37 
38  // Create the points according to y = 0 + 1 * (x + 1) (x + 2) ... (x + order), with y=0 for order=0
39  FittingPointsConvenient points;
40  for (int iPoint = 0; iPoint < numPoints; iPoint++) {
41  double x = iPoint; // Pick arbitrary x values that are near the zeros
42  double y = 0;
43  if (orderReduced > 0) {
44  y = 1; // Multiply this by successive terms
45  for (int ord = 0; ord < orderReduced; ord++) {
46  y *= (x + ord + 1);
47  }
48  }
49 
50  points.append (QPointF (x, y));
51  }
52 
53  fitting.calculateCurveFitAndStatistics (order,
54  points,
55  coefficientsGot,
56  mse,
57  rms,
58  rSquared,
59  SIGNIFICANT_DIGITS);
60 
61  bool success = true;
62 
63  // Expected coefficients are hardcoded
64  FittingCurveCoefficients coefficientsExpected (orderReduced + 1);
65  switch (orderReduced)
66  {
67  case 0: // y=0
68  coefficientsExpected [0] = 0;
69  break;
70  case 1: // y=(x+1)
71  coefficientsExpected [0] = 1;
72  coefficientsExpected [1] = 1;
73  break;
74  case 2: // y=(x+1)(x+2)
75  coefficientsExpected [0] = 2;
76  coefficientsExpected [1] = 3;
77  coefficientsExpected [2] = 1;
78  break;
79  case 3: // y=(x+1)(x+2)(x+3)
80  coefficientsExpected [0] = 6;
81  coefficientsExpected [1] = 11;
82  coefficientsExpected [2] = 6;
83  coefficientsExpected [3] = 1;
84  break;
85  case 4: // y=(x+1)(x+2)(x+3)(x+4)
86  coefficientsExpected [0] = 24;
87  coefficientsExpected [1] = 50;
88  coefficientsExpected [2] = 35;
89  coefficientsExpected [3] = 10;
90  coefficientsExpected [4] = 1;
91  break;
92  }
93 
94  for (int coef = 0; coef < order + 1; coef++) {
95  double coefGot = coefficientsGot [coef];
96 
97  double coefExpected = 0;
98  if (coef <= orderReduced) {
99  coefExpected = coefficientsExpected [coef];
100  }
101 
102  success = (success && ((qAbs (coefGot - coefExpected) < EPSILON)));
103  }
104 
105  if (isOverfitting) {
106  // Overfitting case should always have an error of zero
107  success = (success && ((qAbs (mse) < EPSILON)));
108  }
109 
110  return success;
111 }
112 
113 bool TestFitting::generalNonFunctionTest () const
114 {
115  const double EPSILON = 0.0001;
116  FittingStatistics fitting;
117  double mse, rms, rSquared;
118  FittingCurveCoefficients coefficientsGot (MAX_POLYNOMIAL_ORDER);
119 
120  // Create the points according to y = 0 + 1 * (x + 1) (x + 2) ... (x + order), with y=0 for order=0
121  FittingPointsConvenient points;
122  const double Y1 = 1, Y2 = 2;
123  points.append (QPointF (1, Y1));
124  points.append (QPointF (1, Y2));
125 
127  points,
128  coefficientsGot,
129  mse,
130  rms,
131  rSquared,
132  SIGNIFICANT_DIGITS);
133 
134  bool success = true;
135 
136  // Expected coefficients are hardcoded
137  FittingCurveCoefficients coefficientsExpected (2);
138  coefficientsExpected [0] = (Y1 + Y2) / 2.0;
139  coefficientsExpected [1] = 0;
140 
141  for (int coef = 0; coef < 2; coef++) {
142  double coefGot = coefficientsGot [coef];
143 
144  double coefExpected = coefficientsExpected [coef];
145 
146  success = (success && ((qAbs (coefGot - coefExpected) < EPSILON)));
147  }
148 
149  return success;
150 }
151 
152 void TestFitting::initTestCase ()
153 {
154  const QString NO_ERROR_REPORT_LOG_FILE;
155  const QString NO_REGRESSION_OPEN_FILE;
156  const bool NO_GNUPLOT_LOG_FILES = false;
157  const bool NO_REGRESSION_IMPORT = false;
158  const bool NO_RESET = false;
159  const bool NO_EXPORT_ONLY = false;
160  const bool DEBUG_FLAG = false;
161  const QStringList NO_LOAD_STARTUP_FILES;
162 
163  initializeLogging ("engauge_test",
164  "engauge_test.log",
165  DEBUG_FLAG);
166 
167  MainWindow w (NO_ERROR_REPORT_LOG_FILE,
168  NO_REGRESSION_OPEN_FILE,
169  NO_REGRESSION_IMPORT,
170  NO_GNUPLOT_LOG_FILES,
171  NO_RESET,
172  NO_EXPORT_ONLY,
173  NO_LOAD_STARTUP_FILES);
174  w.show ();
175 }
176 
177 void TestFitting::testFunctionExactFit01 ()
178 {
179  QVERIFY (generalFunctionTest (0, 1));
180 }
181 
182 void TestFitting::testFunctionExactFit12 ()
183 {
184  QVERIFY (generalFunctionTest (1, 2));
185 }
186 
187 void TestFitting::testFunctionExactFit23 ()
188 {
189  QVERIFY (generalFunctionTest (2, 3));
190 }
191 
192 void TestFitting::testFunctionExactFit34 ()
193 {
194  QVERIFY (generalFunctionTest (3, 4));
195 }
196 
197 void TestFitting::testFunctionOverfit11 ()
198 {
199  QVERIFY (generalFunctionTest (1, 1));
200 }
201 
202 void TestFitting::testFunctionOverfit22 ()
203 {
204  QVERIFY (generalFunctionTest (2, 2));
205 }
206 
207 void TestFitting::testFunctionOverfit33 ()
208 {
209  QVERIFY (generalFunctionTest (3, 3));
210 }
211 
212 void TestFitting::testFunctionOverfit44 ()
213 {
214  QVERIFY (generalFunctionTest (4, 4));
215 }
216 
217 void TestFitting::testFunctionUnderfit02 ()
218 {
219  QVERIFY (generalFunctionTest (0, 2));
220 }
221 
222 void TestFitting::testFunctionUnderfit13 ()
223 {
224  QVERIFY (generalFunctionTest (1, 3));
225 }
226 
227 void TestFitting::testFunctionUnderfit24 ()
228 {
229  QVERIFY (generalFunctionTest (2, 4));
230 }
231 
232 void TestFitting::testFunctionUnderfit35 ()
233 {
234  QVERIFY (generalFunctionTest (3, 5));
235 }
236 
237 void TestFitting::testNonFunction ()
238 {
239  QVERIFY (generalNonFunctionTest ());
240 }
Unit test of Fitting classes.
Definition: TestFitting.h:7
void calculateCurveFitAndStatistics(unsigned int order, const FittingPointsConvenient &pointsConvenient, FittingCurveCoefficients &coefficients, double &mse, double &rms, double &rSquared, int significantDigits)
Compute the curve fit and the statistics for that curve fit.
TestFitting(QObject *parent=0)
Single constructor.
Definition: TestFitting.cpp:15
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:89