Engauge Digitizer  2
 All Classes Functions Variables Typedefs Enumerations Friends Pages
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.
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