Skip to content

Commit 8ea5af5

Browse files
Merge branch 'AliceO2Group:master' into master
2 parents 90de9a8 + 10b44ec commit 8ea5af5

File tree

103 files changed

+10922
-1504
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+10922
-1504
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: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
//
12+
/// \file saveCorrelation.C
13+
/// \brief
14+
/// \author ALICE
15+
16+
#include <iostream>
17+
18+
/// @brief function to calibrate centrality
19+
/// @param lInputFileName name of input file.
20+
/// @param anchorPointPercentage anchor point percentage to use
21+
/// @param matchRange width of region in which data/glauber matching is to be done in rolling anchoring test
22+
/// @param doNpartNcoll wether or not to attempt calculating Npart, Ncoll in centrality bins
23+
void runCalibration(TString lInputFileName = "results/AR_544122_glauberNBD_ancestorMode2_hFT0C_BCs.root", double anchorPointPercentage = 90.0, double matchRange = 200.0, bool doNpartNcoll = false)
24+
{
25+
TFile* file = new TFile(lInputFileName.Data(), "READ");
26+
file->ls();
27+
28+
TH1F* hData = (TH1F*)file->Get("hV0MUltraFine");
29+
TH1F* hGlauberParameters = (TH1F*)file->Get("hGlauberParameters");
30+
TH1F* hGlauberFitRange = (TH1F*)file->Get("hGlauberFitRange");
31+
hData->SetName("hData");
32+
TH1F* hStitched = (TH1F*)hData->Clone("hStitched");
33+
TH1F* hFit = (TH1F*)file->Get("hGlauber");
34+
35+
TCanvas* c1 = new TCanvas("c1", "", 800, 600);
36+
c1->SetLeftMargin(0.17);
37+
c1->SetBottomMargin(0.17);
38+
c1->SetRightMargin(0.15);
39+
c1->SetTopMargin(0.05);
40+
c1->SetTicks(1, 1);
41+
c1->SetLogz();
42+
c1->SetFrameFillStyle(0);
43+
c1->SetFillStyle(0);
44+
45+
cout << "Data bin width: " << hData->GetBinWidth(1) << endl;
46+
cout << "Fit bin width: " << hFit->GetBinWidth(1) << endl;
47+
cout << "Match range to use: " << matchRange << endl;
48+
49+
//____________________________________________
50+
double anchorPointFraction = anchorPointPercentage / 100.f;
51+
double anchorPoint = -1; // the anchor point value in raw
52+
53+
//____________________________________________
54+
// doing partial integration up to certain point for finding anchor point bin
55+
for (int ii = 1; ii < hData->GetNbinsX() + 1; ii++) {
56+
// renormalize data curve
57+
int bin1 = ii + 1;
58+
int bin2 = hData->FindBin(hData->GetBinLowEdge(ii + 1) + matchRange + 1e-3);
59+
double matchRangeData = hData->Integral(bin1, bin2);
60+
double matchRangeFit = hFit->Integral(bin1, bin2);
61+
62+
// rescale fit to match in the vicinity of the region we're at
63+
hFit->Scale(matchRangeData / matchRangeFit);
64+
65+
double integralFit = hFit->Integral(1, ii);
66+
double integralData = hData->Integral(ii + 1, hData->GetNbinsX() + 1);
67+
double integralAll = integralFit + integralData;
68+
69+
cout << "at bin #" << ii << ", integrated up to " << hData->GetBinLowEdge(ii + 1) << " fraction above this value is: " << integralData / integralAll << endl;
70+
anchorPoint = hData->GetBinLowEdge(ii + 1);
71+
72+
if (integralData / integralAll < anchorPointFraction)
73+
break;
74+
}
75+
76+
//____________________________________________
77+
for (int ii = 1; ii < hData->GetNbinsX() + 1; ii++) {
78+
// renormalize data curve
79+
if (hData->GetBinCenter(ii) < anchorPoint)
80+
hStitched->SetBinContent(ii, hFit->GetBinContent(ii));
81+
}
82+
83+
cout << "Anchor point determined to be: " << anchorPoint << endl;
84+
cout << "Preparing stitched histogram ... " << endl;
85+
86+
hFit->SetLineColor(kRed);
87+
hStitched->SetLineColor(kBlue);
88+
89+
hData->GetYaxis()->SetTitleSize(0.055);
90+
hData->GetXaxis()->SetTitleSize(0.055);
91+
hData->GetYaxis()->SetLabelSize(0.04);
92+
hData->GetXaxis()->SetLabelSize(0.04);
93+
hData->SetTitle("");
94+
hData->Draw("hist");
95+
hFit->Draw("hist same");
96+
hStitched->Draw("hist same");
97+
98+
// All fine, let's try the calibrator
99+
multCalibrator* lCalib = new multCalibrator("lCalib");
100+
lCalib->SetAnchorPointPercentage(100.0f);
101+
lCalib->SetAnchorPointRaw(-1e-6);
102+
103+
// Set standard Pb-Pb boundaries
104+
lCalib->SetStandardOnePercentBoundaries();
105+
106+
TString calibFileName = lInputFileName.Data();
107+
calibFileName.ReplaceAll("glauberNBD", "calibration");
108+
TFile* fileCalib = new TFile(calibFileName.Data(), "RECREATE");
109+
110+
TH1F* hCalib = lCalib->GetCalibrationHistogram(hStitched, "hCalib");
111+
112+
TCanvas* c2 = new TCanvas("c2", "", 800, 600);
113+
c2->SetLeftMargin(0.17);
114+
c2->SetBottomMargin(0.17);
115+
c2->SetRightMargin(0.15);
116+
c2->SetTopMargin(0.05);
117+
c2->SetTicks(1, 1);
118+
// c2->SetLogz();
119+
c2->SetFrameFillStyle(0);
120+
c2->SetFillStyle(0);
121+
122+
hCalib->GetYaxis()->SetTitleSize(0.055);
123+
hCalib->GetXaxis()->SetTitleSize(0.055);
124+
hCalib->GetYaxis()->SetLabelSize(0.04);
125+
hCalib->GetXaxis()->SetLabelSize(0.04);
126+
hCalib->SetTitle("");
127+
hCalib->Draw();
128+
129+
fileCalib->cd();
130+
131+
hData->Write();
132+
hCalib->Write();
133+
hStitched->Write();
134+
hFit->Write();
135+
136+
if (doNpartNcoll) {
137+
cout << "Will now attempt to calculate % -> Np, Nc map..." << endl;
138+
139+
TProfile* hProfileNpart = new TProfile("hProfileNpart", "", 100, 0, 100);
140+
TProfile* hProfileNcoll = new TProfile("hProfileNcoll", "", 100, 0, 100);
141+
TH2F* h2dNpart = new TH2F("h2dNpart", "", 100, 0, 100, 500, -0.5f, 499.5f);
142+
TH2F* h2dNcoll = new TH2F("h2dNcoll", "", 100, 0, 100, 3000, -0.5f, 2999.5);
143+
144+
// Replay
145+
multGlauberNBDFitter* g = new multGlauberNBDFitter("lglau");
146+
TF1* fitfunc = g->GetGlauberNBD();
147+
148+
// Step 1: open the (Npart, Ncoll) pair information, provide
149+
TFile* fbasefile = new TFile("basehistos.root", "READ");
150+
TH2D* hNpNc = (TH2D*)fbasefile->Get("hNpNc");
151+
g->SetNpartNcollCorrelation(hNpNc);
152+
g->InitializeNpNc();
153+
154+
fitfunc->SetParameter(0, hGlauberParameters->GetBinContent(1));
155+
fitfunc->SetParameter(1, hGlauberParameters->GetBinContent(2));
156+
fitfunc->SetParameter(2, hGlauberParameters->GetBinContent(3));
157+
fitfunc->SetParameter(3, hGlauberParameters->GetBinContent(4));
158+
fitfunc->SetParameter(4, hGlauberParameters->GetBinContent(5));
159+
160+
Double_t lMax = hData->GetBinLowEdge(hData->GetNbinsX() + 1);
161+
162+
// uncomment if Np Nc needed -> Warning, slow!
163+
g->CalculateAvNpNc(hProfileNpart, hProfileNcoll, h2dNpart, h2dNcoll, hCalib, 0, lMax);
164+
165+
hProfileNpart->Write();
166+
hProfileNcoll->Write();
167+
h2dNpart->Write();
168+
h2dNcoll->Write();
169+
}
170+
171+
fileCalib->Write();
172+
}

0 commit comments

Comments
 (0)