#include <NCSpectrumInterpolator.h>
Inheritance diagram for NC::SpectrumInterpolatorFancy:

Protected Member Functions | |
| int | intintpow (int a, int b) const |
| Private utility function. Calculates a^b using integer arithmetic. | |
| double | doubleintpow (double a, int b) const |
| Private utility function. Calculates a^b where b is an integer. | |
| virtual TMatrixD | FindCoeffs (const std::vector< std::vector< double > > &xs, const std::vector< double > &x) const |
| Do the bulk of the work. | |
Consider a curve
fit to a set of
points
by a chi-squared statistic
where the weight accorded to any point varies with
.
Let
be a linear combination of some basis functions 
We want to solve for the
that gives the best fit ie
for all 
Naming the terms we have
and solving for
gives
The final result
can now be computed.
So the coefficients of all the
's (
) can be precomputed as they are functions only of
.
The calculation is general and works for multidimensional
. Because the final combination of the
's is linear and the coefficients can be precomputed we can operate directly over entire histograms.
The
functions are chosen to be one-term polynomials, making up the full
polynomial. So, we need to compute the full set of possible combinations of powers to raise things to so we know what terms are possible.
Where
is the input vector in D-dimensional space
and
is the matrix of powers. above, pows in the code.
The calculation of the coefficients is achieved in ISpectrumInterpolator::FindCoeffs.
is called basis,
is mat,
is vecPart,
is denom and
is pows.
The function chosen for
is 
This has the feature that
diverges whenever
is any of the
's
This is good in that it forces the fit function to go through that point by giving it infinite weight, but bad in that it causes divide-by-zeros. We detect when
is very close to an
and in that case construct the coefficient vector by hand so that it picks out the corresponding
.
Definition at line 183 of file NCSpectrumInterpolator.h.
|
||||||||||||
|
Private utility function. Calculates a^b where b is an integer.
Definition at line 124 of file NCSpectrumInterpolator.cxx. Referenced by FindCoeffs(). 00125 {
00126 double ret = 1;
00127 while(b--) ret *= a;
00128 return ret;
00129 }
|
|
||||||||||||
|
Do the bulk of the work.
Implements NC::ISpectrumInterpolator. Definition at line 321 of file NCSpectrumInterpolator.cxx. References doubleintpow(), intintpow(), and SQR(). 00322 {
00323 assert(xs[0].size() == x.size());
00324
00325 // 2 to fit a general quadratic, 1 to fit a general linear function, etc.
00326 const int fitOrder = 1;
00327
00328 // The dimensionality of the space we are interpolating in
00329 const int D = x.size();
00330
00331 // The size of the matrices, which is the number of coefficients we
00332 // need to determine, which is the number of different products of the
00333 // components of the x coordinate each raised to a power up to fitOrder
00334 const int K = intintpow(fitOrder+1, D);
00335
00336 assert(xs.size() >= (unsigned int)K);
00337
00338
00339 // What powers to raise the xs to for each row in the matrix
00340 vector<vector<int> > pows(K);
00341 for(int k = 0; k < K; ++k) pows[k] = vector<int>(xs.size());
00342
00343 // Calculate every combination of powers
00344 // This produces a matrix like |012012012012012012012012012|
00345 // (where k is the col number, |000111222000111222000111222|
00346 // and d the row number) |000000000111111111222222222|
00347 for(int k = 0; k < K; ++k)
00348 for(int d = 0; d < D; ++d)
00349 pows[k][d] = (k%intintpow(fitOrder+1, d+1))/intintpow(fitOrder+1, d);
00350
00351
00352 // Calculate the value of the different polynomial parts at x
00353 TMatrixD basis(1, K);
00354 for(int k = 0; k < K; ++k){
00355 double basisAdd = 1;
00356 for(int d = 0; d < D; ++d){
00357 basisAdd *= doubleintpow(x[d], pows[k][d]);
00358 }
00359 basis(0, k) = basisAdd;
00360 } // end for k
00361
00362
00363 // The number of data points we are fitting
00364 const int N = xs.size();
00365
00366 // How close is really close?
00367 const double eps = 1e-12;
00368 // If evaluating really close to a known point, just use that point
00369 // since when x-x_n -> 0 we get a divide-by-zero
00370 for(int n = 0; n < N; ++n){
00371 double dist = 0;
00372 for(int d = 0; d < D; ++d){
00373 dist += SQR(xs[n][d]-x[d]);
00374 }
00375 if(dist < eps){
00376 TMatrixD coeffs(1, N);
00377 coeffs(0, n) = 1;
00378 return coeffs;
00379 }
00380 } // end for n
00381
00382 TMatrixD mat(K, K);
00383
00384 TMatrixD vecPart(K, N);
00385
00386 // Loop over all the data points
00387 for(int n = 0; n < N; ++n){
00388 // The weight by which this point is discounted in the fit
00389 // denom=1 corresponds to the usual unweighted fit
00390 // TODO - only taking weight in one dimension
00391 double denom = 0;
00392 for(int d = 0; d < D; ++d) denom += SQR(x[d]-xs[n][d]);
00393
00394 // Loop over the rows in the vector
00395 for(int j = 0; j < K; ++j){
00396 double vecadd = 1/denom;
00397 for(int d = 0; d < D; ++d)
00398 vecadd *= doubleintpow(xs[n][d], pows[j][d]);
00399 vecPart(j, n) = vecadd;
00400 }
00401
00402 // Loop over the cells of the matrix
00403 for(int j = 0; j < K; ++j){
00404 for(int i = 0; i < K; ++i){
00405 double matadd = 1/denom;
00406 for(int d = 0; d < D; ++d){
00407 matadd *= doubleintpow(xs[n][d], pows[j][d]);
00408 matadd *= doubleintpow(xs[n][d], pows[i][d]);
00409 }
00410 mat(j, i) += matadd;
00411 } // end for i
00412 } // end for j
00413 } // end for n
00414 mat.Invert();
00415
00416 return basis*mat*vecPart;
00417 }
|
|
||||||||||||
|
Private utility function. Calculates a^b using integer arithmetic.
Definition at line 116 of file NCSpectrumInterpolator.cxx. Referenced by FindCoeffs(). 00117 {
00118 int ret = 1;
00119 while(b--) ret *= a;
00120 return ret;
00121 }
|
1.3.9.1