KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVLightEnergyCsIFull.cpp
1//Created by KVClassFactory on Fri Feb 8 09:58:44 2013
2//Author: dgruyer
3
4#include "KVLightEnergyCsIFull.h"
5using namespace std;
6
8
9//________________________________________________________________
10
11
12
13Double_t KVLightEnergyCsIFull::GetDeltaFraction(Double_t beta, Double_t beta_delta)
14{
15 double frac = 0.;
16 double rap = 1.;
17 if (beta > beta_delta) rap = TMath::Power(beta / beta_delta, 2.);
18 else return 0.;
19 double deno = log(1.022e6 / (16.*TMath::Power(fZmed, 0.9)) * TMath::Power(beta_delta, 2)) + log(rap);
20 frac = 0.5 * log(rap) / deno;
21 return frac;
22}
23
24
25
27
29{
30 double e = x[0];
31
32 double zfit = Z;
33 double afit = A;
34
35 double ag = par[0];
36 double ar = par[1];
37 double an = par[2];
38 double e_delta = par[3];
39
40 double m = afit * KVNucleus::u();
41 if (zfit == 2. && afit == 4.) m = 3727.4;
42 if ((zfit == 1.) && (afit == 1.)) m = 938.;
43
44 double beta = 0.;
45 double fraction = 0.;
46 double dlum = 0.;
47
48 double beta_delta = sqrt(2.*e_delta / KVNucleus::u());
49
50 beta = sqrt(1. - m * m / ((e + m) * (e + m)));
51
52 fraction = GetDeltaFraction(beta, beta_delta);
53 if (fraction > 1.) fraction = 1.;
54 if (fraction < 0.) fraction = 0.;
55
56
57 double se = sp_e(zfit, afit, e);
58 double sn = sp_n(zfit, afit, e);
59 double deno = 1. + ar * se + an * sn;
60 double deno2 = 1. + (1. - fraction) * ar * se + an * sn;
61 double raps = 1. + sn / se;
62 if (e <= e_delta * afit) {
63 if (se > 0. && raps > 0. && deno > 0.) dlum = (1. + an * sn) / (deno * raps);
64 }
65 else {
66 if (se > 0. && raps > 0. && deno > 0.) {
67 dlum = (1. + an * sn) * (1. - fraction) / (deno2 * raps) + fraction / raps;
68 }
69 }
70
71 dlum *= ag;
72 return dlum;
73}
74
75
76
78
80{
81 double e = x[0];
82 double zfit = Z;
83 double afit = A;
84 double ag = par[0];
85 double ar = par[1];
86 if (ar < 1.e-8) ar = 0.;
87 double an = par[2];
88 double e_delta = par[3];
89 double m = afit * KVNucleus::u();
90 if (zfit == 1. && afit == 1.) m = 938.2;
91 if (zfit == 1. && afit == 2.) m = 1876.;
92 if (zfit == 1. && afit == 3.) m = 2809.4;
93 if (zfit == 2. && afit == 3.) m = 2809.4;
94 if (zfit == 2. && afit == 4.) m = 3727.4;
95 if (zfit == 2. && afit == 6.) m = 5606.6;
96 if (zfit == 2. && afit == 8.) m = 7483.7;
97 double beta = 0.;
98 double fraction = 0.;
99 double dlum = 0.;
100 double beta_delta = sqrt(2.*e_delta / KVNucleus::u());
101 beta = sqrt(1. - m * m / ((e + m) * (e + m)));
102 fraction = GetDeltaFraction(beta, beta_delta);
103 if (fraction > 1.) fraction = 1.;
104 if (fraction < 0.) fraction = 0.;
105
106 double se = sp_e(zfit, afit, e);
107 double sn = sp_n(zfit, afit, e);
108 double raps = 1.;
109 if (se > 1.e-6) raps = 1. + sn / se;
110 double arg = 1. - ar * se / (1. + an * sn + ar * se);
111 double fact = 1.;
112 double deno = 1. + an * sn + (1. - fraction) * ar * se;
113// If energy is below the delta production threshold : 1 term
114 if (e <= e_delta * afit) {
115 if (arg > 0. && raps * ar * se > 0.) dlum = -fact * log(arg) / (raps * ar * se);
116 else dlum = 0.;
117 }
118// If energy is above the delta production threshold : 2 terms
119 else {
120 if (deno > 0.) arg = 1. - (1. - fraction) * ar * se / deno;
121 if (arg > 0. && ar * se > 0. && raps > 0.) dlum = -fact * log(arg) / (raps * ar * se) + fraction / raps;
122 else dlum = 0.;
123 }
124// Multiply by the gain factor
125 dlum = dlum * ag;
126 return dlum;
127 /* double raps = 1.+sn/se;
128 double arg = 1.-ar*se/(1.+an*sn+ar*se);
129 double fact = 1.;
130
131 if(e<=e_delta*afit)
132 {
133 if((arg>0.)&&(ar*se>0.)&&(raps>0.)) dlum = -fact*TMath::Log(arg)/(raps*ar*se);
134 }
135 else
136 {
137 Double_t y = 1 - fraction*ar*se/(1. + an*sn + ar*se);
138 arg = 1. - y*ar*se/(1. + an*sn+ar*se);
139 if((arg>0.)&&(ar*se>0.)&&(raps>0.)) dlum = -fact*(1-fraction)*TMath::Log(arg)/(raps*ar*se*y) + fraction/raps;
140 }
141
142 dlum *= ag;
143 return dlum;
144 */
145}
146
147
148
151
152Double_t KVLightEnergyCsIFull::sp_e(double z, double a, double e)
153{
154// if energy E<0.1 keV, return 0
155 if (e < 1.e-4) return 0.;
156// coefficients for Helium particles (master curves) on Iodium (Z=53), see ref. Ziegler
157 double a1_i = 3.118;
158 double a2_i = 0.6519;
159 double a3_i = 164.9;
160 double a4_i = 1.208;
161 double a5_i = 1.51;
162 double a6_i = 4.614;
163 double a7_i = 0.1043;
164 double a8_i = -0.1315;
165 double a9_i = -0.009175;
166// coefficients for Helium particles (master curves) on Cesium (Z=55), see ref. Ziegler
167 double a1_cs = 14.4;
168 double a2_cs = 0.3923;
169 double a3_cs = 152.5;
170 double a4_cs = 8.354;
171 double a5_cs = 2.597;
172 double a6_cs = 4.671;
173 double a7_cs = 0.1136;
174 double a8_cs = -0.1298;
175 double a9_cs = -0.009078;
176// Reference particles for master curves, here alpha particles
177 int zref = 2;
178 int aref = 4;
179 double ei = float(aref) * e / a * 1000.; // energy in keV !
180 double slow_cs = 0.;
181 double shigh_cs = 0.;
182 double se_cs = 0.;
183 double slow_i = 0.;
184 double shigh_i = 0.;
185 double se_i = 0.;
186 double se = 0.;
187 slow_cs = a1_cs * pow(ei, a2_cs);
188 shigh_cs = 1000.*a3_cs * log(1. + 1000.*a4_cs / ei + a5_cs * ei / 1000.) / ei;
189 slow_i = a1_i * pow(ei, a2_i);
190 shigh_i = 1000.*a3_i * log(1. + 1000.*a4_i / ei + a5_i * ei / 1000.) / ei;
191 if (ei <= 10000.) {
192 double fact = 0.997;
193 se_cs = fact * slow_cs * shigh_cs / (slow_cs + shigh_cs);
194 se_i = fact * slow_i * shigh_i / (slow_i + shigh_i);
195 }
196 else {
197 se_cs = exp(a6_cs + a7_cs * log(1000. / ei) + a8_cs * pow(log(1000. / ei), 2.) + a9_cs * pow(log(1000. / ei), 3.));
198 se_i = exp(a6_i + a7_i * log(1000. / ei) + a8_i * pow(log(1000. / ei), 2.) + a9_i * pow(log(1000. / ei), 3.));
199 }
200// Electronic stopping power for the composite Cs+I = CsI
201 double seref = (127.*se_i + 133.*se_cs) / (127. + 133.);
202// Get the effective charge
203 se = pow(gamma(z, a, e) * float(z) / (gamma(zref, aref, ei) * float(zref)), 2.) * seref;
204// Special cases for Z=1 (gamma=1) and Z=2 (reference!)
205 if (z == int(zref)) se = seref;
206 if (z == 1.) se = seref / (pow(float(zref), 2.) * gamma(zref, aref, ei));
207// Convert the stopping power from eV/(10**15 atoms/cm**2) to MeV/(mg/cm**2)
208 se *= 6.022 / (10.*fAmed);
209// Convert in MeV/micron, not here !
210 return se;
211 /* if ( e<1.e-4 ) return 0.;
212 Double_t se = fMaterialTable->GetStoppingFunction(z,a)->Eval(e);//-sp_n(z,a,e); // in units of MeV/(g/cm**2)
213 se*=1.e-3; // in units of MeV/(mg/cm**2)
214 return se-sp_n(z,a,e);
215 */
216}
217
218
219
222
223Double_t KVLightEnergyCsIFull::gamma(double z, double a, double e)
224{
225// Hubert, Bimbot and Gauvin
226 double g0 = 0.;
227 g0 = (gamma_hbg(z, a, e) + gamma_ziegler(z, a, e)) / 2.;
228// if E<2.5 meV/n, take effective charge gamma from Ziegler, otherwise take Hubert and Bimbot's formula
229// A linear adjustment is made to avoid discontinuity between the two prescriptions at E=2.5 MeV/n
230// For very low energy (E<400 keV/n), take the gamma value from Ziegler's formula at E=400 keV/n
231 if (e < 0.4 * a) g0 = gamma_ziegler(z, a, 0.4 * a);
232 return g0;
233}
234
235
236
238
240{
241 double ei = e;
242 double m = a * KVNucleus::u();
243 if (z == 2. && a == 4.) m = 3727.4;
244 double v0 = 7.2983824e-3; // Bohr velocity for electrons
245 double v = sqrt(2.*ei / m);
246 double v1 = 0.886 * (v / v0) * pow(z, -2. / 3.);
247 double v2 = v1 + 0.038 * sin(3.141592654 * v1 / 2.);
248 double xgamma = 1. - (1.034 - 0.17777 * exp(-0.08114 * z)) * exp(-v2);
249 return xgamma;
250}
251
252
253
255
256Double_t KVLightEnergyCsIFull::gamma_hbg(double z, double a, double e)
257{
258 double z2 = fZmed; // Here the atomic number Z for the stopping material
259 double b = 1.658;
260 double c = 0.0517;
261 double d = 1.164 + 0.2319 * exp(-0.0004302 * z2);
262 double x1 = d + b * exp(-c * z);
263 double x2 = 8.144 + 0.09876 * log(z2);
264 double x3 = 0.314 + 0.01072 * log(z2);
265 double x4 = 0.5218 + 0.02521 * log(z2);
266// Special values for Beryllium
267 if (z == 4) {
268 b = 2.;
269 c = 0.04369;
270 d = 2.045;
271 x1 = d + b * exp(-c * z);
272 x2 = 7.;
273 x3 = 0.2643;
274 x4 = 0.4171;
275 }
276// Special values for Carbon
277 if (z == 6) {
278 b = 1.91;
279 c = 0.03958;
280 d = 2.584;
281 x1 = d + b * exp(-c * z);
282 x2 = 6.933;
283 x3 = 0.2433;
284 x4 = 0.3969;
285 }
286 double xgamma = 1. - x1 * exp(-x2 * pow(e / a, x3) / pow(z, x4));
287 if (xgamma > 1.) xgamma = 1.;
288 if (xgamma < 0.) xgamma = 0.;
289 return xgamma;
290}
291
292
293
296
297Double_t KVLightEnergyCsIFull::sp_n(double z, double a, double e)
298{
299 // return 0.;
300 if (e < 1.e-4) return 0.;
301 double ered = 32.53 * fAmed * e * 1000. / (z * fZmed * (a + fAmed) * sqrt(TMath::Power(z, 2. / 3.) + TMath::Power(fZmed, 2. / 3.)));
302 double sn = 1.593 * sqrt(ered);
303 if (ered >= 0.01 && ered <= 10.) sn = 1.7 * sqrt(ered) * (log(ered + exp(1.)) / (1. + 6.8 * ered + 3.4 * TMath::Power(ered, 1.5)));
304 if (ered > 10.) sn = log(0.47 * ered) / (2.*ered);
305 //
306 // This is in eV/(10**15 atoms/cm**2)
307 //
308 sn = sn * 8.462 * z * fZmed * a / ((a + fAmed) * sqrt(TMath::Power(z, 2. / 3.) + TMath::Power(fZmed, 2. / 3.)));
309 //
310 // convert in MeV/(mg/cm**2)
311 //
312 sn = sn * 6.022 / (10.*fAmed);
313 //
314 // Convert in MeV/micron
315 //
316 //if ( fZmed==zcsi ) sn*=0.4510;
317 //else if ( fZmed==14. ) sn=sn*0.2330;
318 //
319 // Info("sp_n","method called : e=%f Zmed=%f Amed=%f sp_n=%f",e,fZmed,fAmed,sn);
320 return sn;
321}
322
323
324
332
334{
335 // x[0] = energie (MeV)
336 // par[0] = a1
337 // par[1] = a2
338 // par[2] = a3
339 // par[3] = a4
340 // par[4] = pied
341
342 double emin = 1.e-4; //arbitrary set to avoid divergence of de/dx
343 double emax = x[0];
344 double epsilon = 1.; //arbitrary set
345
346#if ROOT_VERSION_CODE > ROOT_VERSION(5,99,01)
347 // for compilation with latest ROOT svn trunk version called 5.99/01
349 return par[4] + fDlight->Integral(emin, emax, epsilon);
350#else
351 return par[4] + fDlight->Integral(emin, emax, par, epsilon);
352#endif
353
354}
355
356
357
367
369{
370 //Calcul de la lumiere totale a partir de Z, A d'une particule et son energie -> copie de KVLightEnergyCsI->CalculeLumiere(...)
371 //
372 // x[0] = energie (MeV)
373 // par[0] = pied
374 // par[1] = a1
375 // par[2] = a2
376 // par[3] = a3
377 // par[4] = a4
378
379 Double_t energie = x[0];
380
381 Double_t c1 = par[1];
382 Double_t c2 = Z * Z * A * par[2];
383 Double_t c3 = A * par[3];
384 Double_t c4 = par[4];
385 Double_t T = 8 * A;
386 Double_t c4_new = c4 / (1. + TMath::Exp((c3 - energie) / T));
387 Double_t c0 = c4 / (1. + TMath::Exp(c3 / T));
388
389 Double_t lumcalc = c1 * energie;
390 if (c2 > 0.0) {
391 Double_t xm = -c1 * c0 * c2 * TMath::Log(c2 / (c2 + c3));
392 lumcalc = lumcalc - c1 * c2 * TMath::Log(1. + energie / c2) + c1 * c2 * c4_new * TMath::Log((energie + c2) / (c3 + c2)) + xm;
393 }
394
395 return par[0] + lumcalc;
396}
397
398
399
409
411{
412 //Calcul de la lumiere totale a partir de Z, A d'une particule et son energie -> copie de ami_4 Lopez, Parlog LPCCaen
413 //
414 // x[0] = energie (MeV)
415 // par[0] = pied
416 // par[1] = a1
417 // par[2] = a2
418 // par[3] = a3
419 // par[4] = a4
420
421 Double_t E = x[0];
422
423 Double_t pied = par[0];
424 Double_t a0 = par[1];
425 Double_t a1 = par[2];
426 Double_t a2 = par[3];
427 Double_t a3 = par[4];
428
429 Double_t raz2 = A * Z * Z * a1;
430 Double_t si = a0 * (E - raz2 * log(1. + E / raz2) + raz2 * log((E + raz2) /
431 (a3 * A + raz2)) - (1. - a2) * (1. - a2) * raz2 * log((E + (1. - a2) * raz2) /
432 (a3 * A + (1. - a2) * raz2)));
433
434 return pied + si;
435}
436
437
438
440
442 : KVLightEnergyCsI(false), fDlight(nullptr)
443{
444 SetType("LightEnergyCsIFull");
445}
446
447
448
451
453{
454 //default initialisations
455
456 fZmed = 54;// default CsI
457 fAmed = 130;// default CsI
458
459 switch (fLightFormula) {
460 case kExact :
461 fDlight = new TF1("fDlight_CsI", this, &KVLightEnergyCsIFull::dLightIntegral, 0., 10000., 4);
462 SetCalibFunction(new TF1("fLight_CsI", this, &KVLightEnergyCsIFull::GetLight, 0., 10000., 5));
463 SetType("Exact");
464 break;
465
466 case kApproxIntegral :
467 fDlight = new TF1("fDlight_CsI", this, &KVLightEnergyCsIFull::dLightIntegralApprox, 0., 10000., 4);
468 SetCalibFunction(new TF1("fLight_CsI", this, &KVLightEnergyCsIFull::GetLight, 0., 10000., 5));
469 SetType("ApproxIntegral");
470 break;
471
472 case kApprox :
473 SetCalibFunction(new TF1("fLight_CsI", this, &KVLightEnergyCsIFull::GetLightApprox, 0., 10000., 5));
474 SetType("Approx");
475 break;
476
477 case kApproxSilicon :
478 fZmed = 14; // values for Silicon?
479 fAmed = 28; // values for Silicon?
480 SetCalibFunction(new TF1("fLight_CsI", this, &KVLightEnergyCsIFull::GetLightApproxSilicon, 0., 10000., 5));
481 SetType("ApproxSilicon");
482 break;
483
484 default :
485 SetCalibFunction(new TF1("fLight_CsI", this, &KVLightEnergyCsIFull::GetLightApprox, 0., 10000., 5));
486 SetType("Approx");
487 break;
488 }
489}
490
491
492
494
496{
498 cout << "Formula : " << fLightFormula << " Type : " << GetType() << endl;
499}
500
501
502
512
514{
515 // Set type of light-energy formula. Can be one of:
516 //
517 //~~~~~~~~~~
518 // Exact
519 // ApproxIntegral
520 // Approx (=INDRA style)
521 // ApproxSilicon
522 //~~~~~~~~~~
523
524 TString formula_types[] = {"Exact", "ApproxIntegral", "Approx", "ApproxSilicon"};
525 for (int i = 0; i < 4; ++i) {
526 if (formula_types[i] == which) {
528 return;
529 }
530 }
531 Error("SetLightFormula", "Unkown light formula type : %s", which.Data());
532}
533
534
535
543
545{
546 // Used to set up a CsI calibrator from infos in a calibration parameter file.
547 // Use an option string like this:
548 //
549 //~~~~~~~~~~~~~~
550 // CalibOptions: formula=[Exact|ApproxIntegral|Approx|ApproxSilicon]
551 //~~~~~~~~~~~~~~
552
553 SetLightFormula(opt.GetStringValue("formula"));
554}
555
556
557
#define d(i)
#define c(i)
#define e(i)
double Double_t
const char Option_t
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
virtual void SetType(const Char_t *str)
Definition KVBase.h:173
virtual const Char_t * GetType() const
Definition KVBase.h:177
void SetCalibFunction(TF1 *f)
Exact calibration formula for CsI detectors.
TF1 * fDlight
function to integrate to get fLight
Double_t gamma_hbg(double z, double a, double e)
Double_t gamma(double z, double a, double e)
Hubert, Bimbot and Gauvin.
Double_t fZmed
Z of detector material.
void SetOptions(const KVNameValueList &opt)
Double_t dLightIntegralApprox(double *x, double *par)
Double_t GetLight(double *x, double *par)
Double_t GetDeltaFraction(Double_t beta, Double_t beta_delta)
Double_t dLightIntegral(double *x, double *par)
Double_t GetLightApproxSilicon(double *x, double *par)
Double_t GetLightApprox(double *x, double *par)
Double_t sp_n(double z, double a, double e)
return 0.;
Int_t fLightFormula
light formula (see NIMa of Marian)
Double_t fAmed
A of detector material (CsI)
Double_t sp_e(double z, double a, double e)
if energy E<0.1 keV, return 0
virtual void Print(Option_t *opt="") const
void SetLightFormula(Int_t form)
void init()
default initialisations
Double_t gamma_ziegler(double z, double a, double e)
Light-energy calibration function for CsI detectors using a Fermi-function dependence on energy for d...
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
const Char_t * GetStringValue(const Char_t *name) const
static Double_t u(void)
virtual Double_t Integral(Double_t a, Double_t b, Double_t epsrel=1.e-12)
virtual void SetParameters(const Double_t *params)
void Print(Option_t *option="") const override
virtual void Error(const char *method, const char *msgfmt,...) const
const char * Data() const
double beta(double x, double y)
RVec< PromoteType< T > > log(const RVec< T > &v)
RVec< PromoteTypes< T0, T1 > > pow(const RVec< T0 > &v, const T1 &y)
RVec< PromoteType< T > > exp(const RVec< T > &v)
RVec< PromoteType< T > > sin(const RVec< T > &v)
return c1
Double_t x[n]
return c2
return c3
double T(double x)
Expr< UnaryOp< Sqrt< T >, Expr< A, T, D, D2, R >, T >, T, D, D2, R > sqrt(const Expr< A, T, D, D2, R > &rhs)
c0
Double_t Exp(Double_t x)
Double_t Power(Double_t x, Double_t y)
constexpr Double_t E()
Double_t Log(Double_t x)
v2
v0
v
v1
TMarker m
TArc a
ClassImp(TPyArg)
double epsilon