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 = 10;
00034 const std::string branchType = "x[10]/D";
00035 const int NPoints = 100000;
00036
00037
00038
00039
00040
00041
00042
00043 double truePar[2*N];
00044 double iniPar[2*N];
00045 const int nfit = 1;
00046 const int strategy = 0;
00047
00048 double gausnorm(const double *x, const double *p) {
00049
00050 double invsig = 1./p[1];
00051 double tmp = (x[0]-p[0]) * invsig;
00052 const double sqrt_2pi = 1./std::sqrt(2.* 3.14159 );
00053 return std::exp(-0.5 * tmp*tmp ) * sqrt_2pi * invsig;
00054 }
00055
00056 double gausnormN(const double *x, const double *p) {
00057 double f = 1;
00058 for (int i = 0; i < N; ++i)
00059 f *= gausnorm(x+i,p+2*i);
00060
00061 return f;
00062 }
00063
00064 struct MINUIT2 {
00065 static std::string name() { return "Minuit2"; }
00066 static std::string name2() { return ""; }
00067 };
00068
00069
00070 ROOT::Fit::UnBinData * FillUnBinData(TTree * tree ) {
00071
00072
00073 ROOT::Fit::UnBinData * d = 0;
00074
00075
00076 d = new ROOT::Fit::UnBinData();
00077
00078 unsigned int n = tree->GetEntries();
00079 #ifdef DEBUG
00080 std::cout << "number of unbin data is " << n << " of dim " << N << std::endl;
00081 #endif
00082 d->Initialize(n,N);
00083 TBranch * bx = tree->GetBranch("x");
00084 double vx[N];
00085 bx->SetAddress(vx);
00086 std::vector<double> m(N);
00087 for (int unsigned i = 0; i < n; ++i) {
00088 bx->GetEntry(i);
00089 d->Add(vx);
00090 for (int j = 0; j < N; ++j)
00091 m[j] += vx[j];
00092 }
00093
00094 #ifdef DEBUG
00095 std::cout << "average values of means :\n";
00096 for (int j = 0; j < N; ++j)
00097 std::cout << m[j]/n << " ";
00098 std::cout << "\n";
00099 #endif
00100
00101 delete tree;
00102 tree = 0;
00103 return d;
00104
00105 }
00106
00107
00108
00109
00110 typedef ROOT::Math::IParamMultiFunction Func;
00111 template <class MinType, class T>
00112 int DoUnBinFit(T * tree, Func & func, bool debug = false ) {
00113
00114 ROOT::Fit::UnBinData * d = FillUnBinData(tree );
00115
00116
00117
00118
00119 std::cout << "Fit data size = " << d->Size() << " dimension = " << d->NDim() << std::endl;
00120
00121
00122
00123
00124
00125
00126
00127
00128 ROOT::Fit::Fitter fitter;
00129 fitter.Config().SetMinimizer(MinType::name().c_str(),MinType::name2().c_str());
00130
00131 if (debug)
00132 fitter.Config().MinimizerOptions().SetPrintLevel(3);
00133 else
00134 fitter.Config().MinimizerOptions().SetPrintLevel(0);
00135
00136
00137 fitter.Config().MinimizerOptions().SetTolerance(1);
00138
00139
00140 fitter.Config().MinimizerOptions().SetStrategy(strategy);
00141
00142
00143
00144
00145 fitter.SetFunction(func);
00146
00147
00148
00149 bool ret = fitter.Fit(*d);
00150 if (!ret) {
00151 std::cout << " Fit Failed " << std::endl;
00152 return -1;
00153 }
00154 if (debug)
00155 fitter.Result().Print(std::cout);
00156
00157
00158 double chi2 = 0;
00159 for (int i = 0; i < N; ++i) {
00160 double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) );
00161 chi2 += d*d;
00162 }
00163 double prob = ROOT::Math::chisquared_cdf_c(chi2,N);
00164 int iret = (prob < 1.0E-6) ? -1 : 0;
00165 if (iret != 0) {
00166 std::cout <<"Found difference in fitted values - prob = " << prob << std::endl;
00167 if (!debug) fitter.Result().Print(std::cout);
00168 for (int i = 0; i < N; ++i) {
00169 double d = (truePar[i] - fitter.Result().Value(i) )/ (fitter.Result().Error(i) );
00170 std::cout << "par_" << i << " = " << fitter.Result().Value(i) << " true = " << truePar[i] << " pull = " << d << std::endl;
00171 }
00172
00173 }
00174
00175 delete d;
00176
00177 return iret;
00178
00179 }
00180
00181
00182 template <class MinType>
00183 int DoFit(TTree * tree, Func & func, bool debug = false ) {
00184 return DoUnBinFit<MinType, TTree>(tree, func, debug);
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 template <class MinType, class FitObj>
00196 int FitUsingNewFitter(FitObj * fitobj, Func & func ) {
00197
00198 std::cout << "\n************************************************************\n";
00199 std::cout << "\tFit using new Fit::Fitter " << typeid(*fitobj).name() << std::endl;
00200 std::cout << "\tMinimizer is " << MinType::name() << " " << MinType::name2() << " func dim = " << func.NDim() << std::endl;
00201
00202 int iret = 0;
00203 TStopwatch w; w.Start();
00204
00205 #ifdef DEBUG
00206 std::cout << "initial Parameters " << iniPar << " " << *iniPar << " " << *(iniPar+1) << std::endl;
00207 func.SetParameters(iniPar);
00208 iret |= DoFit<MinType>(fitobj,func,true );
00209
00210 #else
00211 for (int i = 0; i < nfit; ++i) {
00212 func.SetParameters(iniPar);
00213 iret = DoFit<MinType>(fitobj,func, false);
00214 if (iret != 0) {
00215 std::cout << "Fit failed " << std::endl;
00216 break;
00217 }
00218 }
00219 #endif
00220 w.Stop();
00221 std::cout << "\nTime: \t" << w.RealTime() << " , " << w.CpuTime() << std::endl;
00222 std::cout << "\n************************************************************\n";
00223
00224 return iret;
00225 }
00226
00227
00228 int testNdimFit() {
00229
00230
00231 std::cout << "\n\n************************************************************\n";
00232 std::cout << "\t UNBINNED TREE (GAUSSIAN MULTI-DIM) FIT\n";
00233 std::cout << "************************************************************\n";
00234
00235 TTree * t1 = new TTree("t2","a large Tree with gaussian variables");
00236 double x[N];
00237 Int_t ev;
00238 t1->Branch("x",x,branchType.c_str());
00239 t1->Branch("ev",&ev,"ev/I");
00240
00241
00242 for (int j = 0; j < N; ++j) {
00243 double mu = double(j)/10.;
00244 double s = 1.0 + double(j)/10.;
00245 truePar[2*j] = mu;
00246 truePar[2*j+1] = s;
00247 }
00248
00249
00250
00251 TRandom3 r;
00252 for (Int_t i=0;i<NPoints;i++) {
00253 for (int j = 0; j < N; ++j) {
00254 double mu = truePar[2*j];
00255 double s = truePar[2*j+1];
00256 x[j] = r.Gaus(mu,s);
00257 }
00258
00259 ev = i;
00260 t1->Fill();
00261
00262 }
00263
00264
00265
00266 for (int i = 0; i <N; ++i) {
00267 iniPar[2*i] = 0;
00268 iniPar[2*i+1] = 1;
00269 }
00270
00271
00272
00273 ROOT::Math::WrappedParamFunction<> f2(&gausnormN,N,2*N,iniPar);
00274
00275 int iret = 0;
00276 iret |= FitUsingNewFitter<MINUIT2>(t1,f2);
00277
00278 return iret;
00279 }
00280
00281 int main() {
00282 return testNdimFit();
00283 }