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 TestFitting::TestFitting(QObject *parent) :
14  QObject(parent)
15 {
16 }
17 
18 void TestFitting::cleanupTestCase ()
19 {
20 
21 }
22 
23 bool TestFitting::generalTest (int order,
24  int numPoints) const
25 {
26  int orderReduced = qMin (order, numPoints - 1);
27 
28  const double EPSILON = 0.0001;
29  FittingStatistics fitting;
30  double mse, rms, rSquared;
31  FittingCurveCoefficients coefficientsGot (MAX_POLYNOMIAL_ORDER + 1);
32 
33  // Overfitting or underfitting?
34  bool isOverfitting = (order >= numPoints - 1);
35 
36  // Create the points according to y = 0 + 1 * (x + 1) (x + 2) ... (x + order), with y=0 for order=0
37  FittingPointsConvenient points;
38  for (int iPoint = 0; iPoint < numPoints; iPoint++) {
39  double x = iPoint; // Pick arbitrary x values that are near the zeros
40  double y = 0;
41  if (orderReduced > 0) {
42  y = 1; // Multiply this by successive terms
43  for (int ord = 0; ord < orderReduced; ord++) {
44  y *= (x + ord + 1);
45  }
46  }
47 
48  points.append (QPointF (x, y));
49  }
50 
51  fitting.calculateCurveFitAndStatistics (order,
52  points,
53  coefficientsGot,
54  mse,
55  rms,
56  rSquared);
57 
58  bool success = true;
59 
60  // Expected coefficients are hardcoded
61  FittingCurveCoefficients coefficientsExpected (orderReduced + 1);
62  switch (orderReduced)
63  {
64  case 0: // y=0
65  coefficientsExpected [0] = 0;
66  break;
67  case 1: // y=(x+1)
68  coefficientsExpected [0] = 1;
69  coefficientsExpected [1] = 1;
70  break;
71  case 2: // y=(x+1)(x+2)
72  coefficientsExpected [0] = 2;
73  coefficientsExpected [1] = 3;
74  coefficientsExpected [2] = 1;
75  break;
76  case 3: // y=(x+1)(x+2)(x+3)
77  coefficientsExpected [0] = 6;
78  coefficientsExpected [1] = 11;
79  coefficientsExpected [2] = 6;
80  coefficientsExpected [3] = 1;
81  break;
82  case 4: // y=(x+1)(x+2)(x+3)(x+4)
83  coefficientsExpected [0] = 24;
84  coefficientsExpected [1] = 50;
85  coefficientsExpected [2] = 35;
86  coefficientsExpected [3] = 10;
87  coefficientsExpected [4] = 1;
88  break;
89  }
90 
91  for (int coef = 0; coef < order + 1; coef++) {
92  double coefGot = coefficientsGot [coef];
93 
94  double coefExpected = 0;
95  if (coef <= orderReduced) {
96  coefExpected = coefficientsExpected [coef];
97  }
98 
99  success = (success && ((qAbs (coefGot - coefExpected) < EPSILON)));
100  }
101 
102  if (isOverfitting) {
103  // Overfitting case should always have an error of zero
104  success = (success && ((qAbs (mse) < EPSILON)));
105  }
106 
107  return success;
108 }
109 
110 void TestFitting::initTestCase ()
111 {
112  const QString NO_ERROR_REPORT_LOG_FILE;
113  const QString NO_REGRESSION_OPEN_FILE;
114  const bool NO_GNUPLOT_LOG_FILES = false;
115  const bool NO_REGRESSION_IMPORT = false;
116  const bool NO_RESET = false;
117  const bool DEBUG_FLAG = false;
118  const QStringList NO_LOAD_STARTUP_FILES;
119 
120  initializeLogging ("engauge_test",
121  "engauge_test.log",
122  DEBUG_FLAG);
123 
124  MainWindow w (NO_ERROR_REPORT_LOG_FILE,
125  NO_REGRESSION_OPEN_FILE,
126  NO_GNUPLOT_LOG_FILES,
127  NO_REGRESSION_IMPORT,
128  NO_RESET,
129  NO_LOAD_STARTUP_FILES);
130  w.show ();
131 }
132 
133 void TestFitting::testExactFit01 ()
134 {
135  QVERIFY (generalTest (0, 1));
136 }
137 
138 void TestFitting::testExactFit12 ()
139 {
140  QVERIFY (generalTest (1, 2));
141 }
142 
143 void TestFitting::testExactFit23 ()
144 {
145  QVERIFY (generalTest (2, 3));
146 }
147 
148 void TestFitting::testExactFit34 ()
149 {
150  QVERIFY (generalTest (3, 4));
151 }
152 
153 void TestFitting::testOverfit11 ()
154 {
155  QVERIFY (generalTest (1, 1));
156 }
157 
158 void TestFitting::testOverfit22 ()
159 {
160  QVERIFY (generalTest (2, 2));
161 }
162 
163 void TestFitting::testOverfit33 ()
164 {
165  QVERIFY (generalTest (3, 3));
166 }
167 
168 void TestFitting::testOverfit44 ()
169 {
170  QVERIFY (generalTest (4, 4));
171 }
172 
173 void TestFitting::testUnderfit02 ()
174 {
175  QVERIFY (generalTest (0, 2));
176 }
177 
178 void TestFitting::testUnderfit13 ()
179 {
180  QVERIFY (generalTest (1, 3));
181 }
182 
183 void TestFitting::testUnderfit24 ()
184 {
185  QVERIFY (generalTest (2, 4));
186 }
187 
188 void TestFitting::testUnderfit35 ()
189 {
190  QVERIFY (generalTest (3, 5));
191 }
Unit test of Fitting classes.
Definition: TestFitting.h:7
TestFitting(QObject *parent=0)
Single constructor.
Definition: TestFitting.cpp:13
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
void calculateCurveFitAndStatistics(unsigned int order, const FittingPointsConvenient &pointsConvenient, FittingCurveCoefficients &coefficients, double &mse, double &rms, double &rSquared)
Compute the curve fit and the statistics for that curve fit.