00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #include "TH1.h"
00074 #include "TH2.h"
00075 #include "THnSparse.h"
00076 #include "TGraph.h"
00077 #include "TGraph2D.h"
00078 #include "TGraphErrors.h"
00079 #include "TGraph2DErrors.h"
00080 #include "TTree.h"
00081 #include "TF1.h"
00082 #include "TF2.h"
00083
00084 #include "Math/IFunction.h"
00085 #include "Math/IParamFunction.h"
00086 #include "TMath.h"
00087 #include "Math/DistFunc.h"
00088
00089 #include "TUnuran.h"
00090 #include "TUnuranMultiContDist.h"
00091 #include "Math/MinimizerOptions.h"
00092 #include "TBackCompFitter.h"
00093 #include "TVirtualFitter.h"
00094
00095 #include "Math/WrappedTF1.h"
00096 #include "Math/WrappedMultiTF1.h"
00097 #include "Fit/BinData.h"
00098 #include "Fit/UnBinData.h"
00099 #include "HFitInterface.h"
00100 #include "Fit/Fitter.h"
00101
00102 #include "TRandom3.h"
00103
00104 #include "TROOT.h"
00105
00106 #include "TBenchmark.h"
00107 #include "TCanvas.h"
00108 #include "TApplication.h"
00109
00110 #include <vector>
00111 #include <string>
00112 #include <cassert>
00113 #include <cmath>
00114
00115 #include "Riostream.h"
00116 using namespace std;
00117
00118
00119 #undef R__HAS_MATHMORE
00120
00121 const unsigned int __DRAW__ = 0;
00122
00123 TRandom3 rndm;
00124
00125 enum cmpOpts {
00126 cmpNone = 0,
00127 cmpPars = 1,
00128 cmpDist = 2,
00129 cmpChi2 = 4,
00130 cmpErr = 8,
00131 };
00132
00133
00134 struct RefValue {
00135 const double* pars;
00136 const double chi;
00137 RefValue(const double* p = 0, const double c = 0.0): pars(p), chi(c) {};
00138 };
00139
00140
00141
00142
00143 class CompareResult {
00144 public:
00145 struct RefValue* refValue;
00146 int opts;
00147 double tolPar;
00148 double tolChi2;
00149 CompareResult(int _opts = cmpPars, double _tolPar = 3, double _tolChi2 = 0.01):
00150 refValue(0), opts(_opts), tolPar(_tolPar), tolChi2(_tolChi2) {};
00151
00152 CompareResult(CompareResult const& copy):
00153 refValue(copy.refValue), opts(copy.opts),
00154 tolPar(copy.tolPar), tolChi2(copy.tolChi2) {};
00155
00156 void setRefValue(struct RefValue* _refValue)
00157 {
00158 refValue = _refValue;
00159 };
00160
00161 int parameters(int npar, double val, double ref) const
00162 {
00163 int ret = 0;
00164 if ( refValue && (opts & cmpPars) )
00165 {
00166 ret = compareResult(val, refValue->pars[npar], tolPar*ref);
00167
00168 }
00169 return ret;
00170 };
00171
00172 int chi2(double val) const
00173 { return ( refValue && (opts & cmpChi2) ) ? compareResult(val, refValue->chi, tolChi2) : 0; };
00174
00175 public:
00176
00177 int compareResult(double v1, double v2, double tol = 0.01) const {
00178 if (std::abs(v1-v2) > tol ) return 1;
00179 return 0;
00180 }
00181 };
00182
00183
00184
00185 void FillVariableRange(Double_t v[], Int_t numberOfBins, Double_t minRange, Double_t maxRange)
00186 {
00187 Double_t minLimit = (maxRange-minRange) / (numberOfBins*4);
00188 Double_t maxLimit = (maxRange-minRange)*4/ (numberOfBins);
00189 v[0] = 0;
00190 for ( Int_t i = 1; i < numberOfBins + 1; ++i )
00191 {
00192 Double_t limit = rndm.Uniform(minLimit, maxLimit);
00193 v[i] = v[i-1] + limit;
00194 }
00195
00196 Double_t k = (maxRange-minRange)/v[numberOfBins];
00197 for ( Int_t i = 0; i < numberOfBins + 1; ++i )
00198 {
00199 v[i] = v[i] * k + minRange;
00200 }
00201 }
00202
00203
00204
00205
00206
00207
00208 class algoType {
00209 public:
00210 const char* type;
00211 const char* algo;
00212 const char* opts;
00213 CompareResult cmpResult;
00214
00215 algoType(): type(0), algo(0), opts(0), cmpResult(0) {}
00216
00217 algoType(const char* s1, const char* s2, const char* s3,
00218 CompareResult _cmpResult):
00219 type(s1), algo(s2), opts(s3), cmpResult(_cmpResult) {}
00220 };
00221
00222
00223 vector<algoType> commonAlgos;
00224 vector<algoType> simplexAlgos;
00225 vector<algoType> specialAlgos;
00226 vector<algoType> noGraphAlgos;
00227 vector<algoType> noGraphErrorAlgos;
00228 vector<algoType> graphErrorAlgos;
00229 vector<algoType> histGaus2D;
00230 vector<algoType> linearAlgos;
00231
00232 vector< vector<algoType> > listTH1DAlgos;
00233 vector< vector<algoType> > listAlgosTGraph;
00234 vector< vector<algoType> > listAlgosTGraphError;
00235
00236 vector< vector<algoType> > listLinearAlgos;
00237
00238 vector< vector<algoType> > listTH2DAlgos;
00239 vector< vector<algoType> > listAlgosTGraph2D;
00240 vector< vector<algoType> > listAlgosTGraph2DError;
00241
00242
00243
00244 class ParLimit {
00245 public:
00246 int npar;
00247 double min;
00248 double max;
00249 ParLimit(int _npar = 0, double _min = 0, double _max = 0): npar(_npar), min(_min), max(_max) {};
00250 };
00251
00252
00253 void SetParsLimits(vector<ParLimit>& v, TF1* func)
00254 {
00255 for ( vector<ParLimit>::iterator it = v.begin();
00256 it != v.end(); ++it ) {
00257
00258 func->SetParLimits( it->npar, it->min, it->max);
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 class fitFunctions {
00269 public:
00270 const char* name;
00271 double (*func)(double*, double*);
00272 unsigned int npars;
00273 vector<double> origPars;
00274 vector<double> fitPars;
00275 vector<ParLimit> parLimits;
00276
00277 fitFunctions() {}
00278
00279 fitFunctions(const char* s1, double (*f)(double*, double*),
00280 unsigned int n,
00281 double* v1, double* v2,
00282 vector<ParLimit>& limits):
00283 name(s1), func(f), npars(n),
00284 origPars(npars), fitPars(npars), parLimits(limits.size())
00285 {
00286 copy(v1, v1 + npars, origPars.begin());
00287 copy(v2, v2 + npars, fitPars.begin());
00288 copy(limits.begin(), limits.end(), parLimits.begin());
00289 }
00290 };
00291
00292
00293 vector<fitFunctions> l1DFunctions;
00294 vector<fitFunctions> l2DFunctions;
00295 vector<fitFunctions> treeFunctions;
00296 vector<fitFunctions> l1DLinearFunctions;
00297 vector<fitFunctions> l2DLinearFunctions;
00298
00299
00300 Double_t gaus1DImpl(Double_t* x, Double_t* p)
00301 {
00302 return p[2]*TMath::Gaus(x[0], p[0], p[1]);
00303 }
00304
00305
00306 Double_t poly1DImpl(Double_t *x, Double_t *p)
00307 {
00308 Double_t xx = x[0];
00309 return p[0]*xx*xx*xx+p[1]*xx*xx+p[2]*xx+p[3];
00310 }
00311
00312
00313 Double_t poly2DImpl(Double_t *x, Double_t *p)
00314 {
00315 Double_t xx = x[0];
00316 Double_t yy = x[1];
00317 return p[0]*xx*xx*xx+p[1]*xx*xx+p[2]*xx +
00318 p[3]*yy*yy*yy+p[4]*yy*yy+p[5]*yy +
00319 p[6];
00320 }
00321
00322
00323 Double_t gaus2DImpl(Double_t *x, Double_t *p)
00324 {
00325 return p[0]*TMath::Gaus(x[0], p[1], p[2])*TMath::Gaus(x[1], p[3], p[4]);
00326 }
00327
00328
00329 double gausNormal(Double_t* x, Double_t* p)
00330 {
00331 return p[2]*TMath::Gaus(x[0],p[0],p[1],1);
00332 }
00333
00334
00335 double gaus2dnormal(double *x, double *p) {
00336
00337 double mu_x = p[0];
00338 double sigma_x = p[1];
00339 double mu_y = p[2];
00340 double sigma_y = p[3];
00341 double rho = p[4];
00342 double u = (x[0] - mu_x)/ sigma_x ;
00343 double v = (x[1] - mu_y)/ sigma_y ;
00344 double c = 1 - rho*rho ;
00345 double result = (1 / (2 * TMath::Pi() * sigma_x * sigma_y * sqrt(c)))
00346 * exp (-(u * u - 2 * rho * u * v + v * v ) / (2 * c));
00347 return result;
00348 }
00349
00350
00351 double gausNd(double *x, double *p) {
00352
00353 double f = gaus2dnormal(x,p);
00354 f *= ROOT::Math::normal_pdf(x[2],p[6],p[5]);
00355 f *= ROOT::Math::normal_pdf(x[3],p[8],p[7]);
00356 f *= ROOT::Math::normal_pdf(x[4],p[10],p[9]);
00357 f *= ROOT::Math::normal_pdf(x[5],p[12],p[11]);
00358
00359 if (f <= 0) {
00360 std::cout << "invalid f value " << f << " for x ";
00361 for (int i = 0; i < 6; ++i) std::cout << " " << x[i];
00362 std::cout << "\t P = ";
00363 for (int i = 0; i < 11; ++i) std::cout << " " << p[i];
00364 std::cout << "\n\n ";
00365 return 1.E-300;
00366 }
00367 else if (f > 0) return f;
00368
00369 std::cout << " f is a nan " << f << std::endl;
00370 for (int i = 0; i < 6; ++i) std::cout << " " << x[i];
00371 std::cout << "\t P = ";
00372 for (int i = 0; i < 11; ++i) std::cout << " " << p[i];
00373 std::cout << "\n\n ";
00374 Error("gausNd","f is a nan");
00375 assert(1);
00376 return 0;
00377 }
00378
00379 const double minX = -5.;
00380 const double maxX = +5.;
00381 const double minY = -5.;
00382 const double maxY = +5.;
00383 const int nbinsX = 30;
00384 const int nbinsY = 30;
00385
00386
00387 enum testOpt {
00388 testOptPars = 1,
00389 testOptChi = 2,
00390 testOptErr = 4,
00391 testOptColor = 8,
00392 testOptDebug = 16,
00393 testOptCheck = 32,
00394 };
00395
00396
00397 int defaultOptions = testOptColor | testOptCheck;
00398
00399
00400 template <typename T>
00401 class ObjectWrapper {
00402 public:
00403 T object;
00404 ObjectWrapper(T _obj): object(_obj) {};
00405 template <typename F>
00406 Int_t Fit(F func, const char* opts)
00407 {
00408 if ( opts[0] == 'G' )
00409 {
00410 ROOT::Fit::BinData d;
00411 ROOT::Fit::FillData(d,object,func);
00412
00413 ROOT::Math::WrappedMultiTF1 f(*func);
00414
00415 ROOT::Fit::Fitter fitter;
00416
00417 fitter.Fit(d, f);
00418 const ROOT::Fit::FitResult & fitResult = fitter.Result();
00419
00420 Int_t iret = fitResult.Status();
00421 if (!fitResult.IsEmpty() ) {
00422
00423 func->SetChisquare( fitResult.Chi2() );
00424 func->SetNDF( fitResult.Ndf() );
00425 func->SetNumberFitPoints( d.Size() );
00426
00427 func->SetParameters( &(fitResult.Parameters().front()) );
00428 if ( int( fitResult.Errors().size()) >= func->GetNpar() )
00429 func->SetParErrors( &(fitResult.Errors().front()) );
00430
00431 }
00432
00433
00434 return iret;
00435 } else {
00436
00437 return object->Fit(func, opts);
00438 }
00439 };
00440 const char* GetName() { return object->GetName(); }
00441 };
00442
00443
00444 int gTestIndex = 0;
00445 template <typename T>
00446 void printTestName(T* object, TF1* func)
00447 {
00448 gTestIndex++;
00449 string str = "Test ";
00450 if (gTestIndex < 10) str += " ";
00451 str += ROOT::Math::Util::ToString(gTestIndex);
00452 str += ": '";
00453 str += object->GetName();
00454 str += "' with '";
00455 str += func->GetName();
00456 str += "'...";
00457 while ( str.length() != 65 )
00458 str += '.';
00459 printf("%s", str.c_str());
00460 fflush(stdout);
00461 }
00462
00463
00464 void printTitle(TF1* func)
00465 {
00466 printf("\nMin Type | Min Algo | OPT | PARAMETERS ");
00467 int n = func->GetNpar();
00468 for ( int i = 1; i < n; ++i ) {
00469 printf(" ");
00470 }
00471 printf(" | CHI2TEST | ERRORS \n");
00472 fflush(stdout);
00473 }
00474
00475
00476 void printSeparator()
00477 {
00478 fflush(stdout);
00479 printf("*********************************************************************"
00480 "********************************************************************\n");
00481 fflush(stdout);
00482 }
00483
00484
00485 void setColor(int red = 0)
00486 {
00487 char command[13];
00488 if ( red )
00489 sprintf(command, "%c[%d;%d;%dm", 0x1B, 1, 1 + 30, 8 + 40);
00490 else
00491 sprintf(command, "%c[%d;%d;%dm", 0x1B, 0, 0 + 30, 8 + 40);
00492 printf("%s", command);
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 int testFit(const char* str1, const char* str2, const char* str3,
00504 TF1* func, CompareResult const& cmpResult, int opts)
00505 {
00506 bool debug = opts & testOptDebug;
00507
00508
00509 int status = 0;
00510 int diff = 0;
00511
00512 double chi2 = 0;
00513 if ( opts & testOptChi || opts & testOptCheck )
00514 chi2 = func->GetChisquare();
00515
00516 fflush(stdout);
00517 if ( opts & testOptPars )
00518 {
00519 int n = func->GetNpar();
00520 double* values = func->GetParameters();
00521 if ( debug )
00522 printf("%-11s | %-11s | %-4s | ", str1, str2, str3);
00523 for ( int i = 0; i < n; ++i ) {
00524 if ( opts & testOptCheck )
00525 diff = cmpResult.parameters(i,
00526 values[i],
00527 std::max(std::sqrt(chi2/func->GetNDF()),1.0)*func->GetParError(i));
00528 status += diff;
00529 if ( opts & testOptColor )
00530 setColor ( diff );
00531 if ( debug )
00532 printf("%10.6f +/-(%-6.3f) ", values[i], func->GetParError(i));
00533 fflush(stdout);
00534 }
00535 setColor(0);
00536 }
00537
00538 if ( opts & testOptChi )
00539 {
00540 if ( debug )
00541 printf(" | chi2: %9.4f | ", chi2);
00542 }
00543
00544 if ( opts & testOptErr )
00545 {
00546 assert(TVirtualFitter::GetFitter() != 0 );
00547 TBackCompFitter* fitter = dynamic_cast<TBackCompFitter*>( TVirtualFitter::GetFitter() );
00548 assert(fitter != 0);
00549 const ROOT::Fit::FitResult& fitResult = fitter->GetFitResult();
00550 if ( debug )
00551 printf("err: ");
00552 int n = func->GetNpar();
00553 for ( int i = 0; i < n; ++i ) {
00554 if ( debug )
00555 printf("%c ", (fitResult.LowerError(i) == fitResult.UpperError(i))?'E':'D');
00556 }
00557 if ( debug )
00558 printf("| ");
00559 }
00560
00561 if ( opts != 0 )
00562 {
00563 setColor(0);
00564 if ( debug )
00565 printf("\n");
00566 }
00567 fflush(stdout);
00568
00569 return status;
00570 }
00571
00572
00573
00574
00575
00576
00577 template <typename T, typename F>
00578 int testFitters(T* object, F* func, vector< vector<algoType> >& listAlgos, fitFunctions const& fitFunction)
00579 {
00580
00581 int status = 0;
00582 int numberOfTests = 0;
00583 const double* origpars = &(fitFunction.origPars[0]);
00584 const double* fitpars = &(fitFunction.fitPars[0]);
00585
00586 func->SetParameters(fitpars);
00587
00588 printTestName(object, func);
00589 ROOT::Math::MinimizerOptions::SetDefaultMinimizer(commonAlgos[0].type, commonAlgos[0].algo);
00590 object->Fit(func, "Q0");
00591 if ( defaultOptions & testOptDebug ) printTitle(func);
00592 struct RefValue ref(origpars, func->GetChisquare());
00593 commonAlgos[0].cmpResult.setRefValue(&ref);
00594 int defMinOptions = testOptPars | testOptChi | testOptErr | defaultOptions;
00595 status += testFit(commonAlgos[0].type, commonAlgos[0].algo
00596 , commonAlgos[0].opts, func
00597 , commonAlgos[0].cmpResult, defMinOptions);
00598 numberOfTests += 1;
00599
00600 if ( defaultOptions & testOptDebug )
00601 {
00602 printSeparator();
00603 func->SetParameters(origpars);
00604 status += testFit("Parameters", "Original", "", func, commonAlgos[0].cmpResult, testOptPars | testOptDebug);
00605 func->SetParameters(fitpars);
00606 status += testFit("Parameters", "Initial", "", func, commonAlgos[0].cmpResult, testOptPars | testOptDebug);
00607 printSeparator();
00608 }
00609
00610 for ( unsigned int j = 0; j < listAlgos.size(); ++j )
00611 {
00612 for ( unsigned int i = 0; i < listAlgos[j].size(); ++i )
00613 {
00614 int testFitOptions = testOptPars | testOptChi | testOptErr | defaultOptions;
00615 ROOT::Math::MinimizerOptions::SetDefaultMinimizer(listAlgos[j][i].type, listAlgos[j][i].algo);
00616 func->SetParameters(fitpars);
00617 fflush(stdout);
00618 object->Fit(func, listAlgos[j][i].opts);
00619 listAlgos[j][i].cmpResult.setRefValue(&ref);
00620 status += testFit(listAlgos[j][i].type, listAlgos[j][i].algo, listAlgos[j][i].opts
00621 , func, listAlgos[j][i].cmpResult, testFitOptions);
00622 numberOfTests += 1;
00623 fflush(stdout);
00624 }
00625 }
00626
00627 double percentageFailure = double( status * 100 ) / double( numberOfTests*func->GetNpar() );
00628
00629 if ( defaultOptions & testOptDebug )
00630 {
00631 printSeparator();
00632 printf("Number of fails: %d Total Number of tests %d", status, numberOfTests);
00633 printf(" Percentage of failure: %f\n", percentageFailure );
00634 }
00635
00636
00637 return (percentageFailure < 4)?0:1;
00638 }
00639
00640
00641 int test1DObjects(vector< vector<algoType> >& listH,
00642 vector< vector<algoType> >& listG,
00643 vector< vector<algoType> >& listGE,
00644 vector<fitFunctions>& listOfFunctions)
00645 {
00646
00647 int globalStatus = 0;
00648
00649 int status = 0;
00650
00651 TF1* func = 0;
00652 TH1D* h1 = 0;
00653 TH1D* h2 = 0;
00654 THnSparse* s1 = 0;
00655 TGraph* g1 = 0;
00656 TGraphErrors* ge1 = 0;
00657 TCanvas *c0 = 0, *c1 = 0, *c2 = 0, *c3 = 0;
00658 for ( unsigned int j = 0; j < listOfFunctions.size(); ++j )
00659 {
00660 if ( func ) delete func;
00661 func = new TF1( listOfFunctions[j].name, listOfFunctions[j].func, minX, maxX, listOfFunctions[j].npars);
00662 func->SetParameters(&(listOfFunctions[j].origPars[0]));
00663 SetParsLimits(listOfFunctions[j].parLimits, func);
00664
00665
00666 if ( h1 ) delete h1;
00667 h1 = new TH1D("Histogram 1D","h1-title",nbinsX,minX,maxX);
00668 for ( int i = 0; i <= h1->GetNbinsX() + 1; ++i )
00669 h1->Fill( h1->GetBinCenter(i), rndm.Poisson( func->Eval( h1->GetBinCenter(i) ) ) );
00670
00671 double v[nbinsX + 1];
00672 FillVariableRange(v, nbinsX, minX, maxX);
00673 if ( h2 ) delete h2;
00674 h2 = new TH1D("Histogram 1D Variable","h2-title",nbinsX, v);
00675 for ( int i = 0; i <= h2->GetNbinsX() + 1; ++i )
00676 h2->Fill( h2->GetBinCenter(i), rndm.Poisson( func->Eval( h2->GetBinCenter(i) ) ) );
00677
00678 delete c0; c0 = new TCanvas("c0-1D", "Histogram1D Variable");
00679 if ( __DRAW__ ) h2->Draw();
00680 ObjectWrapper<TH1D*> owh2(h2);
00681 globalStatus += status = testFitters(&owh2, func, listH, listOfFunctions[j]);
00682 printf("%s\n", (status?"FAILED":"OK"));
00683
00684 delete c1; c1 = new TCanvas("c1-1D", "Histogram1D");
00685 if ( __DRAW__ ) h1->Draw();
00686 ObjectWrapper<TH1D*> owh1(h1);
00687 globalStatus += status = testFitters(&owh1, func, listH, listOfFunctions[j]);
00688 printf("%s\n", (status?"FAILED":"OK"));
00689
00690 delete g1; g1 = new TGraph(h1);
00691 g1->SetName("TGraph 1D");
00692 g1->SetTitle("TGraph 1D - title");
00693 if ( c2 ) delete c2;
00694 c2 = new TCanvas("c2-1D","TGraph");
00695 if ( __DRAW__ ) g1->Draw("AB*");
00696 ObjectWrapper<TGraph*> owg1(g1);
00697 globalStatus += status = testFitters(&owg1, func, listG, listOfFunctions[j]);
00698 printf("%s\n", (status?"FAILED":"OK"));
00699
00700 delete ge1; ge1 = new TGraphErrors(h1);
00701 ge1->SetName("TGraphErrors 1D");
00702 ge1->SetTitle("TGraphErrors 1D - title");
00703 if ( c3 ) delete c3;
00704 c3 = new TCanvas("c3-1D","TGraphError");
00705 if ( __DRAW__ ) ge1->Draw("AB*");
00706 ObjectWrapper<TGraphErrors*> owge1(ge1);
00707 globalStatus += status = testFitters(&owge1, func, listGE, listOfFunctions[j]);
00708 printf("%s\n", (status?"FAILED":"OK"));
00709
00710 delete s1; s1 = THnSparse::CreateSparse("THnSparse 1D", "THnSparse 1D - title", h1);
00711 ObjectWrapper<THnSparse*> ows1(s1);
00712 globalStatus += status = testFitters(&ows1, func, listH, listOfFunctions[j]);
00713 printf("%s\n", (status?"FAILED":"OK"));
00714 }
00715
00716 if ( ! __DRAW__ )
00717 {
00718 delete func;
00719 delete h1;
00720 delete h2;
00721 delete g1;
00722 delete ge1;
00723 delete c0;
00724 delete c1;
00725 delete c2;
00726 delete c3;
00727 }
00728
00729 return globalStatus;
00730 }
00731
00732
00733 int test2DObjects(vector< vector<algoType> >& listH,
00734 vector< vector<algoType> >& listG,
00735 vector< vector<algoType> >& listGE,
00736 vector<fitFunctions>& listOfFunctions)
00737 {
00738
00739 int globalStatus = 0;
00740
00741 int status = 0;
00742
00743 TF2* func = 0;
00744 TH2D* h1 = 0;
00745 TH2D* h2 = 0;
00746 THnSparse* s1 = 0;
00747 TGraph2D* g1 = 0;
00748 TGraph2DErrors* ge1 = 0;
00749 TCanvas *c0 = 0, *c1 = 0, *c2 = 0, *c3 = 0;
00750 for ( unsigned int h = 0; h < listOfFunctions.size(); ++h )
00751 {
00752 if ( func ) delete func;
00753 func = new TF2( listOfFunctions[h].name, listOfFunctions[h].func, minX, maxX, minY, maxY, listOfFunctions[h].npars);
00754 func->SetParameters(&(listOfFunctions[h].origPars[0]));
00755 SetParsLimits(listOfFunctions[h].parLimits, func);
00756
00757
00758 if ( h1 ) delete h1;
00759 h1 = new TH2D("Histogram 2D","h1-title",nbinsX,minX,maxX,nbinsY,minY,maxY);
00760 if ( ge1 ) delete ge1;
00761 ge1 = new TGraph2DErrors((h1->GetNbinsX() + 1) * (h1->GetNbinsY() + 1));
00762 ge1->SetName("Graph2D with Errors");
00763 ge1->SetTitle("Graph2D with Errors");
00764 unsigned int counter = 0;
00765 for ( int i = 0; i <= h1->GetNbinsX() + 1; ++i )
00766 for ( int j = 0; j <= h1->GetNbinsY() + 1; ++j )
00767 {
00768 double xc = h1->GetXaxis()->GetBinCenter(i);
00769 double yc = h1->GetYaxis()->GetBinCenter(j);
00770 double content = rndm.Poisson( func->Eval( xc, yc ) );
00771 h1->Fill( xc, yc, content );
00772 ge1->SetPoint(counter, xc, yc, content);
00773 ge1->SetPointError(counter,
00774 h1->GetXaxis()->GetBinWidth(i) / 2,
00775 h1->GetYaxis()->GetBinWidth(j) / 2,
00776 h1->GetBinError(i,j));
00777 counter += 1;
00778 }
00779
00780 if ( h2 ) delete h2;
00781 double x[nbinsX + 1];
00782 FillVariableRange(x, nbinsX, minX, maxX);
00783 double y[nbinsY + 1];
00784 FillVariableRange(y, nbinsY, minY, maxY);
00785 h2 = new TH2D("Histogram 2D Variable","h2-title",nbinsX, x, nbinsY, y);
00786 for ( int i = 0; i <= h2->GetNbinsX() + 1; ++i )
00787 for ( int j = 0; j <= h2->GetNbinsY() + 1; ++j )
00788 {
00789 double xc = h2->GetXaxis()->GetBinCenter(i);
00790 double yc = h2->GetYaxis()->GetBinCenter(j);
00791 double content = rndm.Poisson( func->Eval( xc, yc ) );
00792 h2->Fill( xc, yc, content );
00793 }
00794
00795 if ( c0 ) delete c0;
00796 c0 = new TCanvas("c0-2D", "Histogram2D Variable");
00797 if ( __DRAW__ ) h2->Draw();
00798 ObjectWrapper<TH2D*> owh2(h2);
00799 globalStatus += status = testFitters(&owh2, func, listH, listOfFunctions[h]);
00800 printf("%s\n", (status?"FAILED":"OK"));
00801
00802 if ( c1 ) delete c1;
00803 c1 = new TCanvas("c1-2D", "Histogram2D");
00804 if ( __DRAW__ ) h1->Draw();
00805 ObjectWrapper<TH2D*> owh1(h1);
00806 globalStatus += status = testFitters(&owh1, func, listH, listOfFunctions[h]);
00807 printf("%s\n", (status?"FAILED":"OK"));
00808
00809 if ( g1 ) delete g1;
00810 g1 = new TGraph2D(h1);
00811 g1->SetName("TGraph 2D");
00812 g1->SetTitle("TGraph 2D - title");
00813
00814 if ( c2 ) delete c2;
00815 c2 = new TCanvas("c2-2D","TGraph");
00816 if ( __DRAW__ ) g1->Draw("AB*");
00817 ObjectWrapper<TGraph2D*> owg1(g1);
00818 globalStatus += status = testFitters(&owg1, func, listG, listOfFunctions[h]);
00819 printf("%s\n", (status?"FAILED":"OK"));
00820
00821
00822 ge1->SetName("TGraphErrors 2DGE");
00823 ge1->SetTitle("TGraphErrors 2DGE - title");
00824 if ( c3 ) delete c3;
00825 c3 = new TCanvas("c3-2DGE","TGraphError");
00826 if ( __DRAW__ ) ge1->Draw("AB*");
00827 ObjectWrapper<TGraph2DErrors*> owge1(ge1);
00828 globalStatus += status = testFitters(&owge1, func, listGE, listOfFunctions[h]);
00829 printf("%s\n", (status?"FAILED":"OK"));
00830
00831 delete s1; s1 = THnSparse::CreateSparse("THnSparse 2D", "THnSparse 2D - title", h1);
00832 ObjectWrapper<THnSparse*> ows1(s1);
00833 globalStatus += status = testFitters(&ows1, func, listH, listOfFunctions[h]);
00834 printf("%s\n", (status?"FAILED":"OK"));
00835 }
00836
00837 if ( ! __DRAW__ )
00838 {
00839 delete func;
00840 delete h1;
00841 delete h2;
00842 delete g1;
00843 delete ge1;
00844 delete c0;
00845 delete c1;
00846 delete c2;
00847 delete c3;
00848 }
00849
00850 return globalStatus;
00851 }
00852
00853
00854
00855
00856 class TreeWrapper {
00857 public:
00858
00859 const char* vars;
00860 const char* cuts;
00861 TTree *tree;
00862
00863 void set(TTree* t, const char* v, const char* c)
00864 {
00865 tree = t;
00866 vars = v;
00867 cuts = c;
00868 }
00869
00870 const char* GetName() const {
00871 return tree->GetName();
00872 }
00873
00874 Int_t Fit(TF1* f1, Option_t* option = "")
00875 {
00876 return tree->UnbinnedFit(f1->GetName(), vars, cuts, option);
00877 }
00878 };
00879
00880
00881 int testUnBinnedFit(int n = 10000)
00882 {
00883
00884 int globalStatus = 0;
00885
00886 int status = 0;
00887
00888 double origPars[13] = {1,2,3,0.5, 0.5, 0, 3, 0, 4, 0, 5, 1, 10 };
00889
00890
00891 TF2 * func = new TF2("gaus2Dn",gaus2dnormal,-10,-10,-10,10,5);
00892 func->SetParameters(origPars);
00893
00894 TUnuranMultiContDist dist(func);
00895 TUnuran unr(&rndm);
00896
00897
00898 if (! unr.Init(dist,"vnrou")) {
00899 std::cerr << "error in init unuran " << std::endl; return -1;
00900 }
00901
00902 TTree * tree = new TTree("tree","2 var gaus tree");
00903 double x,y,z,u,v,w;
00904 tree->Branch("x",&x,"x/D");
00905 tree->Branch("y",&y,"y/D");
00906 tree->Branch("z",&z,"z/D");
00907 tree->Branch("u",&u,"u/D");
00908 tree->Branch("v",&v,"v/D");
00909 tree->Branch("w",&w,"w/D");
00910 double xx[2];
00911 for (Int_t i=0;i<n;i++) {
00912 unr.SampleMulti(xx);
00913 x = xx[0];
00914 y = xx[1];
00915 z = rndm.Gaus(origPars[5],origPars[6]);
00916 u = rndm.Gaus(origPars[7],origPars[8]);
00917 v = rndm.Gaus(origPars[9],origPars[10]);
00918 w = rndm.Gaus(origPars[11],origPars[12]);
00919
00920 tree->Fill();
00921
00922 }
00923
00924 delete func;
00925
00926 vector< vector<algoType> > listAlgos(2);
00927 listAlgos[0] = commonAlgos;
00928 listAlgos[1] = simplexAlgos;
00929
00930 TreeWrapper tw;
00931
00932 TF1 * f1 = new TF1(treeFunctions[0].name,treeFunctions[0].func,minX,maxY,treeFunctions[0].npars);
00933 f1->SetParameters( &(treeFunctions[0].fitPars[0]) );
00934 f1->FixParameter(2,1);
00935 tw.set(tree, "x", "");
00936 globalStatus += status = testFitters(&tw, f1, listAlgos, treeFunctions[0]);
00937 printf("%s\n", (status?"FAILED":"OK"));
00938
00939 vector<algoType> noCompareInTree;
00940
00941
00942
00943 vector< vector<algoType> > listAlgosND(2);
00944 listAlgosND[0] = commonAlgos;
00945 listAlgosND[1] = noCompareInTree;
00946
00947 TF2 * f2 = new TF2(treeFunctions[1].name,treeFunctions[1].func,minX,maxX,minY,maxY,treeFunctions[1].npars);
00948 f2->SetParameters( &(treeFunctions[1].fitPars[0]) );
00949 tw.set(tree, "x:y", "");
00950 globalStatus += status = testFitters(&tw, f2, listAlgosND, treeFunctions[1]);
00951 printf("%s\n", (status?"FAILED":"OK"));
00952
00953 TF1 * f4 = new TF1("gausND",gausNd,0,1,13);
00954 f4->SetParameters(&(treeFunctions[2].fitPars[0]));
00955 tw.set(tree, "x:y:z:u:v:w", "");
00956 globalStatus += status = testFitters(&tw, f4, listAlgosND, treeFunctions[2]);
00957 printf("%s\n", (status?"FAILED":"OK"));
00958
00959 delete tree;
00960 delete f1;
00961 delete f2;
00962 delete f4;
00963
00964 return globalStatus;
00965 }
00966
00967
00968
00969 void init_structures()
00970 {
00971 commonAlgos.push_back( algoType( "Minuit", "Migrad", "Q0", CompareResult()) );
00972 commonAlgos.push_back( algoType( "Minuit", "Minimize", "Q0", CompareResult()) );
00973 commonAlgos.push_back( algoType( "Minuit", "Scan", "Q0", CompareResult(0)) );
00974 commonAlgos.push_back( algoType( "Minuit", "Seek", "Q0", CompareResult()) );
00975 commonAlgos.push_back( algoType( "Minuit2", "Migrad", "Q0", CompareResult()) );
00976 commonAlgos.push_back( algoType( "Minuit2", "Minimize", "Q0", CompareResult()) );
00977 commonAlgos.push_back( algoType( "Minuit2", "Scan", "Q0", CompareResult(0)) );
00978 commonAlgos.push_back( algoType( "Minuit2", "Fumili2", "Q0", CompareResult()) );
00979 #ifdef R__HAS_MATHMORE
00980 commonAlgos.push_back( algoType( "GSLMultiMin", "conjugatefr", "Q0", CompareResult()) );
00981 commonAlgos.push_back( algoType( "GSLMultiMin", "conjugatepr", "Q0", CompareResult()) );
00982 commonAlgos.push_back( algoType( "GSLMultiMin", "bfgs2", "Q0", CompareResult()) );
00983 commonAlgos.push_back( algoType( "GSLSimAn", "", "Q0", CompareResult()) );
00984 #endif
00985
00986
00987 simplexAlgos.push_back( algoType( "Minuit", "Simplex", "Q0", CompareResult()) );
00988 simplexAlgos.push_back( algoType( "Minuit2", "Simplex", "Q0", CompareResult()) );
00989
00990 specialAlgos.push_back( algoType( "Minuit", "Migrad", "QE0", CompareResult()) );
00991 specialAlgos.push_back( algoType( "Minuit", "Migrad", "QW0", CompareResult()) );
00992
00993 noGraphAlgos.push_back( algoType( "Minuit", "Migrad", "Q0I", CompareResult()) );
00994 noGraphAlgos.push_back( algoType( "Minuit", "Migrad", "QL0", CompareResult()) );
00995 noGraphAlgos.push_back( algoType( "Minuit", "Migrad", "QLI0", CompareResult()) );
00996
00997
00998
00999 noGraphAlgos.push_back( algoType( "Minuit", "Migrad", "GQ0", CompareResult()) );
01000
01001 noGraphAlgos.push_back( algoType( "Minuit2", "Migrad", "GQ0", CompareResult()) );
01002 noGraphAlgos.push_back( algoType( "Minuit2", "Minimize", "GQ0", CompareResult()) );
01003 noGraphAlgos.push_back( algoType( "Fumili", "Fumili", "GQ0", CompareResult()) );
01004 noGraphAlgos.push_back( algoType( "Minuit2", "Fumili", "GQ0", CompareResult()) );
01005
01006 noGraphAlgos.push_back( algoType( "Minuit", "Migrad", "GQL0", CompareResult()) );
01007
01008 noGraphErrorAlgos.push_back( algoType( "Fumili", "Fumili", "Q0", CompareResult()) );
01009 #ifdef R__HAS_MATHMORE
01010 noGraphErrorAlgos.push_back( algoType( "GSLMultiFit", "", "Q0", CompareResult()) );
01011 #endif
01012
01013
01014 histGaus2D.push_back( algoType( "Minuit", "Migrad", "Q0", CompareResult(cmpPars,6)) );
01015 histGaus2D.push_back( algoType( "Minuit", "Minimize", "Q0", CompareResult(cmpPars,6)) );
01016 histGaus2D.push_back( algoType( "Minuit", "Scan", "Q0", CompareResult(0)) );
01017 histGaus2D.push_back( algoType( "Minuit", "Seek", "Q0", CompareResult(cmpPars,6)) );
01018 histGaus2D.push_back( algoType( "Minuit2", "Migrad", "Q0", CompareResult(cmpPars,6)) );
01019 histGaus2D.push_back( algoType( "Minuit2", "Minimize", "Q0", CompareResult(cmpPars,6)) );
01020 histGaus2D.push_back( algoType( "Minuit2", "Scan", "Q0", CompareResult(0)) );
01021 histGaus2D.push_back( algoType( "Minuit2", "Fumili2", "Q0", CompareResult(cmpPars,6)) );
01022 #ifdef R__HAS_MATHMORE
01023 histGaus2D.push_back( algoType( "GSLMultiMin", "conjugatefr", "Q0", CompareResult(cmpPars,6)) );
01024 histGaus2D.push_back( algoType( "GSLMultiMin", "conjugatepr", "Q0", CompareResult(cmpPars,6)) );
01025 histGaus2D.push_back( algoType( "GSLMultiMin", "bfgs2", "Q0", CompareResult(cmpPars,6)) );
01026 histGaus2D.push_back( algoType( "GSLSimAn", "", "Q0", CompareResult(cmpPars,6)) );
01027 #endif // treeFail
01028 histGaus2D.push_back( algoType( "Minuit", "Simplex", "Q0", CompareResult(cmpPars,6)) );
01029
01030
01031
01032 histGaus2D.push_back( algoType( "Minuit", "Migrad", "QE0", CompareResult(cmpPars,6)) );
01033 histGaus2D.push_back( algoType( "Minuit", "Migrad", "QW0", CompareResult()) );
01034
01035 histGaus2D.push_back( algoType( "Minuit", "Migrad", "Q0I", CompareResult(cmpPars,6)) );
01036 histGaus2D.push_back( algoType( "Minuit", "Migrad", "QL0", CompareResult()) );
01037 histGaus2D.push_back( algoType( "Minuit", "Migrad", "QLI0", CompareResult()) );
01038
01039
01040 histGaus2D.push_back( algoType( "Minuit", "Migrad", "GQ0", CompareResult()) );
01041 histGaus2D.push_back( algoType( "Minuit", "Minimize", "GQ0", CompareResult()) );
01042 histGaus2D.push_back( algoType( "Minuit2", "Migrad", "GQ0", CompareResult()) );
01043 histGaus2D.push_back( algoType( "Minuit2", "Minimize", "GQ0", CompareResult()) );
01044 histGaus2D.push_back( algoType( "Fumili", "Fumili", "GQ0", CompareResult()) );
01045 histGaus2D.push_back( algoType( "Minuit2", "Fumili", "GQ0", CompareResult()) );
01046
01047 histGaus2D.push_back( algoType( "Minuit", "Migrad", "GQL0", CompareResult()) );
01048
01049
01050 histGaus2D.push_back( algoType( "Fumili", "Fumili", "Q0", CompareResult(cmpPars,6)) );
01051 #ifdef R__HAS_MATHMORE
01052 histGaus2D.push_back( algoType( "GSLMultiFit", "", "Q0", CompareResult(cmpPars,6)) );
01053 #endif
01054
01055 graphErrorAlgos.push_back( algoType( "Minuit", "Migrad", "Q0EX0", CompareResult()) );
01056 graphErrorAlgos.push_back( algoType( "Minuit2", "Migrad", "Q0EX0", CompareResult()) );
01057
01058
01059
01060
01061
01062
01063
01064 linearAlgos.push_back( algoType( "Linear", "", "Q0XG", CompareResult()) );
01065 listLinearAlgos.push_back( linearAlgos );
01066
01067 listTH1DAlgos.push_back( commonAlgos );
01068 listTH1DAlgos.push_back( simplexAlgos );
01069 listTH1DAlgos.push_back( specialAlgos );
01070 listTH1DAlgos.push_back( noGraphAlgos );
01071 listTH1DAlgos.push_back( noGraphErrorAlgos );
01072
01073 listAlgosTGraph.push_back( commonAlgos );
01074 listAlgosTGraph.push_back( simplexAlgos );
01075 listAlgosTGraph.push_back( specialAlgos );
01076 listAlgosTGraph.push_back( noGraphErrorAlgos );
01077
01078 listAlgosTGraphError.push_back( commonAlgos );
01079 listAlgosTGraphError.push_back( simplexAlgos );
01080 listAlgosTGraphError.push_back( specialAlgos );
01081 listAlgosTGraphError.push_back( graphErrorAlgos );
01082
01083 listTH2DAlgos.push_back( histGaus2D );
01084
01085 listAlgosTGraph2D.push_back( commonAlgos );
01086 listAlgosTGraph2D.push_back( specialAlgos );
01087 listAlgosTGraph2D.push_back( noGraphErrorAlgos );
01088
01089 listAlgosTGraph2DError.push_back( commonAlgos );
01090 listAlgosTGraph2DError.push_back( specialAlgos );
01091 listAlgosTGraph2DError.push_back( graphErrorAlgos );
01092
01093 vector<ParLimit> emptyLimits(0);
01094
01095 double gausOrig[] = { 0., 3., 200.};
01096 double gausFit[] = {0.5, 3.7, 250.};
01097 vector<ParLimit> gaus1DLimits;
01098 gaus1DLimits.push_back( ParLimit(1, 0, 5) );
01099 l1DFunctions.push_back( fitFunctions("GAUS", gaus1DImpl, 3, gausOrig, gausFit, gaus1DLimits) );
01100 double poly1DOrig[] = { 2, 3, 4, 200};
01101 double poly1DFit[] = { 6.4, -2.3, 15.4, 210.5};
01102 l1DFunctions.push_back( fitFunctions("Polynomial", poly1DImpl, 4, poly1DOrig, poly1DFit, emptyLimits) );
01103
01104
01105 double gaus2DOrig[] = { 500., +.5, 2.7, -.5, 3.0 };
01106 double gaus2DFit[] = { 510., .0, 1.8, -1.0, 1.6};
01107 l2DFunctions.push_back( fitFunctions("gaus2D", gaus2DImpl, 5, gaus2DOrig, gaus2DFit, emptyLimits) );
01108
01109 double gausnOrig[3] = {1,2,1};
01110 double treeOrig[13] = {1,2,3,0.5, 0.5, 0, 3, 0, 4, 0, 5, 1, 10 };
01111 double treeFit[13] = {1,1,1, 1, 0.1, 0, 2, 0, 3, 0, 4, 0, 9 };
01112 treeFunctions.push_back( fitFunctions("gausn", gausNormal, 3, gausnOrig, treeFit, emptyLimits ));
01113 treeFunctions.push_back( fitFunctions("gaus2Dn", gaus2dnormal, 5, treeOrig, treeFit, emptyLimits));
01114 treeFunctions.push_back( fitFunctions("gausND", gausNd, 13, treeOrig, treeFit, emptyLimits));
01115
01116 l1DLinearFunctions.push_back( fitFunctions("Polynomial", poly1DImpl, 4, poly1DOrig, poly1DFit, emptyLimits) );
01117
01118 double poly2DOrig[] = { 2, 3, 4, 5, 6, 7, 200, };
01119 double poly2DFit[] = { 6.4, -2.3, 15.4, 3, 10, -3, 210.5};
01120 l2DLinearFunctions.push_back( fitFunctions("Poly2D", poly2DImpl, 7, poly2DOrig, poly2DFit, emptyLimits) );
01121 }
01122
01123 int stressFit()
01124 {
01125 rndm.SetSeed(10);
01126
01127 init_structures();
01128
01129 int iret = 0;
01130
01131 TBenchmark bm;
01132 bm.Start("stressHistoFit");
01133
01134 cout << "****************************************************************************" <<endl;
01135 cout << "* Starting stress H I S T O F I T *" <<endl;
01136 cout << "****************************************************************************" <<endl;
01137
01138 std::cout << "\nTest 1D and 2D objects\n\n";
01139 iret += test1DObjects(listTH1DAlgos, listAlgosTGraph, listAlgosTGraphError, l1DFunctions);
01140 iret += test2DObjects(listTH2DAlgos, listAlgosTGraph2D, listAlgosTGraph2DError, l2DFunctions);
01141 std::cout << "\nTest Linear fits\n\n";
01142 iret += test1DObjects(listLinearAlgos, listLinearAlgos, listLinearAlgos, l1DLinearFunctions);
01143 iret += test2DObjects(listLinearAlgos, listLinearAlgos, listLinearAlgos, l2DLinearFunctions);
01144
01145
01146 std::cout << "\nTest unbinned fits\n\n";
01147 iret += testUnBinnedFit(2000);
01148
01149 bm.Stop("stressHistoFit");
01150 std::cout <<"\n****************************************************************************\n";
01151 bm.Print("stressHistoFit");
01152 const double reftime = 124;
01153 double rootmarks = 800 * reftime / bm.GetCpuTime("stressHistoFit");
01154 std::cout << " ROOTMARKS = " << rootmarks << " ROOT version: " << gROOT->GetVersion() << "\t"
01155 << gROOT->GetSvnBranch() << "@" << gROOT->GetSvnRevision() << std::endl;
01156 std::cout <<"****************************************************************************\n";
01157
01158 return iret;
01159 }
01160
01161 int main(int argc, char** argv)
01162 {
01163 TApplication* theApp = 0;
01164
01165 if ( __DRAW__ )
01166 theApp = new TApplication("App",&argc,argv);
01167
01168 int ret = stressFit();
01169
01170 if ( __DRAW__ ) {
01171 theApp->Run();
01172 delete theApp;
01173 theApp = 0;
01174 }
01175
01176 return ret;
01177 }