KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVLightEnergyCsIFull.cpp
Go to the documentation of this file.
1 //Created by KVClassFactory on Fri Feb 8 09:58:44 2013
2 //Author: dgruyer
3 
4 #include "KVLightEnergyCsIFull.h"
5 using namespace std;
6 
8 
9 //________________________________________________________________
10 
11 
13 Double_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 
152 Double_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 
223 Double_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 
239 Double_t KVLightEnergyCsIFull::gamma_ziegler(double z, double a, double e)
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 
256 Double_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 
297 Double_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
348  fDlight->SetParameters(par);
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) {
527  SetLightFormula(i);
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 
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define d(i)
#define b(i)
#define c(i)
#define e(i)
double Double_t
const char Option_t
double pow(double, double)
double sin(double)
double exp(double)
double log(double)
const Char_t * GetType() const
Definition: KVBase.h:170
virtual void SetType(const Char_t *str)
Definition: KVBase.h:166
void SetCalibFunction(TF1 *f)
Definition: KVCalibrator.h:88
virtual void Print(Option_t *opt="") const
Print a description of the calibration object, including a list of its parameters.
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 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
Print a description of the calibration object, including a list of its parameters.
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)
Definition: KVNucleus.cpp:1769
virtual void Error(const char *method, const char *msgfmt,...) const
const char * Data() const
double beta(double x, double y)
VecExpr< UnaryOp< Sqrt< T >, SVector< T, D >, T >, T, D > sqrt(const SVector< T, D > &rhs)
return c1
Double_t x[n]
return c2
return c3
const long double m
Definition: KVUnits.h:70
double gamma(double x)
double T(double x)
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
auto * a
REAL epsilon