00001 #include "TMath.h"
00002 #include "TSystem.h"
00003 #include "TRandom3.h"
00004 #include "TTree.h"
00005 #include "TROOT.h"
00006
00007 #include "Fit/UnBinData.h"
00008 #include "Fit/Fitter.h"
00009
00010
00011 #include "Math/IParamFunction.h"
00012 #include "Math/WrappedTF1.h"
00013 #include "Math/WrappedMultiTF1.h"
00014 #include "Math/WrappedParamFunction.h"
00015 #include "Math/MultiDimParamFunctionAdapter.h"
00016
00017 #include "TGraphErrors.h"
00018
00019 #include "TStyle.h"
00020
00021
00022 #include "Math/DistFunc.h"
00023
00024 #include <string>
00025 #include <iostream>
00026
00027 #include "TStopwatch.h"
00028
00029 #define DEBUG
00030
00031
00032
00033 const int N = 1;
00034 const int NGaus = 3;
00035 const int NPar = 8;
00036 const std::string branchType = "x[1]/D";
00037
00038
00039 const int NPoints = 100000;
00040 double truePar[NPar];
00041 double iniPar[NPar];
00042 const int nfit = 1;
00043 const int strategy = 0;
00044
00045 double gausnorm(const double *x, const double *p) {
00046
00047 double invsig = 1./std::abs(p[1]);
00048 double tmp = (x[0]-p[0]) * invsig;
00049 const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 );
00050 return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig;
00051 }
00052
00053 double gausSum(const double *x, const double *p) {
00054
00055 double f = gausnorm(x,p+2) +
00056 p[0] * gausnorm(x,p+4) +
00057 p[1] * gausnorm(x,p+6);
00058
00059 double norm = 1. + p[0] + p[1];
00060 return f/norm;
00061 }
00062
00063 struct MINUIT2 {
00064 static std::string name() { return "Minuit2"; }
00065 static std::string name2() { return ""; }
00066 };
00067
00068
00069 ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) {
00070
00071
00072 ROOT::Fit::UnBinData * d = 0;
00073
00074
00075 d = new ROOT::Fit::UnBinData();
00076
00077 unsigned int n = tree->GetEntries();
00078 #ifdef DEBUG
00079 std::cout << "number of unbin data is " << n << " of dim " << N << std::endl;
00080 #endif
00081 d->Initialize(n,N);
00082 TBranch * bx = tree->GetBranch("x");
00083 double vx[N];
00084 bx->SetAddress(vx);
00085 std::vector<double> m(N);
00086 for (int unsigned i = 0; i < n; ++i) {
00087 bx->GetEntry(i);
00088 d->Add(vx);
00089 for (int j = 0; j < N; ++j)
00090 m[j] += vx[j];
00091 }
00092
00093 #ifdef DEBUG
00094 std::cout << "average values of means :\n";
00095 for (int j = 0; j < N; ++j)
00096 std::cout << m[j]/n << " ";
00097 std::cout << "\n";
00098 #endif
00099
00100 return d;
00101 }
00102
00103
00104
00105
00106 typedef ROOT::Math::IParamMultiFunction Func;
00107 template <class MinType, class T>
00108 int DoUnBinFit(T * tree, Func & func, bool debug = false ) {
00109
00110 ROOT::Fit::UnBinData * d = FillUnBinData(tree );
00111
00112
00113
00114 std::cout << "Filled the fit data " << std::endl;
00115
00116
00117 #ifdef DEBUG
00118 std::cout << "data size type and size is " << typeid(*d).name() << " " << d->Size() << std::endl;
00119 #endif
00120
00121
00122
00123
00124
00125
00126 ROOT::Fit::Fitter fitter;
00127 fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str());
00128
00129 if (debug)
00130 fitter.Config().MinimizerOptions().SetPrintLevel(3);
00131 else
00132 fitter.Config().MinimizerOptions().SetPrintLevel(1);
00133
00134
00135
00136 fitter.Config().MinimizerOptions().SetTolerance(0.01);
00137
00138
00139 fitter.Config().MinimizerOptions().SetStrategy(strategy);
00140
00141
00142
00143
00144 fitter.SetFunction(func);
00145
00146 fitter.Config().ParSettings(0).SetLowerLimit(0.);
00147 fitter.Config().ParSettings(1).SetLowerLimit(0.);
00148
00149 if (debug)
00150 std::cout << "do fitting... " << std::endl;
00151
00152 bool ret = fitter.Fit(*d);
00153 if (!ret) {
00154 std::cout << " Fit Failed " << std::endl;
00155 return -1;
00156 }
00157 if (debug)
00158 fitter.Result().Print(std::cout);
00159
00160
00161 double chi2 = 0;
00162
00163 for (int i = 0; i < NPar; ++i) {
00164 double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) );
00165 chi2 += d*d;
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 double prob = ROOT::Math::chisquared_cdf_c(chi2,NPar);
00181 int iret = (prob < 1.0E-6) ? -1 : 0;
00182 if (iret != 0) {
00183 std::cout <<"Found difference in fitted values - chi2 = " << chi2
00184 << " prob = " << prob << std::endl;
00185 fitter.Result().Print(std::cout);
00186 }
00187
00188 delete d;
00189
00190 return iret;
00191
00192 }
00193
00194
00195 template <class MinType>
00196 int DoFit(TTree * tree, Func & func, bool debug = false ) {
00197 return DoUnBinFit<MinType, TTree>(tree, func, debug);
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 template <class MinType, class FitObj>
00209 int FitUsingNewFitter(FitObj * fitobj, Func & func ) {
00210
00211 std::cout << "\n************************************************************\n";
00212 std::cout << "\tFit using new Fit::Fitter " << typeid(*fitobj).name() << std::endl;
00213 std::cout << "\tMinimizer is " << MinType::name() << " " << MinType::name2() << " func dim = " << func.NDim() << std::endl;
00214
00215 int iret = 0;
00216 TStopwatch w; w.Start();
00217
00218 #ifdef DEBUG
00219 std::cout << "initial Parameters " << iniPar << " " << *iniPar << " " << *(iniPar+1) << std::endl;
00220 func.SetParameters(iniPar);
00221 iret |= DoFit<MinType>(fitobj,func,true );
00222 if (iret != 0) {
00223 std::cout << "Test failed " << std::endl;
00224 }
00225
00226 #else
00227 for (int i = 0; i < nfit; ++i) {
00228 func.SetParameters(iniPar);
00229 iret = DoFit<MinType>(fitobj,func, false);
00230 if (iret != 0) {
00231 std::cout << "Test failed " << std::endl;
00232 break;
00233 }
00234 }
00235 #endif
00236 w.Stop();
00237 std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl;
00238 std::cout << "\n************************************************************\n";
00239
00240 return iret;
00241 }
00242
00243
00244 int testNdimFit() {
00245
00246
00247 std::cout << "\n\n************************************************************\n";
00248 std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM) FIT\n";
00249 std::cout << "************************************************************\n";
00250
00251 TTree t1("t2","a large Tree with gaussian variables");
00252 double x[N];
00253 Int_t ev;
00254 t1.Branch("x",x,branchType.c_str());
00255 t1.Branch("ev",&ev,"ev/I");
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 truePar[0] = 0.2;
00268 truePar[1] = 0.05;
00269 truePar[2] = 0.;
00270 truePar[3] = 0.5;
00271 truePar[4] = 0.;
00272 truePar[5] = 1;
00273 truePar[6] = -3;
00274 truePar[7] = 10;
00275
00276
00277
00278
00279 TRandom3 r;
00280 double norm = (1+truePar[0] + truePar[1] );
00281 double a = 1./norm;
00282 double b = truePar[0]/ norm;
00283 double c = truePar[1]/ norm;
00284 assert(a+b+c == 1.);
00285 std::cout << " True amplitude gaussians " << a << " " << b << " " << c << std::endl;
00286 for (Int_t i=0;i<NPoints;i++) {
00287 for (int j = 0; j < N; ++j) {
00288 if (r.Rndm() < a ) {
00289 double mu = truePar[2];
00290 double s = truePar[3];
00291 x[j] = r.Gaus(mu,s);
00292 }
00293 else if (r.Rndm() < b ) {
00294 double mu = truePar[4];
00295 double s = truePar[5];
00296 x[j] = r.Gaus(mu,s);
00297 }
00298 else {
00299 double mu = truePar[6];
00300 double s = truePar[7];
00301 x[j] = r.Gaus(mu,s);
00302 }
00303 }
00304
00305 ev = i;
00306 t1.Fill();
00307
00308 }
00309
00310
00311 iniPar[0] = 0.5;
00312 iniPar[1] = 0.05;
00313 for (int i = 0; i <NGaus; ++i) {
00314 iniPar[2*i+2] = 0 ;
00315 iniPar[2*i+3] = 1. + 4*i;
00316 std::cout << "inipar " << i << " = " << iniPar[2*i+2] << " " << iniPar[2*i+3] << std::endl;
00317 }
00318
00319
00320
00321 ROOT::Math::WrappedParamFunction<> f2(&gausSum,1,NPar,iniPar);
00322
00323 int iret = 0;
00324 iret |= FitUsingNewFitter<MINUIT2>(&t1,f2);
00325
00326 return iret;
00327 }
00328
00329 int main() {
00330 return testNdimFit();
00331 }