14 #include "StMessMgr.h"
15 #include "StNegativeBinomial.h"
16 #include "StNbdFitMaker.h"
30 mMinimumMultiplicityCut = 100.0 ;
33 mDoCentralityDetermination = kTRUE;
44 StNbdFitMaker::~StNbdFitMaker()
46 if(mNBinomial)
delete mNBinomial ;
47 if(mCanvas)
delete mCanvas ;
49 for(Int_t i=0;i<2;i++)
51 if(mCutOff[i])
delete mCutOff[i] ;
53 if(mOneLine)
delete mOneLine ;
55 if(mChi2Graph)
delete mChi2Graph ;
61 LOG_INFO <<
"StNbdFitMaker::DoCentralityDetermination Centrality determination is ON" << endm;
62 mDoCentralityDetermination = kTRUE ;
66 Double_t StNbdFitMaker::GetNormalization(
const TH1& h1,
const TH1& h2,
const Double_t min,
const Double_t max)
const
69 Double_t numerator = 0.0;
70 Double_t denominator = 0.0;
71 const Int_t mulminbin = h1.GetXaxis()->FindBin(min);
72 const Int_t mulmaxbin = h1.GetXaxis()->FindBin(max);
74 for(Int_t mul=mulminbin; mul<mulmaxbin; mul++){
75 const Double_t n1 = h1.GetBinContent(mul+1);
76 const Double_t n1Error = h1.GetBinError(mul+1);
78 if( n1 == 0.0 || n1Error == 0.0 ) continue ;
80 const Double_t n2 = h2.GetBinContent(mul+1);
82 numerator += n1 * n2 / (n1Error*n1Error) ;
83 denominator += n2 * n2 / (n1Error*n1Error) ;
86 const Double_t norm = (denominator!=0.0) ? numerator / denominator : 1.0 ;
88 LOG_INFO << Form(
"StNbdFitMaker::GetNormalization (min, max, norm) = (%5d, %5d, %1.7f)",
89 static_cast<Int_t>(min), static_cast<Int_t>(max), norm)
96 Double_t StNbdFitMaker::CalculateChi2(
const TH1& hdata,
const TH1& hfunc,
const Double_t minimumMultiplicityCut)
101 Double_t chi2 = 0.0 ;
102 for(Int_t ix=0; ix<hdata.GetNbinsX(); ix++){
104 const Double_t mult = hdata.GetBinCenter(ix+1);
105 if( mult < minimumMultiplicityCut ) continue ;
108 const Double_t dataError = hdata.GetBinError(ix+1);
109 if( dataError == 0.0 ) continue ;
111 const Double_t simError = hfunc.GetBinError(ix+1);
112 if( simError == 0.0 ) continue ;
114 const Double_t totError = TMath::Power((dataError*dataError + simError*simError),0.5);
117 const Double_t
data = hdata.GetBinContent(ix+1);
118 const Double_t func = hfunc.GetBinContent(ix+1);
119 const Double_t delta = (data - func)/totError ;
120 chi2 += delta*delta ;
124 LOG_INFO << Form(
"StNbdFitMaker::calculateChi2 M > %5d: (npp, k) = (%1.5f, %1.5f) chi2/ndata = %1.3f/%5d = %1.3f",
125 static_cast<Int_t>(minimumMultiplicityCut), mNBinomial->GetNpp(), mNBinomial->
GetK(), chi2, mNData, chi2/
static_cast<Double_t
>(mNData))
132 void StNbdFitMaker::CalculateCentrality(
const TH1& hdata,
const TH1& hmc)
const
139 const UInt_t ncent = 16 ;
140 Int_t centBin[2][3][ncent];
142 for(UInt_t i=0; i<2; i++) {
146 if ( i == 0 ) LOG_INFO <<
"StNbdFitMaker::CalculateCentrality (1) Centrality determination from peripheral to central" << endm;
147 if ( i == 1 ) LOG_INFO <<
"StNbdFitMaker::CalculateCentrality (2) Centrality determination from central to peripheral" << endm;
150 Double_t centralityCut[ncent] ;
151 Double_t centralityMin[ncent] ;
152 Double_t centralityMax[ncent] ;
154 for(UInt_t ic=0; ic<ncent; ic++) {
155 const Double_t sign = (i==0) ? -1.0 : 1.0 ;
156 const Double_t centStep = 0.05 ;
157 const Double_t centCutStart = (i==0) ? 0.80 : 0.05 ;
158 const Double_t centMinStart = (i==0) ? 75.0 : 0.0 ;
160 centralityCut[ic] = centCutStart + sign*centStep * ic ;
161 centralityMin[ic] = centMinStart + sign*centStep * 100.0 * ic ;
162 centralityMax[ic] = (centMinStart + centStep*100.0) + sign*centStep * 100.0 * ic ;
165 LOG_INFO << Form(
"StNbdFitMaker::CalculateCentrality Centrality: %1.0f-%1.0f %%, cut = %1.2f",
166 TMath::Abs(centralityMin[ic]), TMath::Abs(centralityMax[ic]), centralityCut[ic])
172 const Double_t nevent = hmc.Integral() ;
173 for(Int_t it=0; it<3; it++){
174 Double_t scale = 1.0 ;
175 if( it == 1 ) scale = 0.95 ;
176 if( it == 2 ) scale = 1.05 ;
179 const Int_t nbin = hmc.GetNbinsX() ;
205 Double_t distance = 1000.0;
206 for(Int_t im=0; im<nbin; im++){
207 const Int_t Mint = (i==0) ? im : nbin-im ;
208 Double_t count = 0.0;
209 if( (i==0 && bin>11) || (i!=0 && bin<4) ) count = (i==0) ? hdata.GetBinContent(im+1) : hdata.GetBinContent(nbin-im);
210 else count = (i==0) ? hmc.GetBinContent(im+1) : hmc.GetBinContent(nbin-im) ;
211 if( count == 0.0 ) continue ;
214 const Double_t fraction = sum / nevent ;
215 const Double_t fCentBinCut = centralityCut[bin] * scale;
216 const Double_t R = (i==0) ? (1.0 - fraction) : fraction ;
217 Double_t thisdistance = TMath::Abs(R - fCentBinCut );
219 const Bool_t isCentOk = (thisdistance > distance) ;
220 distance=thisdistance;
222 if( isCentOk && bin < ncent ){
223 cout << Form(
"%2.2f - %2.2f (%%) : M > %4d (im=%3d, M=%1.1f, bin=%4d) (sum, total, fraction>cut) = (%1.3f, %1.3f, %1.3f>%1.3f)",
224 TMath::Abs(centralityMin[bin]*scale), TMath::Abs(centralityMax[bin]*scale), Mint, im, (Double_t)Mint, bin, sum, nevent, R, fCentBinCut) << endl;
225 centBin[i][it][bin] = (Double_t)Mint ;
235 for(UInt_t ic=0; ic<ncent; ic++) {
236 LOG_INFO << Form(
" mMultiplicityCut[0].push_back( %3d ); mCentralityMin[0].push_back( %2.1f ); mCentralityMax[0].push_back( %2.1f );",
237 (Int_t)centBin[1][0][ic], 5.0*ic, 5.0*(ic+1)
242 for(UInt_t ic=0; ic<ncent; ic++) {
243 LOG_INFO << Form(
" mMultiplicityCut[1].push_back( %3d ); mMultiplicityCut[2].push_back( %3d );",
244 (Int_t)centBin[1][1][ic], (Int_t)centBin[1][2][ic]
252 const Double_t efficiency,
const Double_t triggerbias,
const Bool_t isConstEfficiency)
254 if(mNBinomial)
delete mNBinomial ;
256 mNBinomial =
new StNegativeBinomial(npp, k, x, efficiency, triggerbias, isConstEfficiency);
262 mMinimumMultiplicityCut = cut ;
263 LOG_INFO <<
"StNbdFitMaker::setMinimumMultiplicityCut Set low multiplicity cut off : M > " << cut << endm;
270 TFile* inputData = TFile::Open(data);
271 if(!inputData || !inputData->IsOpen()){
272 Error(
"StNbdFitMaker::readData",
"can't open %s", data);
275 LOG_INFO <<
"StNbdFitMaker::readData open Data file: " << inputData->GetName() << endm;
280 mhRefMult = (TH1D*) inputData->Get(dataHistogramName);
290 Error(
"StNbdFitMaker::readData",
"hRefMult doesn't exist");
294 mhRefMult->SetLineColor(1);
297 const Int_t nbinsx = mhRefMult->GetNbinsX() ;
298 const Double_t xmin = mhRefMult->GetXaxis()->GetXmin() ;
299 const Double_t xmax = mhRefMult->GetXaxis()->GetXmax() ;
300 mhRefMultSim =
new TH1D(
"hRefMultSim",
"", nbinsx, xmin, xmax);
301 mhRefMultSim->SetLineColor(2);
305 mhRefMultSim->Sumw2();
308 TFile* inputGlauber = TFile::Open(glauber);
309 if(!inputGlauber || !inputGlauber->IsOpen())
311 Error(
"StNbdFitMaker::readData",
"can't open %s", glauber);
314 LOG_INFO <<
"StNbdFitMaker::readData open Glauber file: " << inputGlauber->GetName() << endm;
316 mhNcoll_Npart = (TH2D*) inputGlauber->Get(
"hNcoll_Npart");
319 Error(
"StNbdFitMaker::readData",
"hNcoll_Npart doesn't exist");
320 assert(mhNcoll_Npart);
328 gStyle->SetOptStat(0);
335 Error(
"StNbdFitMaker::Fit",
"hRefMult doesn't exist");
341 Error(
"StNbdFitMaker::Fit",
"hNcoll_Npart doesn't exist");
342 assert(mhNcoll_Npart);
345 mhRefMultSim->Reset();
348 while( ievent < nevents )
350 Double_t npart, ncoll;
351 mhNcoll_Npart->GetRandom2(npart, ncoll);
352 const Bool_t isNpartNcollOk = (npart>=2 && ncoll>=1) ;
353 if ( !isNpartNcollOk ) continue ;
355 const Int_t multiplicity = mNBinomial->
GetMultiplicity(npart, static_cast<Int_t>(ncoll));
356 mhRefMultSim->Fill(multiplicity);
358 if( ievent % (nevents/10) == 0 )
360 LOG_INFO << Form(
"StNbdFitMaker::Fit ievent=%10d (npart, ncoll, mult) = (%10d, %10d, %10d)",
361 ievent, (Int_t)npart, (Int_t)ncoll, multiplicity)
369 const Double_t norm = GetNormalization(*mhRefMult, *mhRefMultSim, mMinimumMultiplicityCut, mhRefMult->GetXaxis()->GetXmax());
371 mhRefMultSim->Scale(norm);
374 const Double_t chi2 = CalculateChi2(*mhRefMult, *mhRefMultSim, mMinimumMultiplicityCut);
379 if(mChi2Graph)
delete mChi2Graph ;
380 mChi2Graph =
new TGraph();
381 mChi2Graph->SetPoint(0, 0, chi2);
382 mChi2Graph->SetPoint(1, 1, mNData - 2);
383 mChi2Graph->SetPoint(2, 2, chi2/(mNData-2.0));
388 mhRefMult->SetMinimum(0.1);
389 mhRefMult->SetMaximum(mhRefMult->GetMaximum()*10.0);
391 mhRefMultSim->SetXTitle(
"Refmult (MC)");
392 mhRefMultSim->SetYTitle(
"Count");
393 mhRefMultSim->SetTitle(Form(
"npp=%1.2f, k=%1.2f, x=%1.2f",
394 mNBinomial->GetNpp(), mNBinomial->
GetK(), mNBinomial->
GetX()));
396 if(mCanvas)
delete mCanvas ;
397 mCanvas =
new TCanvas(
"c1",
"c1", 1200, 500);
398 mCanvas->Divide(2, 1);
400 mCanvas->GetPad(1)->SetLogy(1);
402 mhRefMult->Draw(
"h");
403 mhRefMultSim->Draw(
"hsame");
406 if(mCutOff[0])
delete mCutOff[0] ;
407 mCutOff[0] =
new TLine( mMinimumMultiplicityCut, mhRefMult->GetMinimum(), mMinimumMultiplicityCut, mhRefMult->GetMaximum());
408 mCutOff[0]->SetLineColor(4);
409 mCutOff[0]->SetLineStyle(2);
414 TH1* hRatio = (TH1D*) mhRefMultSim->Clone();
415 hRatio->SetName(
"hRatio");
416 hRatio->Divide(mhRefMult);
417 hRatio->SetYTitle(
"MC/data");
419 hRatio->SetMinimum(0);
420 hRatio->SetMaximum(2);
423 if(mOneLine)
delete mOneLine ;
424 mOneLine =
new TLine(hRatio->GetXaxis()->GetXmin(), 1.0, hRatio->GetXaxis()->GetXmax(), 1.0);
425 mOneLine->SetLineColor(4);
426 mOneLine->SetLineStyle(2);
429 if(mCutOff[1])
delete mCutOff[1] ;
430 mCutOff[1] =
new TLine( mMinimumMultiplicityCut, hRatio->GetMinimum(), mMinimumMultiplicityCut, hRatio->GetMaximum());
431 mCutOff[1]->SetLineColor(4);
432 mCutOff[1]->SetLineStyle(2);
441 if ( mDoCentralityDetermination )
443 CalculateCentrality(*mhRefMult, *mhRefMultSim) ;
451 if(!outputFileName.IsWhitespace())
453 LOG_INFO <<
"StNbdFitMaker::Fit Write output ROOT file : " << outputFileName << endm;
454 TFile* output = TFile::Open(outputFileName,
"recreate");
456 mhRefMultSim->Write();
466 const Int_t nppbin,
const Double_t nppmin,
const Double_t nppmax,
467 const Int_t kbin,
const Double_t kmin,
const Double_t kmax,
468 const Int_t xbin,
const Double_t xmin,
const Double_t xmax,
471 const Double_t efficiency,
472 const Double_t triggerbias,
const Bool_t isConstEfficiency
475 TH3* hChi2 =
new TH3D(
"hChi2",
"#chi^{2}/NDF in (npp, k, x) space",
476 nppbin, nppmin, nppmax, kbin, kmin, kmax, xbin, xmin, xmax);
477 hChi2->SetXTitle(
"n_{pp}");
478 hChi2->SetYTitle(
"k");
479 hChi2->SetZTitle(
"x");
481 const Double_t nppstep = (nppbin==1) ? 0 : (nppmax-nppmin)/
static_cast<Double_t
>(nppbin-1) ;
482 const Double_t kstep = (kbin==1) ? 0 : (kmax-kmin)/
static_cast<Double_t
>(kbin-1) ;
483 const Double_t xstep = (xbin==1) ? 0 : (xmax-xmin)/
static_cast<Double_t
>(xbin-1) ;
485 for(Int_t ix=0; ix<nppbin; ix++){
486 const Double_t npp = nppmin + nppstep*ix ;
488 for(Int_t iy=0; iy<kbin; iy++){
489 const Double_t k = kmin + kstep*iy ;
490 LOG_INFO << Form(
"StNbdFitMaker::Scan Fitting for (npp, k) = (%1.3f, %1.3f) ...", npp, k) << endm;
492 for(Int_t iz=0; iz<xbin; iz++){
493 const Double_t x = xmin + xstep*iz ;
495 SetParameters(npp, k, x, efficiency, triggerbias, isConstEfficiency);
499 const TString fileforratio = Form(
"RatioChi2Files/Ratio_npp%1.3f_k%1.3f_x%1.3f_eff%1.3f.root", npp, k, x, efficiency);
502 Fit(nevents, fileforratio);
508 hChi2->SetBinContent(ix+1, iy+1, iz+1, mChi2Graph->GetY()[2]);
510 LOG_INFO << Form(
"StNbdFitMaker::Scan Fitting for (npp, k, x, d, chi2/ndf) = (%1.3f, %1.3f, %1.3f, %1.3f, %1.3f/%3d=%1.3f) ...",
511 npp, k, x, efficiency, mChi2Graph->GetY()[0], (Int_t)mChi2Graph->GetY()[1], mChi2Graph->GetY()[2])
522 const Char_t* fileName(Form(
"RatioChi2Files/chi2_nevents%d_npp%1.3f-%1.3f_k%1.3f-%1.3f_x%1.3f_%1.3f_eff%1.3f.root",
523 nevents, nppmin, nppmax, kmin, kmax, xmin, xmax, efficiency));
524 TFile* outputFile = TFile::Open(fileName,
"recreate");
TGraph * Fit(const Int_t nevents=1000, const TString outputFileName="")
Int_t Scan(const Int_t nevents, const Int_t nppbin, const Double_t nppmin, const Double_t nppmax, const Int_t kbin, const Double_t kmin, const Double_t kmax, const Int_t xbin, const Double_t xmin, const Double_t xmax, const Double_t efficiency=1.0, const Double_t triggerbias=1.0, const Bool_t isConstEfficiency=kTRUE)
Find minimum chi2/NDF in (npp, k, efficiency) space.
void SetParameters(const Double_t npp, const Double_t k, const Double_t x, const Double_t efficiency, const Double_t triggerbias, const Bool_t isConstEfficiency)
Set parameters.
void SetMinimumMultiplicityCut(const Double_t cut)
Set minimum multiplicity cuts to avoid inefficiency (default is M>50)
void DoCentralityDetermination()
Default destructor.
void ReadData(const Char_t *data, const Char_t *glauber, const Char_t *dataHistogramName="hRefMultTpc")
Read real data and glauber ROOT files.
Double_t GetK() const
Get npp parameter.
Int_t GetMultiplicity(const Double_t npart, const Double_t ncoll) const
Get multiplcity by convoluting NBD.
Double_t GetX() const
Get k parameter.