CbmRoot
Loading...
Searching...
No Matches
CbmTrdParModGas.cxx
Go to the documentation of this file.
1/* Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Alexandru Bercuci, Florian Uhlig [committer] */
4
5#include "CbmTrdParModGas.h"
6
7#include <Logger.h> // for Logger, LOG
8
9#include <TAxis.h> // for TAxis
10#include <TGenericClassInfo.h> // for TGenericClassInfo
11#include <TH2.h> // for TH2F
12#include <TMath.h> // for Exp
13#include <TMathBase.h> // for Abs
14#include <TObjArray.h> // for TObjArray
15#include <TObjString.h> // for TObjString
16
17#include <stdio.h> // for printf
18
19#define VERBOSE 0
20
21// binding energy in keV for 'K' 'L' and 'M' shells of Ar and Xe
23 {34.5, 5.1, 1.1}, // Xe
24 {3.2, 0.25, 0.1} // Ar
25};
26// binding energy in keV for 'K' 'L' and 'M' shells of Ar and Xe
27Float_t CbmTrdParModGas::fgkBR[2][NSHELLS - 1] = {
28 {0.11, 0.02}, // Xe
29 {0.11, 0.02} // Ar
30};
31// average energy to produce one electron-ion pair
32Float_t CbmTrdParModGas::fgkWi[3] = {
33 23.1, // Xe
34 25.8, // Ar
35 33 // CO2
36};
37// Bucharest detector gas gain parametrization based on 55Fe measurements with ArCO2(80/20)
38Float_t CbmTrdParModGas::fgkGGainUaPar[2] = {-10.1676, 8.3745};
39Float_t CbmTrdParModGas::fgkE0 = 866.1047; // energy offset in ADC ch @ 0 keV
40
41//___________________________________________________________________
43 : CbmTrdParMod("CbmTrdParModGas", title)
44 , fConfig(0)
45 , fUa(0)
46 , fUd(0)
47 , fDw(0.3)
48 , fGasThick(0.6)
49 , fPercentCO2(0.2)
50 , fDriftMap(nullptr)
51 , fFileNamePID("parameters/trd/Likelihood_Xenon_85_v20b_tdr18_apr21.root")
52{
53 TString s(title);
54 TString name;
55 // Int_t val;
56 TObjArray* so = s.Tokenize("/");
57 for (Int_t ie(0); ie < so->GetEntriesFast(); ie += 2) {
58 name = ((TObjString*) (*so)[ie])->String();
59 if (name.EqualTo("Module")) fModuleId = ((TObjString*) (*so)[ie + 1])->String().Atoi();
60 else if (name.EqualTo("Ua"))
61 fUa = ((TObjString*) (*so)[ie + 1])->String().Atoi();
62 else if (name.EqualTo("Ud"))
63 fUd = ((TObjString*) (*so)[ie + 1])->String().Atoi();
64 else if (name.EqualTo("Gas")) {
65 TString gas = ((TObjString*) (*so)[ie + 1])->String();
66 if (gas.EqualTo("Ar")) SetNobleGasType(1);
67 else if (gas.EqualTo("Xe"))
69 else {
70 LOG(warn) << GetName() << ":: gas type \"" << gas << "\" not defined. Default to Xe.";
72 }
73 }
74 }
75 so->Delete();
76 delete so;
77
78 if (VERBOSE) printf("Module[%2d] U[%4d %3d]\n", fModuleId, fUa, fUd);
79}
80
81//___________________________________________________________________
83{
84 // if(fDriftMap) delete fDriftMap;
85}
86
87//_______________________________________________________________________________________________
88Float_t CbmTrdParModGas::EkevFC(Float_t ekev) const
89{
90 // Convert energy deposit to no of primary ionizations and apply gas gain.
91 // Currently gas gain is evalauted from 55Fe spectrum analysis on ArCO2(80/20)
92 Int_t gasId = GetNobleGasType() - 1;
93 Float_t wi = (1. - fPercentCO2) * fgkWi[gasId] + fPercentCO2 * fgkWi[2];
94
95 //gas gain
96 // G = G[ev->ADC] * wi[ArCO2]/C[mV->ADC]/A[fC->mV]/e
97 // G[ev->ADC] : measured gain based on 55Fe spectrum (expo)
98 // wi[ArCO2] : average energy to produce a ele-ion pair in mixture (27.24 ev)
99 // C[mV->ADC] : FASP out [2V] to ADC range [4096 ch] (2)
100 // A[fC->mV] : FASP gain from CADENCE (6)
101 // e : 1.6e-4 [fC] electric charge
102 Double_t gain = 170.25 * TMath::Exp(fgkGGainUaPar[0] + fgkGGainUaPar[1] * fUa * 1.e-3) / 12.;
103 // for Xe correct Ar gain measurements TODO
104 if (gasId == 0) gain *= 0.6;
105
106 Float_t efC = gain * ekev * 0.16 / wi;
107 if (VERBOSE)
108 printf(" ua[V]=%d gain[%5.2e] wi[eV]=%5.2f :: E[keV]=%6.3f E[fC]=%6.2f\n", fUa, gain, wi, ekev, efC);
109 return efC;
110
111 // Double_t eadc = fgkE0 + gain * ekev;
112 // //printf("E = %fkeV %fADC\n", ekev, eadc);
113 // // apply FASP gain -> should be done without intermediate ADC conversion TODO
114 // Double_t sFASP = eadc/2.; // FASP signal [mV]; FASP amplification 1
115 // // FASP gaincharacteristic -> should be defined elsewhere
116 // // data based on CADENCE simulations
117 // Double_t s0FASP = 10, gFASP = 6;
118 // return (sFASP-s0FASP)/gFASP;
119}
120
121//_______________________________________________________________________________________________
122Float_t CbmTrdParModGas::EfCkeV(Float_t efC) const
123{
128 Int_t gasId = GetNobleGasType() - 1;
129 Float_t wi = (1. - fPercentCO2) * fgkWi[gasId] + fPercentCO2 * fgkWi[2];
130
131 //gas gain
132 // G = G[ev->ADC] * wi[ArCO2]/C[mV->ADC]/A[fC->mV]/e
133 // G[ev->ADC] : measured gain based on 55Fe spectrum (expo)
134 // wi[ArCO2] : average energy to produce a ele-ion pair in mixture (27.24 ev)
135 // C[mV->ADC] : FASP out [2V] to ADC range [4096 ch] (2)
136 // A[fC->mV] : FASP gain from CADENCE (6)
137 // e : 1.6e-4 [fC] electric charge
138 Double_t gain = 170.25 * TMath::Exp(fgkGGainUaPar[0] + fgkGGainUaPar[1] * fUa * 1.e-3)
139 / 12.; // for Xe correct Ar gain measurements TODO
140 if (gasId == 0) gain *= 0.6;
141
142 Float_t ekev = efC * wi / gain / 0.16;
143 if (VERBOSE)
144 printf(" ua[V]=%d gain[%5.2e] wi[eV]=%5.2f :: E[keV]=%6.3f E[fC]=%6.2f\n", fUa, gain, wi, ekev, efC);
145 return ekev;
146}
147
148//_______________________________________________________________________________________________
149Int_t CbmTrdParModGas::GetShellId(const Char_t shell) const
150{
154 switch (shell) {
155 case 'K': return 0;
156 case 'L': return 1;
157 case 'M': return 2;
158 default:
159 LOG(warn) << GetName() << "::GetShellId: Atomic shell : " << shell << " not defined for gas "
160 << (GetNobleGasType() == 2 ? "Ar" : "Xe");
161 return -1;
162 }
163}
164
165//_______________________________________________________________________________________________
166Float_t CbmTrdParModGas::GetBindingEnergy(const Char_t shell, Bool_t main) const
167{
168 Int_t gasId = GetNobleGasType() - 1;
169 Int_t shellId = GetShellId(shell);
170 if (shellId < 0) return 0;
171
172 if (!main) return fgkBindingEnergy[gasId][shellId];
173 else {
174 if (shellId < NSHELLS - 1) return fgkBindingEnergy[gasId][shellId + 1];
175 else {
176 LOG(warn) << GetName() << "::GetBindingEnergy: Request atomic shell : " << shellId + 1 << " not defined for gas "
177 << (gasId ? "Ar" : "Xe");
178 return 0;
179 }
180 }
181 return 0;
182}
183
184//_______________________________________________________________________________________________
185Float_t CbmTrdParModGas::GetNonIonizingBR(const Char_t shell) const
186{
187 Int_t gasId = GetNobleGasType() - 1;
188 Int_t shellId = GetShellId(shell);
189 if (shellId < 0) return 0;
190
191 return fgkBR[gasId][shellId];
192}
193
194//_______________________________________________________________________________________________
195Char_t CbmTrdParModGas::GetPEshell(Float_t Ex) const
196{
197 const Char_t shellName[NSHELLS] = {'K', 'L', 'M'};
198 Int_t gasId = GetNobleGasType() - 1;
199 for (Int_t ishell(0); ishell < NSHELLS; ishell++) {
200 if (Ex < fgkBindingEnergy[gasId][ishell]) continue;
201 return shellName[ishell];
202 }
203 LOG(debug) << GetName() << "::GetPEshell: Ex[keV] " << Ex
204 << " less than highes atomic shell binding energy : " << fgkBindingEnergy[gasId][NSHELLS - 1]
205 << " for gas " << (gasId ? "Ar" : "Xe");
206 return 0;
207}
208
209//_______________________________________________________________________________________________
210Double_t CbmTrdParModGas::GetDriftTime(Double_t y0, Double_t z0) const
211{
212 const TAxis *ay(fDriftMap->GetXaxis()), *az(fDriftMap->GetYaxis());
213 Int_t by(ay->FindBin(y0)), bz(az->FindBin(z0));
214 Double_t tmin(fDriftMap->GetBinContent(by, bz));
215 if (VERBOSE) printf("GetDriftTime :: Start @ dt=%3d [ns]\n", Int_t(tmin));
216 return tmin;
217}
218
219//_______________________________________________________________________________________________
220void CbmTrdParModGas::Print(Option_t* /*opt*/) const
221{
222 printf("%s @ %4d ", GetName(), fModuleId);
223 printf("Type[%s] ", GetDetName());
224 printf("%s[%4.1f%%] Ua[V]=%d Ud[V]=%d ", GetNobleGasName(), 1e2 * GetNobleGas(), fUa, fUd);
225 printf("Pid Type[%d] DB[%s]\n", GetPidType(), fFileNamePID.Data());
226}
227
228//_______________________________________________________________________________________________
229Double_t CbmTrdParModGas::ScanDriftTime(Double_t y0, Double_t z0, Double_t dzdy, Double_t dy) const
230{
231 Double_t y1 = y0 + dy, z1 = z0 + dzdy * dy, dw(fDw), dwh(0.5 * dw);
232 // Double_t dhh(fGasThick);
233
234 if (VERBOSE)
235 printf("ScanDriftTime :: Try : [%7.4f %7.4f] => [%7.4f %7.4f] dzdy[%5.2f] "
236 "dy[%5.2f]\n",
237 y0, z0, y1, z1, dzdy, dy);
238 while (y1 < -dwh - 1e-3) {
239 y0 += dw;
240 y1 += dw;
241 }
242 while (y1 > dwh + 1.e-3) {
243 y0 -= dw;
244 y1 -= dw;
245 }
246 TH2F* h = fDriftMap;
247 y1 = y0;
248 z1 = z0;
249 const TAxis *ay(fDriftMap->GetXaxis()), *az(fDriftMap->GetYaxis());
250 Int_t by(ay->FindBin(y1)), bz(az->FindBin(z1)), nby(ay->GetNbins()), nbz(az->GetNbins());
251 Float_t dyStep = ay->GetBinWidth(1), tmin(500), tmax(0), tc(0);
252 while (by > 0 && by <= nby && bz <= nbz) {
253 bz = az->FindBin(z1);
254 tc = h->GetBinContent(by, bz);
255 //if(VERBOSE) printf("ScanDriftTime :: Do : y0(%7.4f), z0(%7.4f), by(%3d), bz(%3d) td[ns]=%5.1f t0[ns]=%5.1f \n", y1, z1, by, bz, tc, tmin);
256
257 if (tc > 0) {
258 if (tc < tmin) tmin = tc;
259 if (tc > tmax) tmax = tc;
260 }
261 z1 += TMath::Abs(dzdy) * dyStep;
262 if (dzdy > 0) {
263 y1 += dyStep;
264 by++;
265 }
266 else {
267 y1 -= dyStep;
268 by--;
269 }
270 }
271 if (VERBOSE) printf("ScanDriftTime :: Start @ dt=%3d [ns]\n", Int_t(tmin));
272
273 return tmin;
274}
275
276//___________________________________________________________________
277void CbmTrdParModGas::SetDriftMap(TH2F* hm, TDirectory* d)
278{
283 if (VERBOSE) printf("CbmTrdParModGas::SetDriftMap : Module[%2d] U[%4d %3d]\n", fModuleId, fUa, fUd);
284
285 fDriftMap = (TH2F*) hm->Clone(Form("trdDM%02d", fModuleId));
286 fDriftMap->SetTitle(GetTitle());
287 fDriftMap->SetDirectory(d);
288}
289
ClassImp(CbmConverterManager)
#define VERBOSE
#define NSHELLS
int main(int argc, char *argv[])
Data class with information on a STS local track.
Definition of gas parameters for one TRD module.
Int_t GetNobleGasType() const
UShort_t fUd
drift voltage
Double_t fDw
anode wire pitch
const Char_t * GetDetName() const
Char_t GetPEshell(Float_t Ex) const
Get first atomic shell which can be excited by PE effect.
static Float_t fgkE0
min energy [ADC ch] which can be measured
Double_t ScanDriftTime(Double_t y0, Double_t z0, Double_t dzdy, Double_t dy) const
Get prompt signal for track segment in the y-z plane.
const Char_t * GetNobleGasName() const
static Float_t fgkGGainUaPar[2]
gas gaian parametrization on Ua for Ar on Buch detector
virtual ~CbmTrdParModGas()
Double_t fPercentCO2
Percentage of CO2.
Float_t GetNonIonizingBR(const Char_t shell='K') const
Get branching ration for radiative process on the.
CbmTrdParModGas(const char *title="TRD gas properties definition")
static Float_t fgkBR[2][NSHELLS - 1]
branching ratio for non-ionizing decay of Ar and Xe
UShort_t fUa
anode voltage
static Float_t fgkWi[3]
average energy to produce one electron-ion pair for ar, xe and co2
Float_t GetBindingEnergy(const Char_t shell='K', Bool_t main=kTRUE) const
Get binding energy for the working gas.
Int_t GetPidType() const
TH2F * fDriftMap
drift time map for one amplification cell
void SetDriftMap(TH2F *hm, TDirectory *d)
Load drift map for current settings from repository.
void SetNobleGasType(Int_t ar=1)
Int_t GetShellId(const Char_t shell) const
Get atomic shell index.
Float_t EfCkeV(Float_t efc) const
Convert pad-plane charge in fC to energy deposit [keV] taking into account the gas gain.
static Float_t fgkBindingEnergy[2][NSHELLS]
binding energy in keV for first atomic shells of Ar and Xe
TString fFileNamePID
filename for PID database
virtual void Print(Option_t *opt="") const
Float_t EkevFC(Float_t ekev) const
Convert Energy debposit in keV to pad-plane charge taking into account the gas gain.
Double_t GetDriftTime(Double_t y0, Double_t z0) const
Double_t GetNobleGas() const
Definition of generic parameters for one TRD module.
int fModuleId
module id