Skip to content

Commit 631beb7

Browse files
committed
Add code for glauber fits
1 parent a0db63a commit 631beb7

File tree

5 files changed

+644
-0
lines changed

5 files changed

+644
-0
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Multiplicity/centrality tools in O2/O2Physics
2+
3+
This directory serves to aggregate all files necessary for multiplicity
4+
and centrality calibration going from pp to Pb-Pb. It offers functionality
5+
to perform simple slicing in percentiles, such as what is done in
6+
proton-proton collisions, as well as the Glauber + analytical NBD fitter
7+
used to perform anchoring and hadronic event distribution estimates in
8+
nucleus-nucleus collisions.
9+
10+
## Files
11+
* `README.md` this readme
12+
* `CMakeLists.txt` definition of source files that need compiling
13+
* `multCalibrator.cxx/h` a class to do percentile slicing of a given histogram. Used for all systems.
14+
* `multMCCalibrator.cxx/h` a class to perform data-to-mc matching of average Nch.
15+
* `multGlauberNBDFitter.cxx/h` a class to do glauber fits.
16+
* `multModule.h` a class to perform calculations of multiplicity and centrality tables for analysis. Meant to be used inside the main core service wagon 'multcenttable'.
17+
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Example multiplicity calibration macros
2+
3+
You will find some example macros in this directory that will allow for the calculation of a glauber fit and the corresponding calibration histograms.
4+
5+
A simplified description of the procedure necessary to generate a
6+
Glauber + NBD fit to a certain histogram is described below.
7+
8+
## Performing a Glauber + NBD fit
9+
10+
### First step: calculation of Glauber MC sample
11+
12+
The Glauber + NBD model assumes that the multiplicity / amplitude
13+
distribution that one intends to fit can be described as coming
14+
from a certain number N_{ancestor} of particle-emitting sources called 'ancestors'. Each ancestor is assumed to produce particles
15+
according to a negative binominal distribution. Further,
16+
the number of ancestors is assumed to be related to the basic
17+
glauber quantities N_{part} and N_{coll} via the formula:
18+
19+
N_{ancestor} = f * N_{part} + (1-f) N_{coll}
20+
21+
Usually, the value f is fixed at 0.8, and thus the range of
22+
N_{ancestors} is typically 0-700 in Pb-Pb collisions.
23+
24+
In order to allow for Glauber + NBD fitting, the correlation of
25+
(N_{part}, N_{coll}) needs to be known. For that purpose,
26+
a tree of Glauber MC needs to be generated using TGlauberMC using the relevant nuclei, which also involves choosing an appropriate nuclear profile.
27+
28+
Once TGlauberMC has been used to produce a tree with N_{part} and
29+
N_{coll} values, their correlation needs to be saved to a 2D histogram that serves as input to the Glauber + NBD fitter used in
30+
O2/O2Physics. This is done using the macro called `saveCorrelation.C` contained in this directory, which produces a file named `baseHistos.root`. The file `saveCorrelation.C` serves as
31+
an example for the Pb-Pb case and minor adaptation may be needed
32+
in case other nuclei are to be used.
33+
34+
### Second step: execution of Glauber + NBD fitter
35+
36+
The fitting procedure is done via the macro ``. Because
37+
the numerical fitting utilizes a convolution of a N_{ancestor}
38+
distribution and NBD distributions, it will not be as fast
39+
as typical one-dimensional fits: typical times of 10-100 seconds
40+
are not unusual. The macro will produce an output file
41+
that contains:
42+
43+
* the original fitted histogram
44+
* the actual glauber fit distribution, plotted all the way
45+
to zero multiplicity
46+
47+
This output can then be used to extract percentiles.
48+
49+
### Third step: calculation of percentile boundaries
50+
51+
Once both the data and glauber fit distributions are known,
52+
the next step is to create a 'stitched' data/glauber distribution in
53+
which the distribution at low multiplicities follows
54+
the glauber fit and the distribution at higher multiplicities
55+
follows the data. The multiplicity value in which the switch from
56+
glauber to data takes place is called 'anchor point'.
57+
58+
Because of the fact that this 'stitching' procedure may need to be tuned and the actual glauber fit is slow, the stitching is done
59+
in a separate macro called `runCalibration.C`. It is provided
60+
in this directory as well and it is the third and last step in calculating percentile boundaries. The macro will printout some
61+
key boundaries as well as save an output file with the calibration.
62+
63+
*Bonus*: at the stage in which the glauber fit has been done
64+
and all information is available, a de-convolution process
65+
can be used to calculate the average N_{part} and N_{coll}
66+
in centrality slices. This functionality is also provided
67+
in O2Physics as part of the `multGlauberNBDFitter` and the
68+
`runCalibration.C` macro can optionally also perform that
69+
deconvolution. *Warning*: this procedure might take a mooment.
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
void runCalibration( TString lInputFileName = "results/AR_544122_glauberNBD_ancestorMode2_hFT0C_BCs.root", double anchorPointPercentage = 90.0, double matchRange = 200.0, bool doNpartNcoll = false){
2+
TFile *file = new TFile(lInputFileName.Data(), "READ");
3+
file->ls();
4+
5+
TH1F *hData = (TH1F*) file->Get("hV0MUltraFine");
6+
TH1F *hGlauberParameters = (TH1F*) file->Get("hGlauberParameters");
7+
TH1F *hGlauberFitRange = (TH1F*) file->Get("hGlauberFitRange");
8+
hData->SetName("hData");
9+
TH1F *hStitched = (TH1F*) hData->Clone("hStitched");
10+
TH1F *hFit = (TH1F*) file->Get("hGlauber");
11+
12+
TCanvas *c1 = new TCanvas("c1", "", 800, 600);
13+
c1->SetLeftMargin(0.17);
14+
c1->SetBottomMargin(0.17);
15+
c1->SetRightMargin(0.15);
16+
c1->SetTopMargin(0.05);
17+
c1->SetTicks(1,1);
18+
c1->SetLogz();
19+
c1->SetFrameFillStyle(0);
20+
c1->SetFillStyle(0);
21+
22+
23+
cout<<"Data bin width: "<<hData->GetBinWidth(1)<<endl;
24+
cout<<"Fit bin width: "<<hFit->GetBinWidth(1)<<endl;
25+
cout<<"Match range to use: "<<matchRange<<endl;
26+
27+
//____________________________________________
28+
double anchorPointFraction = anchorPointPercentage/100.f;
29+
double anchorPoint = -1; // the anchor point value in raw
30+
31+
//____________________________________________
32+
// doing partial integration up to certain point for finding anchor point bin
33+
for(int ii=1; ii<hData->GetNbinsX()+1; ii++){
34+
// renormalize data curve
35+
int bin1 = ii+1;
36+
int bin2 = hData->FindBin( hData->GetBinLowEdge(ii+1) + matchRange + 1e-3 );
37+
double matchRangeData = hData -> Integral( bin1, bin2);
38+
double matchRangeFit = hFit -> Integral( bin1, bin2);
39+
40+
// rescale fit to match in the vicinity of the region we're at
41+
hFit->Scale(matchRangeData/matchRangeFit);
42+
43+
double integralFit = hFit->Integral(1,ii);
44+
double integralData = hData->Integral(ii+1,hData->GetNbinsX()+1);
45+
double integralAll = integralFit+integralData;
46+
47+
cout<<"at bin #"<<ii<<", integrated up to "<<hData->GetBinLowEdge(ii+1)<<" fraction above this value is: "<<integralData/integralAll<<endl;
48+
anchorPoint = hData->GetBinLowEdge(ii+1);
49+
50+
if(integralData/integralAll<anchorPointFraction) break;
51+
}
52+
53+
//____________________________________________
54+
for(int ii=1; ii<hData->GetNbinsX()+1; ii++){
55+
// renormalize data curve
56+
if( hData->GetBinCenter(ii) < anchorPoint) hStitched->SetBinContent(ii, hFit->GetBinContent(ii));
57+
}
58+
59+
60+
cout<<"Anchor point determined to be: "<<anchorPoint<<endl;
61+
cout<<"Preparing stitched histogram ... "<<endl;
62+
63+
hFit->SetLineColor(kRed);
64+
hStitched->SetLineColor(kBlue);
65+
66+
hData->GetYaxis()->SetTitleSize(0.055);
67+
hData->GetXaxis()->SetTitleSize(0.055);
68+
hData->GetYaxis()->SetLabelSize(0.04);
69+
hData->GetXaxis()->SetLabelSize(0.04);
70+
hData->SetTitle("");
71+
hData->Draw("hist");
72+
hFit->Draw("hist same");
73+
hStitched->Draw("hist same");
74+
75+
//All fine, let's try the calibrator
76+
multCalibrator *lCalib = new multCalibrator("lCalib");
77+
lCalib->SetAnchorPointPercentage(100.0f);
78+
lCalib->SetAnchorPointRaw(-1e-6);
79+
80+
//Set standard Pb-Pb boundaries
81+
lCalib->SetStandardOnePercentBoundaries();
82+
83+
TString calibFileName = lInputFileName.Data();
84+
calibFileName.ReplaceAll("glauberNBD", "calibration");
85+
TFile *fileCalib = new TFile(calibFileName.Data(), "RECREATE");
86+
87+
TH1F *hCalib = lCalib->GetCalibrationHistogram(hStitched, "hCalib");
88+
89+
TCanvas *c2 = new TCanvas("c2", "", 800, 600);
90+
c2->SetLeftMargin(0.17);
91+
c2->SetBottomMargin(0.17);
92+
c2->SetRightMargin(0.15);
93+
c2->SetTopMargin(0.05);
94+
c2->SetTicks(1,1);
95+
// c2->SetLogz();
96+
c2->SetFrameFillStyle(0);
97+
c2->SetFillStyle(0);
98+
99+
hCalib->GetYaxis()->SetTitleSize(0.055);
100+
hCalib->GetXaxis()->SetTitleSize(0.055);
101+
hCalib->GetYaxis()->SetLabelSize(0.04);
102+
hCalib->GetXaxis()->SetLabelSize(0.04);
103+
hCalib->SetTitle("");
104+
hCalib->Draw();
105+
106+
107+
fileCalib->cd();
108+
109+
hData->Write();
110+
hCalib->Write();
111+
hStitched->Write();
112+
hFit->Write();
113+
114+
if(doNpartNcoll){
115+
cout<<"Will now attempt to calculate % -> Np, Nc map..."<<endl;
116+
117+
TProfile *hProfileNpart = new TProfile("hProfileNpart", "", 100, 0, 100);
118+
TProfile *hProfileNcoll = new TProfile("hProfileNcoll", "", 100, 0, 100);
119+
TH2F *h2dNpart = new TH2F("h2dNpart", "", 100, 0, 100, 500, -0.5f, 499.5f);
120+
TH2F *h2dNcoll = new TH2F("h2dNcoll", "", 100, 0, 100, 3000, -0.5f, 2999.5);
121+
122+
// Replay
123+
multGlauberNBDFitter *g = new multGlauberNBDFitter("lglau");
124+
TF1 *fitfunc = g->GetGlauberNBD();
125+
126+
//Step 1: open the (Npart, Ncoll) pair information, provide
127+
TFile *fbasefile = new TFile("basehistos.root","READ");
128+
TH2D *hNpNc = (TH2D*) fbasefile->Get("hNpNc");
129+
g->SetNpartNcollCorrelation(hNpNc);
130+
g->InitializeNpNc();
131+
132+
fitfunc->SetParameter(0, hGlauberParameters->GetBinContent(1));
133+
fitfunc->SetParameter(1, hGlauberParameters->GetBinContent(2));
134+
fitfunc->SetParameter(2, hGlauberParameters->GetBinContent(3));
135+
fitfunc->SetParameter(3, hGlauberParameters->GetBinContent(4));
136+
fitfunc->SetParameter(4, hGlauberParameters->GetBinContent(5));
137+
138+
Double_t lMax = hData->GetBinLowEdge( hData->GetNbinsX() + 1);
139+
140+
// uncomment if Np Nc needed -> Warning, slow!
141+
g->CalculateAvNpNc( hProfileNpart, hProfileNcoll, h2dNpart, h2dNcoll, hCalib, 0, lMax );
142+
143+
hProfileNpart->Write();
144+
hProfileNcoll->Write();
145+
h2dNpart->Write();
146+
h2dNcoll->Write();
147+
}
148+
149+
fileCalib->Write();
150+
}

0 commit comments

Comments
 (0)