1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /* Origin: Alberica Toia, CERN, Alberica.Toia@cern.ch */
18 ///////////////////////////////////////////////////////////////////////////////
20 // class to determine centrality percentiles from 1D distributions //
22 ///////////////////////////////////////////////////////////////////////////////
34 #include <TGraphErrors.h>
37 #include <TStopwatch.h>
39 #include "AliCentralityGlauberFit.h"
42 ClassImp(AliCentralityGlauberFit)
44 //______________________________________________________________________________
45 AliCentralityGlauberFit::AliCentralityGlauberFit(const char *filename) :
78 // standard constructor
80 TFile *f = TFile::Open(filename);
81 fGlauntuple = (TNtuple*) f->Get("nt_Pb_Pb");
82 fGlauntuple->SetBranchAddress("Npart",&fNpart);
83 fGlauntuple->SetBranchAddress("Ncoll",&fNcoll);
84 fGlauntuple->SetBranchAddress("B",&fB);
85 fGlauntuple->SetBranchAddress("tAA",&fTaa);
87 fNBD = new TF1 ("fNBD", AliCentralityGlauberFit::NBDFunc, 0, 100,2);
91 //--------------------------------------------------------------------------------------------------
92 void AliCentralityGlauberFit::SetRangeToFit(Float_t fmultmin, Float_t fmultmax)
100 //--------------------------------------------------------------------------------------------------
101 void AliCentralityGlauberFit::SetGlauberParam(
115 // Set Glauber parameters.
125 fAlphahigh=alphahigh;
131 //--------------------------------------------------------------------------------------------------
132 void AliCentralityGlauberFit::MakeFits(TString infilename)
136 FILE* fTxt = fopen ("parameters.txt","w");
139 // open inrootfile, outrootfile
140 finrootfile = new TFile(infilename);
141 outrootfile = new TFile(foutrootfilename,"RECREATE");
143 // loop over all distribution names
144 std::vector<TString>::const_iterator hni;
145 for(hni=fhistnames.begin(); hni!=fhistnames.end(); hni++) {
146 hDATA = (TH1D*) (finrootfile->Get(*hni));
147 //TList *list = (TList*) (inrootfile->Get("coutput1"));
148 //hDATA = (TH1D*) (list->FindObject(*hni));
149 hDATA->Rebin(fRebinFactor);
150 TH1D *hGLAU = new TH1D("hGLAU","hGLAU",hDATA->GetNbinsX(),0,hDATA->GetNbinsX()*hDATA->GetBinWidth(1));
151 Float_t chi2min = 9999999.0;
152 Float_t alpha_min=-1;
156 Float_t alpha, mu, k, eff, chi2;
158 for (int nalpha=0;nalpha<fNalpha;nalpha++) {
159 alpha = fAlphalow + ((float) nalpha ) * (fAlphahigh - fAlphalow ) / fNalpha;
161 for (int nmu=0; nmu<fNmu; nmu++) {
162 mu = (fMulow*(1-nalpha*0.05) ) + ((float) nmu ) * (fMuhigh - fMulow ) / fNmu;
163 //mu = mulow + ((float) nmu ) * (muhigh - mulow ) / Nmu;
165 for (int nk=0; nk<fNk; nk++) {
166 k = fKlow + ((float) nk ) * (fKhigh - fKlow ) / fNk;
168 for (int neff=0; neff<fNeff; neff++) {
169 eff = fEfflow + ((float) neff) * (fEffhigh - fEfflow) / fNeff;
171 thistGlau = GlauberHisto(mu,k,eff,alpha,hDATA,kFALSE);
172 chi2 = CalculateChi2(hDATA,thistGlau,eff);
173 fprintf(fTxt, "%3.3f %3.3f %3.3f %3.3f %3.3f\n",(float) eff, (float) mu, (float) k, (float) alpha, chi2);
175 if ( chi2 < chi2min ) {
187 thistGlau = GlauberHisto(mu_min,k_min,eff_min,alpha_min,hDATA,kTRUE);
188 hGLAU = (TH1D *) thistGlau->Clone("hGLAU");
189 //hGLAU->SetName( ((TString)hDATA->GetName()).Append(Form("_GLAU_%d_%d_%d_%d",(int)(100*mu_min),(int)(100*k_min),(int)(100*alpha_min),(int)(100*eff_min))));
190 hGLAU->SetName( ((TString)hDATA->GetName()).Append(Form("_GLAU")));
191 hGLAU->SetTitle( ((TString)hDATA->GetName()).Append(Form("_GLAU_%.3f_%.3f_%.3f_%.3f",mu_min,k_min,alpha_min,eff_min)));
193 float mcintegral = hGLAU->Integral(1,hGLAU->GetNbinsX());
194 float scale = (hDATA->Integral(1,hDATA->GetNbinsX())/mcintegral) * ((float) eff_min);
197 fhEffi = GetTriggerEfficiencyFunction(hDATA, hGLAU);
198 SaveHisto(hDATA,hGLAU,fhEffi,outrootfile);
201 std::cout << "chi2 min is " << chi2min << std::endl;
202 std::cout << "fitted " << hGLAU->Integral(hGLAU->FindBin(fMultmin),
203 hGLAU->FindBin(fMultmax))/hGLAU->Integral()
204 << " of the total cross section" << std::endl;
209 // close inrootfile, outrootfile
210 finrootfile->Close();
211 outrootfile->Close();
214 //--------------------------------------------------------------------------------------------------
215 void AliCentralityGlauberFit::MakeFitsMinuitNBD(TString infilename)
217 // Make fits using Minut.
223 // open inrootfile, outrootfile
224 finrootfile = new TFile(infilename);
225 outrootfile = new TFile(foutrootfilename,"RECREATE");
227 // loop over all distribution names
228 std::vector<TString>::const_iterator hni;
229 for(hni=fhistnames.begin(); hni!=fhistnames.end(); hni++) {
232 hDATA = (TH1D*) (finrootfile->Get(*hni));
233 hDATA->Rebin(fRebinFactor);
235 TH1D *hGLAU = new TH1D("hGLAU","hGLAU",hDATA->GetNbinsX(),0,hDATA->GetNbinsX()*hDATA->GetBinWidth(1));
238 if(gMinuit) delete gMinuit;
241 gMinuit->SetFCN(AliCentralityGlauberFit::MinuitFcnNBD);
242 gMinuit->SetObjectFit(this);
244 Double_t arglist[2]={0};
246 if (fUseChi2) arglist[0] = 1; // should be 1 if you want to minimize chi2
247 else arglist[0] = 0.5; // should be 0.5 for ll
248 gMinuit->mnexcm("SET ERR",arglist, 1, ierflg);
252 //gMinuit->Command((TString("SET PRINTOUT ")+long(fVerbosity)).Data());
256 gMinuit->mnparm(0,"alpha", fAlphalow, 0.1, 0.75,1, ierflg);
257 gMinuit->mnparm(1,"mu" , fMulow, 0.2, 1,100, ierflg);
258 gMinuit->mnparm(2,"k" , fKlow, 0.1, 0.5,2.5, ierflg);
259 gMinuit->mnparm(3,"eff" , fEfflow, 0.1, 0.95,1.0, ierflg);
260 } else if (fFastFit == 2) {
261 gMinuit->mnparm(0,"alpha", 0.59, 0.1, 0,1, ierflg);
262 gMinuit->mnparm(1,"mu" , 30.2, 1, 0,0, ierflg);
263 gMinuit->mnparm(2,"k" , 3.875, 0.1, 0,0, ierflg);
264 gMinuit->mnparm(3,"eff" , 0.98947, 0.1, 0,0, ierflg);
268 // arglist[0] = 100000; // max calls
269 // arglist[1] = 0.1; // tolerance
270 // arglist[0] = 50; // max calls
271 // arglist[1] = 1; // tolerance
272 // gMinuit->mnexcm("MIGrad",arglist, 2, ierflg);
273 arglist[0] = 100; // max calls
274 arglist[1] = 0.1; // tolerance
275 gMinuit->mnexcm("SIMPLEX",arglist, 2, ierflg);
276 arglist[0] = 1000; // max calls
277 arglist[1] = 0.1; // tolerance
278 gMinuit->mnexcm("MIGrad",arglist, 2, ierflg);
279 //gMinuit->mnexcm("IMPROVE",arglist, 0, ierflg);
282 AliWarning("Abnormal termination of minimization.");
285 // if(opt.Contains("M")) {
286 // gMinuit->mnexcm("IMPROVE",arglist, 0, ierflg);
288 // if(opt.Contains("E")) {
289 // gMinuit->mnexcm("HESSE",arglist, 0, ierflg);
290 // gMinuit->mnexcm("MINOS",arglist, 0, ierflg);
293 // ______________________ Get chi2 and Fit Status __________
294 Double_t amin,edm,errdef;
295 int nvpar, nparx, icstat;
298 gMinuit->mnstat(amin,edm,errdef,nvpar,nparx,icstat);
299 Double_t chi2min = amin;
300 std::cout << "Fit status " << icstat << std::endl;
302 Double_t alpha_min, mu_min, k_min, eff_min;
303 Double_t alpha_mine, mu_mine, k_mine, eff_mine;
304 gMinuit->GetParameter(0, alpha_min , alpha_mine );
305 gMinuit->GetParameter(1, mu_min , mu_mine );
306 gMinuit->GetParameter(2, k_min , k_mine );
307 gMinuit->GetParameter(3, eff_min , eff_mine );
310 std::cout << "chi2 min is " << chi2min << ", " << alpha_min << ", "<< mu_min<< ", " << k_min << ", " << eff_min << std::endl;
312 thistGlau = GlauberHisto(mu_min,k_min,eff_min,alpha_min,hDATA,kTRUE);
313 hGLAU = (TH1D *) thistGlau->Clone("hGLAU");
314 hGLAU->SetName( ((TString)hDATA->GetName()).Append(Form("_GLAU")));
315 hGLAU->SetTitle( ((TString)hDATA->GetName()).Append(Form("_GLAU_%.3f_%.3f_%.3f_%.3f",mu_min,k_min,alpha_min,eff_min)));
318 std::cout << "fitted " << hGLAU->Integral(hGLAU->FindBin(fMultmin),
319 hGLAU->FindBin(fMultmax))/hGLAU->Integral()
320 << " of the total cross section" << std::endl;
322 float mcintegral = hGLAU->Integral(1,hGLAU->GetNbinsX());
323 float scale = (hDATA->Integral(1,hDATA->GetNbinsX())/mcintegral) * ((float) eff_min);
326 std::cout << "Chi2 final " << CalculateChi2(hDATA,hGLAU,eff_min) << std::endl;
328 fhEffi = GetTriggerEfficiencyFunction(hDATA, hGLAU);
329 SaveHisto(hDATA,hGLAU,fhEffi,outrootfile);
332 // close inrootfile, outrootfile
333 finrootfile->Close();
334 outrootfile->Close();
337 //--------------------------------------------------------------------------------------------------
338 TH1D *AliCentralityGlauberFit::GlauberHisto(Float_t mu, Float_t k, Float_t eff, Float_t alpha,
339 TH1D *hDATA, Bool_t save)
341 // Get Glauber histogram
344 static TStopwatch sw;
346 TH1D *hSample = fFastFit != 2 ? NBDhist(mu,k) : 0;
347 // fNBD->SetParameters(mu,k);
348 static TH1D *h1 = (TH1D*)hDATA->Clone();
350 // h1->SetName(Form("fit_%.3f_%.3f_%.3f_%.3f",mu,k,eff,alpha));
351 TFile *outFile = NULL;
352 TNtuple *ntuple = NULL;
355 outFile = TFile::Open("pippo.root", "RECREATE");
356 ntuple = new TNtuple("gnt", "Glauber ntuple", "Npart:Ncoll:B:tAA:ntot");
359 Int_t nents = 100000;//glau_ntuple->GetEntries();
360 //if(fFastFit > 0 && fFastFit < 2) nents = 10000;
361 // Int_t nents = 100;//glau_ntuple->GetEntries();
362 for (Int_t i=0;i<nents;++i) {
363 fGlauntuple->GetEntry(i);
364 //Int_t n = TMath::Nint(TMath::Power(Npart,alpha));
365 //Int_t n = TMath::Nint(TMath::Power(Ncoll,alpha));
366 Int_t n = alpha * fNpart + (1-alpha) * fNcoll;
368 // ntot=n*fNBD->GetRandom();
371 ntot = n*hSample->GetRandom();
373 else if (fFastFit == 2) {
375 Double_t sigma = k*TMath::Sqrt(n*mu);
376 ntot = gRandom->Gaus(n*mu,sigma);
379 for(Int_t j = 0; j<n; ++j)
380 ntot+=hSample->GetRandom();
381 // ntot+=fNBD->GetRandom();
386 ntuple->Fill(fNpart,fNcoll,fB,fTaa,ntot);
395 if (fFastFit != 2) delete hSample;
400 //--------------------------------------------------------------------------------------------------
401 Float_t AliCentralityGlauberFit::CalculateChi2(TH1D *hDATA, TH1D *thistGlau, Float_t eff)
403 // note that for different values of neff the mc distribution is identical, just re-scaled below
404 // normalize the two histogram
405 // scale MC up but leave data alone - that preserves error bars !!!!
407 int lowchibin = hDATA->FindBin(fMultmin);
408 int highchibin = hDATA->FindBin(fMultmax);
410 float mcintegral = thistGlau->Integral(1,thistGlau->GetNbinsX());
411 float scale = (hDATA->Integral(1,hDATA->GetNbinsX())/mcintegral) * ((float) eff);
412 thistGlau->Scale(scale);
415 //return hDATA->KolmogorovTest(thistGlau,"M");
417 // // calculate the chi2 between MC and real data over some range ????
420 for (int i=lowchibin; i<=highchibin; i++) {
421 if (hDATA->GetBinContent(i) < 1.0) continue;
422 float diff = pow( (thistGlau->GetBinContent(i) - hDATA->GetBinContent(i)) , 2);
423 diff = diff / (pow(hDATA->GetBinError(i) , 2)+pow(thistGlau->GetBinError(i) , 2)); // FIXME squared distance if commented
426 chi2 = chi2 / (highchibin - lowchibin + 1);
429 // "-2 log likelihood ratio(mu;n) = 2[(mu - n) + n ln(n/mu)]"
431 std::cout << "LL" << std::endl;
435 for (int i=lowchibin; i<=highchibin; i++) {
436 // if (thistGlau->GetBinContent(i) < 1) continue;
437 // if (hDATA->GetBinContent(i) < 1) continue;
438 // cout << ll << " " << thistGlau->GetBinContent(i) <<" " << hDATA->GetBinContent(i) << endl;
440 Float_t data = hDATA ->GetBinContent(i);
441 Float_t mc = thistGlau->GetBinContent(i);
442 Int_t idata = TMath::Nint(data);
443 if (mc < 1.e-9) mc = 1.e-9;
444 Float_t fsub = - mc + idata * TMath::Log(mc);
446 //Int_t imc = TMath::Nint(mc);
448 for(Int_t istep = 0; istep < idata; istep++){
450 fobs += TMath::Log(istep);
453 // cout << mc << " " << data << " " << fsub << " " << fobs << endl;
462 //--------------------------------------------------------------------------------------------------
463 TH1D * AliCentralityGlauberFit::GetTriggerEfficiencyFunction(TH1D *hist1, TH1D *hist2)
467 fhEffi = (TH1D*)hist1->Clone("heffi");
468 fhEffi->Divide(hist2);
472 //--------------------------------------------------------------------------------------------------
473 Float_t AliCentralityGlauberFit::GetTriggerEfficiencyIntegral(TH1D *hist1, TH1D *hist2)
476 fEffi = hist1->Integral()/hist2->Integral();
480 //--------------------------------------------------------------------------------------------------
481 void AliCentralityGlauberFit::SaveHisto(TH1D *hist1, TH1D *hist2, TH1D *heffi, TFile *outrootfile)
489 //--------------------------------------------------------------------------------------------------
490 Double_t AliCentralityGlauberFit::NBD(Int_t n, Double_t mu, Double_t k)
493 Double_t ret = TMath::Exp( TMath::LnGamma(n+k) - TMath::LnGamma(k) - TMath::LnGamma(n+1) ) *
494 TMath::Power(mu/(mu+k),n) * TMath::Power(1-mu/(mu+k),k);
498 //--------------------------------------------------------------------------------------------------
499 TH1D *AliCentralityGlauberFit::NBDhist(Double_t mu, Double_t k)
501 TH1D *h = new TH1D("htemp","",100,-0.5,299.5);
502 h->SetName(Form("nbd_%f_%f",mu,k));
504 for (Int_t i=0;i<300;++i) {
505 Double_t val = NBD(i,mu,k);
506 if (val>1e-20) h->Fill(i,val);
511 //--------------------------------------------------------------------------------------------------
512 void AliCentralityGlauberFit::MinuitFcnNBD(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
515 Double_t alpha = par[0];
516 Double_t mu = par[1];
518 Double_t eff = par[3];
519 //Double_t eff = 1;//par[3];
520 if (0) { //avoid warning
525 AliCentralityGlauberFit * obj = (AliCentralityGlauberFit *) gMinuit->GetObjectFit();
527 // static TStopwatch sw;
529 TH1D * thistGlau = obj->GlauberHisto(mu,k,eff,alpha,obj->GetTempHist(),kFALSE);
530 f = obj->CalculateChi2(obj->GetTempHist(),thistGlau,eff);
533 Printf("%f - %f - %f - %f - %f \n",f,alpha,mu,k,eff);
536 //--------------------------------------------------------------------------------------------------
537 Double_t AliCentralityGlauberFit::NBDFunc(Double_t * x, Double_t *par)
540 Double_t mu = par[0];
543 Double_t ret = exp( TMath::LnGamma(n+k) - TMath::LnGamma(k) - TMath::LnGamma(n+1) ) * TMath::Power(mu/(mu+k),n) * TMath::Power(1-mu/(mu+k),k);