12#include <QApplication>
23void FittingStatistics::calculateCurveFit (
int orderReduced,
26 int significantDigits)
30 if (0 <= orderReduced) {
36 int orderReducedFurther = orderReduced;
37 while (!calculateCurveFitReducedFurther (orderReducedFurther,
43 --orderReducedFurther;
44 if (orderReducedFurther < 0) {
54 if (order < a.size ()) {
57 coefficients [order] = a [order];
58 fittingCurveCoef.append (a [order]);
60 }
else if (order < coefficients.size ()) {
63 coefficients [order] = 0;
69bool FittingStatistics::calculateCurveFitReducedFurther (
int orderReducedFurther,
71 int significantDigits,
72 QVector<double> &a)
const
75 Matrix X (pointsConvenient.size (), orderReducedFurther + 1);
76 QVector<double> Y (pointsConvenient.size ());
77 loadXAndYArrays (orderReducedFurther,
85 Matrix denominator = X.transpose () * X;
89 Matrix inv = denominator.
inverse (significantDigits,
95 << orderReducedFurther;
101 Matrix expectedIdentity = denominator * inv;
103 LOG4CPP_DEBUG_S ((*
mainCat)) <<
"FittingStatistics::calculateCurveFitReducedFurther succeeded with order="
104 << orderReducedFurther
105 <<
" expectedIdentity="
106 << expectedIdentity.
toString ().toLatin1().data ();
117 int significantDigits)
120 qApp->setOverrideCursor (Qt::WaitCursor);
125 int orderReduced = qMin (qFloor (order),
126 pointsConvenient.size() - 1);
128 calculateCurveFit (orderReduced,
132 calculateStatistics (pointsConvenient,
138 qApp->restoreOverrideCursor();
149 FittingPointsConvenient::const_iterator itrC;
150 for (itrC = pointsConvenient.begin (); itrC != pointsConvenient.end (); itrC++) {
152 const QPointF &pointC = *itrC;
155 double yAverage = ySum / pointsConvenient.length();
162 if (pointsConvenient.count() > 0) {
164 double mseSum = 0, rSquaredNumerator = 0, rSquaredDenominator = 0;
165 for (itrC = pointsConvenient.begin(); itrC != pointsConvenient.end (); itrC++) {
167 const QPointF &pointC = *itrC;
168 double yActual = pointC.y();
169 double yCurveFit = yFromXAndCoefficients (coefficients,
172 mseSum += (yCurveFit - yActual ) * (yCurveFit - yActual );
173 rSquaredNumerator += (yCurveFit - yAverage) * (yCurveFit - yAverage);
174 rSquaredDenominator += (yActual - yAverage) * (yActual - yAverage);
177 mse = mseSum / pointsConvenient.count ();
179 rSquared = (rSquaredDenominator > 0 ?
180 rSquaredNumerator / rSquaredDenominator :
185void FittingStatistics::loadXAndYArrays (
int orderReduced,
188 QVector<double> &Y)
const
194 FittingPointsConvenient::const_iterator itr;
195 for (row = 0, itr = pointsConvenient.begin(); itr != pointsConvenient.end(); itr++, row++) {
197 const QPointF &p = *itr;
201 for (
int order = 0; order <= orderReduced; order++) {
203 X.
set (row, order, qPow (x, order));
217 if (order < coefficients.size ()) {
218 coef = coefficients [order];
220 sum += coef * qPow (x,
double (order));
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT.
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
log4cpp::Category * mainCat
MatrixConsistent
Indicates if matrix is consistent (i.e. has at least one solution)
FittingStatistics()
Single constructor.
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.
virtual ~FittingStatistics()
Matrix class that supports arbitrary NxN size.
double determinant() const
Return the determinant of this matrix.
int rows() const
Height of matrix.
Matrix inverse(int significantDigits, MatrixConsistent &matrixConsistent) const
Return the inverse of this matrix.
void set(int row, int col, double value)
Set (row, col) element.
Matrix transpose() const
Return the transpose of the current matrix.
QString toString() const
Dump matrix to a string.
#define LOG4CPP_DEBUG_S(logger)