Project
Loading...
Searching...
No Matches
GEMAmplification.cxx
Go to the documentation of this file.
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
15
17#include <TStopwatch.h>
19#include <TFile.h>
21#include <fstream>
22#include "Framework/Logger.h"
23#include <filesystem>
24
25using namespace o2::tpc;
26using namespace o2::math_utils;
27using boost::format;
28
29GEMAmplification::GEMAmplification()
30 : mRandomGaus(),
31 mRandomFlat(RandomRing<>::RandomType::Flat),
32 mGain()
33{
34 updateParameters();
35
36 TStopwatch watch;
37 watch.Start();
38 const float sigmaOverMu = mGasParam->SigmaOverMu;
39 const float kappa = 1 / (sigmaOverMu * sigmaOverMu);
40 boost::format polya("1/(TMath::Gamma(%1%)*%2%) * TMath::Power(x/%3%, %4%) * TMath::Exp(-x/%5%)");
41
42 const char* polyaFileName = "tpc_polya.root";
43 TFile* outfile;
44 auto cacheexists = std::filesystem::exists(polyaFileName);
45 if (cacheexists) {
46 LOG(info) << "TPC: GEM setup from existing cache";
47 outfile = TFile::Open(polyaFileName);
48 } else {
49 LOG(info) << "TPC: GEM setup - initialization from scratch";
50 outfile = TFile::Open(polyaFileName, "CREATE");
51 }
52
54 for (int i = 0; i < 4; ++i) {
55 float s = mGEMParam->AbsoluteGain[i] / kappa;
56 polya % kappa % s % s % (kappa - 1) % s;
57 std::string name = polya.str();
58 o2::math_utils::CachingTF1* polyaDistribution = nullptr;
59 if (!cacheexists) {
60 polyaDistribution = new o2::math_utils::CachingTF1("polya", name.c_str(), 0, 10.f * mGEMParam->AbsoluteGain[i]);
63 polyaDistribution->SetNpx(100000);
64 } else {
65 polyaDistribution = (o2::math_utils::CachingTF1*)outfile->Get(TString::Format("func%d", i).Data());
66 // FIXME: verify that distribution corresponds to the parameters used here
67 }
68 mGain[i].initialize(*polyaDistribution);
69
70 if (!cacheexists) {
71 outfile->WriteTObject(polyaDistribution, TString::Format("func%d", i).Data());
72 }
73 delete polyaDistribution;
74 }
75
77 const float gainStack = mGEMParam->TotalGainStack;
78 const float kappaStack = mGEMParam->KappaStack;
79 const float effStack = mGEMParam->EfficiencyStack;
80 // Correct for electron losses occurring when changing kappa and the efficiency
81 const float sStack = gainStack / (kappaStack * effStack);
82 polya % kappaStack % sStack % sStack % (kappaStack - 1) % sStack;
83 std::string name = polya.str();
84 o2::math_utils::CachingTF1* polyaDistribution = nullptr;
85 if (!cacheexists) {
86 polyaDistribution = new o2::math_utils::CachingTF1("polya", name.c_str(), 0, 25.f * gainStack);
87 polyaDistribution->SetNpx(50000);
88 } else {
89 polyaDistribution = (o2::math_utils::CachingTF1*)outfile->Get("polyaStack");
90 }
91 mGainFullStack.initialize(*polyaDistribution);
92
93 if (!cacheexists) {
94 outfile->WriteTObject(polyaDistribution, "polyaStack");
95 }
96 delete polyaDistribution;
97
98 if (outfile) {
99 outfile->Close();
100 }
101 watch.Stop();
102 LOG(info) << "TPC: GEM setup (polya) took " << watch.CpuTime();
103}
104
106{
107 auto& cdb = CDBInterface::instance();
108 mGEMParam = &(ParameterGEM::Instance());
109 mGasParam = &(ParameterGas::Instance());
110 mGainMap = &(cdb.getGainMap());
111}
112
114{
118 const int nElectronsGEM1 = getSingleGEMAmplification(nElectrons, 0);
119 const int nElectronsGEM2 = getSingleGEMAmplification(nElectronsGEM1, 1);
120 const int nElectronsGEM3 = getSingleGEMAmplification(nElectronsGEM2, 2);
121 const int nElectronsGEM4 = getSingleGEMAmplification(nElectronsGEM3, 3);
122 return nElectronsGEM4;
123}
124
126{
130 int nElectronsGEM = 0;
131 for (int i = 0; i < nElectrons; ++i) {
132 if (mRandomFlat.getNextValue() > mGEMParam->EfficiencyStack) {
133 continue;
134 }
135 nElectronsGEM += mGainFullStack.getNextValue();
136 }
137 return nElectronsGEM;
138}
139
141{
149 int collectionGEM = getElectronLosses(nElectrons, mGEMParam->CollectionEfficiency[GEM]);
150 int amplificationGEM = getGEMMultiplication(collectionGEM, GEM);
151 int extractionGEM = getElectronLosses(amplificationGEM, mGEMParam->ExtractionEfficiency[GEM]);
152 return extractionGEM;
153}
154
155int GEMAmplification::getGEMMultiplication(int nElectrons, int GEM)
156{
159 if (nElectrons < 1) {
161 return 0;
162 } else if (nElectrons > 500) {
166 return ((mRandomGaus.getNextValue() * std::sqrt(static_cast<float>(nElectrons)) *
167 mGasParam->SigmaOverMu) +
168 nElectrons) *
169 mGEMParam->AbsoluteGain[GEM];
170 } else {
173 int electronsOut = 0;
174 for (int i = 0; i < nElectrons; ++i) {
175 electronsOut += mGain[GEM].getNextValue();
176 }
177 return electronsOut;
178 }
179}
180
181int GEMAmplification::getElectronLosses(int nElectrons, float probability)
182{
184 float electronsFloat = static_cast<float>(nElectrons);
185 if (nElectrons < 1 || probability < 0.00001) {
187 return 0;
188 } else if (probability > 0.99999) {
190 return nElectrons;
191 } else if (electronsFloat * probability >= 5.f && electronsFloat * (1.f - probability) >= 5.f) {
194 return (mRandomGaus.getNextValue() * std::sqrt(electronsFloat * probability * (1 - probability))) +
195 electronsFloat * probability + 0.5;
196 } else {
198 int nElectronsOut = 0;
199 for (int i = 0; i < nElectrons; ++i) {
200 if (mRandomFlat.getNextValue() < probability) {
201 ++nElectronsOut;
202 }
203 }
204 return nElectronsOut;
205 }
206}
Simple interface to the CDB manager.
Definition of the GEM amplification.
int32_t i
static CDBInterface & instance()
void updateParameters()
Update the OCDB parameters cached in the class. To be called once per event.
int getElectronLosses(int nElectrons, float probability)
int getEffectiveStackAmplification(int nElectrons=1)
int getStackAmplification(int nElectrons=1)
int getSingleGEMAmplification(int nElectrons, int GEM)
int getGEMMultiplication(int nElectrons, int GEM)
GLuint const GLchar * name
Definition glcorearb.h:781
float & s
Definition Utils.h:110
Global TPC definitions and constants.
Definition SimTraits.h:167
float AbsoluteGain[4]
Absolute gain.
float CollectionEfficiency[4]
Collection efficiency.
float EfficiencyStack
Variable steering the single electron efficiency of the full stack for the EffectiveMode.
float ExtractionEfficiency[4]
Extraction efficiency.
float SigmaOverMu
Sigma over mu, gives deviation from exponential gain fluctuations.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"