00001
00002
00003
00004
00005
00006
00007
00008
00010
00011 #include "NCSpectrumInterpolator.h"
00012
00013 #include "MessageService/MsgService.h"
00014
00015 #include "NCUtils/NCUtility.h"
00016 using namespace NC::Utility;
00017
00018 #include "TCanvas.h"
00019 #include "TH1.h"
00020 #include "TH2.h"
00021 #include "TH3.h"
00022 #include "TMath.h"
00023 #include "TMatrixD.h"
00024
00025 #include <cassert>
00026 #include <cmath>
00027
00028 CVSID("$Id: NCSpectrumInterpolator.cxx,v 1.18 2009/11/18 18:58:24 bckhouse Exp $");
00029
00030 using std::vector;
00031
00032 bool NC::ISpectrumInterpolator::ShiftInfo::IsNominal() const
00033 {
00034 for(unsigned int n = 0; n < shift.size(); ++n)
00035 if(shift[n] != 0) return false;
00036 return true;
00037 }
00038
00039
00040 NC::ISpectrumInterpolator::~ISpectrumInterpolator()
00041 {
00042 for(unsigned int n = 0; n < shifted.size(); ++n)
00043 for(unsigned int m = 0; m < shifted[n].spectra.size(); ++m)
00044 delete shifted[n].spectra[m];
00045 }
00046
00047
00048 void NC::ISpectrumInterpolator::AddInputSpectra(std::vector<double> shift,
00049 std::vector<TH1*> spectra)
00050 {
00051 for(unsigned int n = 0; n < shifted.size(); ++n){
00052 if(shifted[n].shift == shift){
00053 assert(0 && "We already added spectra at this shift");
00054
00055
00056
00057 }
00058 }
00059
00060
00061 shifted.push_back(ShiftInfo(shift, spectra));
00062 }
00063
00064
00065 vector<TH1*> NC::ISpectrumInterpolator::
00066 GetInputSpectra(vector<double> shift) const
00067 {
00068 vector<TH1*> ret;
00069
00070 for(unsigned int n = 0; n < shifted.size(); ++n){
00071 const ShiftInfo& sn = shifted[n];
00072 if(sn.shift == shift){
00073 ret.reserve(sn.spectra.size());
00074 for(unsigned int n = 0; n < sn.spectra.size(); ++n)
00075 ret.push_back(CloneFast(sn.spectra[n]));
00076 return ret;
00077 }
00078 }
00079
00080 return ret;
00081 }
00082
00083
00084 vector<TH1*> NC::ISpectrumInterpolator::
00085 InterpolateHists(const vector<ShiftInfo>& hs,
00086 const vector<double>& shift) const
00087 {
00088 assert(!hs.empty());
00089
00090 vector<vector<double> > xs;
00091 xs.reserve(hs.size());
00092 for(unsigned int n = 0; n < hs.size(); ++n) xs.push_back(hs[n].shift);
00093
00094 const TMatrixD coeffs = FindCoeffs(xs, shift);
00095
00096 const unsigned int I = hs[0].spectra.size();
00097 vector<TH1*> ret;
00098 ret.reserve(I);
00099 for(unsigned int i = 0; i < I; ++i){
00100
00101 TH1* h = CloneFast(hs[0].spectra[i]);
00102 h->Reset();
00103
00104 const unsigned int J = hs.size();
00105
00106 for(unsigned int j = 0; j < J; ++j)
00107 AddFast(h, hs[j].spectra[i], coeffs(0, j));
00108
00109 ret.push_back(h);
00110 }
00111
00112 return ret;
00113 }
00114
00115
00116 int NC::SpectrumInterpolatorFancy::intintpow(int a, int b) const
00117 {
00118 int ret = 1;
00119 while(b--) ret *= a;
00120 return ret;
00121 }
00122
00123
00124 double NC::SpectrumInterpolatorFancy::doubleintpow(double a, int b) const
00125 {
00126 double ret = 1;
00127 while(b--) ret *= a;
00128 return ret;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 void NC::ISpectrumInterpolator::WriteResources() const
00235 {
00236 MSG("NCISpectrumInterpolator",
00237 Msg::kInfo) << "NC::ISpectrumInterpolator::WriteResources()" << endl;
00238
00239 const int N = int(shifted.size());
00240 if(N == 0) return;
00241 const int M = int(shifted[0].spectra.size());
00242
00243
00244
00245 double min = FLT_MAX;
00246 double max = FLT_MIN;
00247 for(int n = 0; n < N; ++n){
00248 for(int m = 0; m < M; ++m){
00249 TH1* s = shifted[n].spectra[m];
00250 if(s->GetMinimum(0) < min) min = s->GetMinimum(0);
00251 if(s->GetMaximum() > max) max = s->GetMaximum();
00252 }
00253 }
00254 max = 1+(max-1)*1.1;
00255 min = 1-(1-min)*1.1;
00256 if(max > 2) max = 2;
00257 if(min < 0.5) min = 0.5;
00258
00259 for(int n = 0; n < N; ++n){
00260 for(int m = 0; m < M; ++m){
00261 TH1* s = shifted[n].spectra[m];
00262 s->SetMinimum(min);
00263 s->SetMaximum(max);
00264 s->Write();
00265 }
00266 }
00267
00268 TCanvas canv("all_spectra_canv");
00269
00270
00271 int X = int(TMath::Sqrt(N*M));
00272 int Y = int(TMath::Sqrt(N*M));
00273 if(X*Y < N*M) ++X;
00274 if(X*Y < N*M) ++Y;
00275 canv.Divide(X, Y);
00276
00277 for(int n = 0; n < N; ++n){
00278 for(int m = 0; m < M; ++m){
00279 canv.cd(M*n+m+1);
00280 TH1* s = shifted[n].spectra[m];
00281 s->SetTitle(s->GetName());
00282 if(s->GetXaxis()->GetXmin() == 0 && s->GetXaxis()->GetXmax() == 120)
00283 s->GetXaxis()->SetRangeUser(0, 19.5);
00284 if(s->GetDimension() == 2) s->Draw("colz"); else s->Draw();
00285 }
00286 }
00287 canv.Write();
00288
00289 MSG("NCISpectrumInterpolator",
00290 Msg::kInfo) << "Done writing interpolator resources" << endl;
00291 }
00292
00293
00294 vector<TH1*> NC::ISpectrumInterpolator::GetNominal() const
00295 {
00296 for(unsigned int n = 0; n < shifted.size(); ++n){
00297 if(shifted[n].IsNominal()) return shifted[n].spectra;
00298 }
00299 assert(0 && "No nominal spectrum exists");
00300 }
00301
00302
00303 ostream& operator<<(ostream& op, const TMatrixD& m)
00304 {
00305 op << "| ";
00306 for(int n = 0; n < m.GetNcols(); ++n) op << m(0, n) << " ";
00307 op << "|";
00308 return op;
00309 }
00310
00311 ostream& operator<<(ostream& op, const vector<double>& m)
00312 {
00313 op << "[ ";
00314 for(unsigned int n = 0; n < m.size(); ++n) op << m[n] << " ";
00315 op << "]";
00316 return op;
00317 }
00318
00319
00320 TMatrixD NC::SpectrumInterpolatorFancy::
00321 FindCoeffs(const vector<vector<double> >& xs, const vector<double>& x) const
00322 {
00323 assert(xs[0].size() == x.size());
00324
00325
00326 const int fitOrder = 1;
00327
00328
00329 const int D = x.size();
00330
00331
00332
00333
00334 const int K = intintpow(fitOrder+1, D);
00335
00336 assert(xs.size() >= (unsigned int)K);
00337
00338
00339
00340 vector<vector<int> > pows(K);
00341 for(int k = 0; k < K; ++k) pows[k] = vector<int>(xs.size());
00342
00343
00344
00345
00346
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
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 }
00361
00362
00363
00364 const int N = xs.size();
00365
00366
00367 const double eps = 1e-12;
00368
00369
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 }
00381
00382 TMatrixD mat(K, K);
00383
00384 TMatrixD vecPart(K, N);
00385
00386
00387 for(int n = 0; n < N; ++n){
00388
00389
00390
00391 double denom = 0;
00392 for(int d = 0; d < D; ++d) denom += SQR(x[d]-xs[n][d]);
00393
00394
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
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 }
00412 }
00413 }
00414 mat.Invert();
00415
00416 return basis*mat*vecPart;
00417 }
00418
00419
00420 TMatrixD NC::SpectrumInterpolatorSimple::
00421 FindCoeffs(const vector<vector<double> >& xs, const vector<double>& x) const
00422 {
00423
00424
00425
00426
00427 assert(xs[0].size() <= x.size());
00428 const unsigned int D = TMath::Min(x.size(), xs[0].size());
00429
00430 const unsigned int N = xs.size();
00431
00432 TMatrixD ret(1, N);
00433
00434 for(unsigned int n = 0; n < N; ++n){
00435 double weight = 1;
00436 for(unsigned int d = 0; d < D; ++d){
00437 const bool ltOneSigma = x[d] > -1 && x[d] < +1;
00438
00439 if(ltOneSigma){
00440 const double dist = fabs(xs[n][d]-x[d]);
00441 if(dist > 1)
00442 weight = 0;
00443 else
00444 weight *= (1-dist);
00445 }
00446 else{
00447 const bool sign = xs[n][d]/x[d] >= 0;
00448
00449 if(sign){
00450 if(fabs(xs[n][d]) < 1)
00451 weight *= 1-fabs(x[d]);
00452 else
00453 weight *= fabs(x[d]);
00454 }
00455 else weight = 0;
00456 }
00457 }
00458 ret(0, n) = weight;
00459 }
00460
00461
00462
00463 double norm = 0;
00464 for(unsigned int n = 0; n < N; ++n) norm += ret(0, n);
00465 assert(fabs(norm - 1) < 1e-3);
00466
00467
00468 return ret;
00469 }
00470
00471
00472
00473
00474
00475
00476 TMatrixD NC::SpectrumInterpolatorSimplest::
00477 FindCoeffs(const vector<vector<double> >& xs, const vector<double>& x) const
00478 {
00479 const unsigned int N = xs.size();
00480 TMatrixD ret(1, N);
00481
00482 const unsigned int D = TMath::Min(x.size(), xs[0].size());
00483
00484
00485
00486
00487
00488 assert((N == 1 || D > 0) && "Empty shift");
00489
00490 int nominalIdx = -1;
00491
00492 for(unsigned int n = 0; n < N; ++n){
00493 bool isNominal = true;
00494 double weight = 0;
00495 for(unsigned int d = 0; d < D; ++d){
00496 if(xs[n][d] != 0) isNominal = false;
00497 if((xs[n][d] < 0 && x[d] < 0) ||
00498 (xs[n][d] > 0 && x[d] > 0)){
00499 assert(weight == 0);
00500 weight = x[d] / xs[n][d];
00501 }
00502 }
00503 ret(0, n) = weight;
00504 if(isNominal){
00505
00506 assert(nominalIdx == -1 && "Multiple nominal spectra");
00507 nominalIdx = n;
00508 }
00509 }
00510 assert(nominalIdx >= 0);
00511
00512 assert(ret(0, nominalIdx) == 0);
00513 double norm = 0;
00514 for(unsigned int n = 0; n < N; ++n) norm += ret(0, n);
00515 ret(0, nominalIdx) = 1-norm;
00516
00517
00518
00519 return ret;
00520 }