00001 #include "ParabolaFit.h"
00002 #include <iostream>
00003 using namespace std;
00004 template <class T> T sqr( T t) {return t*t;}
00005
00006 void ParabolaFit::addPoint(double x, double y)
00007 {
00008 hasWeights = false;
00009 addPoint(x,y,1.);
00010 }
00011
00012 void ParabolaFit::addPoint(double x, double y, double w)
00013 {
00014 hasValues = false;
00015 hasErrors = false;
00016 Point p = {x,y,w};
00017 points.push_back(p);
00018 }
00019
00020 const ParabolaFit::Result & ParabolaFit::result( bool doErrors ) const
00021 {
00022 if (hasErrors) return theResult;
00023 if (hasValues && !doErrors) return theResult;
00024
00025 double F0, F1, F2, F3, F4, F0y, F1y, F2y;
00026 F0 = F1 = F2 = F3 = F4 = F0y = F1y = F2y = 0.;
00027
00028 typedef vector<Point>::const_iterator IT;
00029 for (IT ip = points.begin(); ip != points.end(); ip++) {
00030
00031 double pow;
00032 double x = ip->x;
00033 double y = ip->y;
00034 double w = ip->w;
00035
00036 F0 += w; F0y += w*y;
00037 F1 += w*x; F1y += w*x*y;
00038 pow = x*x; F2 += w*pow; F2y += w*pow*y;
00039 pow *= x; F3 += w*pow;
00040 pow *= x; F4 += w*pow;
00041 }
00042
00043 Column cA = { F0, F1, F2 };
00044 Column cB = { F1, F2, F3 };
00045 Column cC = { F2, F3, F4 };
00046 Column cY = { F0y, F1y, F2y };
00047
00048 double det0 = det(cA, cB, cC);
00049
00050 if ( !hasFixedParC) {
00051 theResult.parA = det(cY, cB, cC) / det0;
00052 theResult.parB = det(cA, cY, cC) / det0;
00053 theResult.parC = det(cA, cB, cY) / det0;
00054 } else {
00055 Column cCY = {F0y-theResult.parC*F2, F1y-theResult.parC*F3, F2y-theResult.parC*F4};
00056 double det0C = det(cA, cB);
00057 theResult.parA = det(cCY, cB) / det0C;
00058 theResult.parB = det(cA, cCY) / det0C;
00059 }
00060
00061
00062 double vAA, vBB, vCC, vAB, vAC, vBC;
00063 vAA = vBB = vCC = vAB = vAC = vBC = 0.;
00064
00065 hasValues = true;
00066 if (!doErrors) return theResult;
00067
00068 if( !hasWeights && dof() > 0) {
00069
00070 double scale_w = 1./chi2()/dof();
00071 for (IT ip = points.begin(); ip != points.end(); ip++) ip->w *= scale_w;
00072
00073 }
00074
00075 for (IT ip = points.begin(); ip != points.end(); ip++) {
00076
00077 double w = ip->w;
00078 Column cX = {1., ip->x, sqr(ip->x) };
00079
00080 double dXBC = det(cX, cB, cC);
00081 double dAXC = det(cA, cX, cC);
00082 double dABX = det(cA, cB, cX);
00083
00084 vAA += w * sqr(dXBC);
00085 vBB += w * sqr(dAXC);
00086 vCC += w * sqr(dABX);
00087 vAB += w * dXBC * dAXC;
00088 vAC += w * dXBC * dABX;
00089 vBC += w * dAXC * dABX;
00090 }
00091
00092 theResult.varAA = vAA/sqr(det0);
00093 theResult.varBB = vBB/sqr(det0);
00094 theResult.varCC = vCC/sqr(det0);
00095 theResult.varAB = vAB/sqr(det0);
00096 theResult.varAC = vAC/sqr(det0);
00097 theResult.varBC = vBC/sqr(det0);
00098
00099 hasErrors = true;
00100 return theResult;
00101 }
00102
00103
00104 double ParabolaFit::chi2() const
00105 {
00106 double mychi2 = 0.;
00107 for ( vector<Point>::const_iterator
00108 ip = points.begin(); ip != points.end(); ip++) {
00109 mychi2 += ip->w * sqr(ip->y - fun(ip->x));
00110 }
00111 return mychi2;
00112 }
00113
00114 double ParabolaFit::fun(double x) const
00115 {
00116 return theResult.parA + theResult.parB*x + theResult.parC*x*x;
00117 }
00118
00119 int ParabolaFit::dof() const
00120 {
00121 int nPar = 3; if (hasFixedParC) nPar--;
00122 int nDof = points.size() - nPar;
00123 return (nDof > 0) ? nDof : 0;
00124 }
00125
00126 double ParabolaFit::det(
00127 const Column & c1, const Column & c2, const Column & c3) const
00128 {
00129 return c1.r1 * c2.r2 * c3.r3
00130 + c2.r1 * c3.r2 * c1.r3
00131 + c3.r1 * c1.r2 * c2.r3
00132 - c1.r3 * c2.r2 * c3.r1
00133 - c2.r3 * c3.r2 * c1.r1
00134 - c3.r3 * c1.r2 * c2.r1;
00135 }
00136
00137 double ParabolaFit::det( const Column & c1, const Column & c2) const
00138 {
00139 return c1.r1*c2.r2 - c1.r2*c2.r1;
00140 }