Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaElossCorrection.cxx
Go to the documentation of this file.
1//*-- Author : Ole Hansen 23-Apr-04
2
4//
5// THaElossCorrection
6//
8
10#include "THaSpectrometer.h"
11#include "THaVertexModule.h"
12#include "TMath.h"
13#include "VarDef.h"
14#include "VarType.h"
15#include <iostream>
16
17// Default tolerance for floating-point equality comparisons of z_med
18static const Double_t eps = 0.1;
19
20using namespace std;
21
22//_____________________________________________________________________________
24 const char* description,
25 const char* input_tracks,
26 Double_t particle_mass,
27 Int_t hadron_charge ) :
28 THaPhysicsModule(name,description), fEloss(kBig), fM(kBig),
29 fZ(hadron_charge), fZmed(0.0), fAmed(0.0), fDensity(0.0), fPathlength(0.0),
30 fZref(0.0), fScale(0.0),
31 fTestMode(false), fElectronMode(false), fExtPathMode(false),
32 fInputName(input_tracks), fVertexModule(nullptr)
33{
34 // Normal constructor.
35
36 SetMass(particle_mass);
37 Clear();
38}
39
40//_____________________________________________________________________________
42{
43 // Destructor
44
46}
47
48//_____________________________________________________________________________
50{
51 // Clear all event-by-event variables.
52
54 if( !fTestMode )
55 fEloss = kBig;
56}
57
58//_____________________________________________________________________________
60{
61 // Initialize the module.
62
63 if( fExtPathMode ) {
64 fVertexModule = dynamic_cast<THaVertexModule*>
65 ( FindModule( fVertexName.Data(), "THaVertexModule" ));
66 if( !fVertexModule )
67 return fStatus;
68 }
69
70 // Continue with standard initialization
71 THaPhysicsModule::Init( run_time );
72
73 return fStatus;
74}
75
76//_____________________________________________________________________________
78{
79 // Define/delete global variables.
80
81 // Locally computed data
82 const RVarDef var[] = {
83 { "eloss", "Calculated energy loss correction (GeV)", "fEloss" },
84 { "pathl", "Pathlength thru medium for this event", "fPathlength" },
85 { nullptr }
86 };
87 return DefineVarsFromList( var, mode );
88}
89
90//_____________________________________________________________________________
92{
93 // Query the run database for the module parameters.
94
96 if( err ) return err;
97
98 FILE* f = OpenRunDBFile( date );
99 if( !f ) return kFileError;
100
101 DBRequest req[] = {
102 { "M", &fM, kDouble, 0, false, 0, "M (particle mass [GeV/c^2])" },
103 { "Z", &fZ, kInt, 0, true, 0, "Z (particle Z)" },
104 { "Z_med", &fZmed, kDouble, 0, false, 0, "Z_med (Z of medium)" },
105 { "A_med", &fAmed, kDouble, 0, false, 0, "A_med (A of medium)" },
106 { "density", &fDensity, kDouble, 0, false, 0, "density of medium [g/cm^3]" },
107 { "pathlength", &fPathlength, kDouble, 0, false, 0, "pathlength through medium [m]" },
108 { nullptr }
109 };
110 // Allow pathlength key to be absent in variable pathlength mode
111 if( fExtPathMode ) {
112 int i = 0;
113 while( req[i].name ) {
114 if( TString(req[i].name) == "pathlength" ) {
115 req[i].optional = true;
116 break;
117 }
118 ++i;
119 }
120 }
121
122 // Ignore database entries if parameter already set
123 DBRequest* item = req;
124 while( item->name ) {
125 if( *((double*)item->var) != 0.0 )
126 item->var = nullptr;
127 item++;
128 }
129
130 // Try to read any unset parameters from the database
131 err = LoadDB( f, date, req );
132 fclose(f);
133 if( err )
134 return kInitError;
135
136 return kOK;
137}
138
139//_____________________________________________________________________________
140void THaElossCorrection::SetInputModule( const char* name )
141{
142 // Set the name of the module that provides the input data
143 if( !IsInit())
144 fInputName = name;
145 else
146 PrintInitError("SetInputModule");
147}
148
149//_____________________________________________________________________________
151{
152 // Set mass of track particle
153 if( !IsInit() ) {
154 fM = m;
155 fElectronMode = (TMath::Abs(fM) < 1e-3);
156 } else
157 PrintInitError("SetMass");
158}
159
160//_____________________________________________________________________________
162{
163 // Enable test mode. If enabled, apply fixed energy correction for
164 // every event. Negative eloss values are ignored.
165
166 if( !IsInit() ) {
167 fTestMode = enable;
168 if( enable )
169 fEloss = TMath::Max(eloss_value,0.0);
170 } else
171 PrintInitError("SetTestMode");
172}
173
174//_____________________________________________________________________________
176 Double_t density )
177{
178 // Set parameters of the medium in which the energy loss occurs
179 if( !IsInit() ) {
180 fZmed = Z;
181 fAmed = A;
182 fDensity = density;
183 } else
184 PrintInitError("SetMedium");
185}
186
187//_____________________________________________________________________________
189{
190 // Use fixed pathlength for energy loss calculations
191
192 if( !IsInit() ) {
193 fPathlength = pathlength;
194 fExtPathMode = false;
195 } else
196 PrintInitError("SetPathlength");
197}
198
199//_____________________________________________________________________________
200void THaElossCorrection::SetPathlength( const char* vertex_module,
201 Double_t z_ref, Double_t scale )
202{
203 // Use variable pathlength for eloss calculations.
204 // The pathlength is calculated for every event as
205 // path = abs(z_vertex - z_ref) * scale
206
207 if( !IsInit() ) {
208 fZref = z_ref;
209 fScale = scale;
210 fVertexName = vertex_module;
211 fExtPathMode = true;
212 } else
213 PrintInitError("SetPathlength");
214}
215
216//-----------------------------------------------------------------------
217// The following four routines have been taken from ESPACE
218// (file kinematics/eloss.f) and translated from FORTRAN to C++.
219//
220// Original comments follow:
221//-----------------------------------------------------------------------
222// Copyright (c) 2001 Institut des Sciences Nucleaires de Grenoble
223//
224// Authors: J. Mougey, E. Voutier (Name@isn.in2p3.fr)
225//-----------------------------------------------------------------------
226//
227// WARNING !!
228//
229// These routines calculate the energy loss of electrons and hadrons
230// for elemental and compound materials, assuming that the relevant
231// physics parameters are tabulated. In the contrary, the tables at
232// the end of the section should be implemented using references:
233//
234// M.J. Berger and S.M. Seltzer, National Bureau of Standards Report
235// 82-2550A (1983).
236// R.M. Sternheimer, M.J. Berger and S.M. Seltzer,Atomic and Nuclear
237// Data Tables 30 (1984) 261.
238//
239//-----------------------------------------------------------------------
240//
241// These routines are based on the written document
242//
243// ESPACE Energy Loss Corrections Revisited
244// J. Mougey, E89-044 Analysis Progress Report, November 2000.
245//
246// which PostScript version can be downloaded from the WebSite
247//
248// http://isnwww.in2p3.fr/hadrons/helium3/Anal/AnaPag.html
249//
250//_____________________________________________________________________________
252 Double_t a_med, Double_t d_med,
253 Double_t pathlength )
254{
255 //-----------------------------------------------------------------------
256 // Energy loss of electrons taking into account the usual Bethe-Bloch
257 // stopping power and the Density Effect Corrections that are important
258 // at high electron energy. Additional shell effects can be safely
259 // neglected for ultrarelativistic electrons.
260 //
261 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
262 //
263 // Passed variables
264 //
265 // beta electron velocity (relative to light)
266 //
267 // z_med effective charge of the medium
268 // a_med effective atomic mass (AMU)
269 // d_med medium density (g/cm^3)
270 // pathlength flight path through medium (m)
271 //
272 // z_med = sum(i)(w(i)*z(i))/sum(i)w(i)
273 // w(i) is the abundacy of element i in the medium
274 //
275 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276 //
277 // Return value: Energy loss of electron (GeV)
278 //
279 //-----------------------------------------------------------------------
280
281
282 //---- Constant factor corresponding to 2*pi*N_a*(r_e)^2*m_e*c^2
283 // Its units are MeV.cm2/g
284
285 static const Double_t COEF = 0.1535374581;
286
287 //---- Electron mass (MeV)
288
289 static const Double_t EMAS = 0.5109989020;
290
291 //---- Numerical constants
292
293 static const Double_t log2 = TMath::Log(2.0);
294
295 //---- Input variables consistency check
296
297 if( beta <= 0.0 || beta >= 1.0 || z_med == 0.0 ||
298 a_med == 0.0 || pathlength == 0.0 )
299 return 0.0;
300
301 pathlength *= 1e2; // internal units are cm
302
303 Double_t BETA2 = beta * beta;
304 Double_t BETA3 = 1.0 - BETA2;
305 Double_t GAMMA = 1.0/TMath::Sqrt(BETA3);
306
307 //---- Reduced Bethe-Bloch stopping power
308
309 Double_t EXEN = ExEnerg(z_med,d_med);
310 if( EXEN == 0.0 )
311 return 0.0;
312
313 Double_t EKIN = EMAS * ( GAMMA - 1.0 );
314 Double_t TAU = EKIN / EMAS;
315 Double_t FTAU = 1.0+(TAU*TAU/8.0)-((2.0*TAU+1.0)*log2);
316 Double_t BETH = 2.0 * TMath::Log(1e6*EKIN/EXEN) + BETA3 * FTAU;
317 BETH = BETH + TMath::Log(1.0+(0.5*TAU));
318
319 //---- Reduced density correction
320
321 Double_t PLAS = 28.8084 * TMath::Sqrt(d_med*z_med/a_med);
322 Double_t DENS = 2.0*(TMath::Log(PLAS)+TMath::Log(beta*GAMMA)-TMath::Log(EXEN))-1.0;
323 if(DENS < 0.0) DENS = 0.0;
324
325 //---- Total electron stopping power
326
327 Double_t ESTP = COEF * z_med * ( BETH - DENS ) / a_med / BETA2;
328
329 //---- Electron energy loss
330
331 Double_t eloss = ESTP * d_med * pathlength * 1e-3; // GeV
332
333 return eloss;
334}
335
336//_____________________________________________________________________________
338 Double_t z_med, Double_t a_med,
339 Double_t d_med,
340 Double_t pathlength )
341{
342 //-----------------------------------------------------------------------
343 //
344 // Energy loss of hadrons taking into account the usual Bethe-Bloch
345 // stopping power + the Density Effect Corrections (important at high
346 // energy) + the Shell Corrections (important at small energy).
347 // The approximation 2 * gamma * m_e / M << 1 is used for the Bethe-
348 // Bloch formulae: for a 4 GeV/c pion, this leads to an effect about
349 // 0.5-0.7 % on the total stopping power.
350 //
351 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
352 //
353 // Passed variables
354 //
355 // Z_hadron hadron charge
356 // beta hadron velocity (relative to light)
357 //
358 // z_med effective charge of the medium
359 // a_med effective atomic mass (AMU)
360 // d_med medium density (g/cm^3)
361 // pathlength flight path through medium (m)
362 //
363 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
364 //
365 // Return value
366 //
367 // Energy loss of hadron (GeV)
368 //
369 //-----------------------------------------------------------------------
370
371
372 //---- Constant factor corresponding to 4*pi*N_a*(r_e)^2*m_e*c^2
373 // Its units are MeV.cm2/g
374
375 static const Double_t COEF = 0.3070749162;
376
377 //---- Electron mass (MeV)
378
379 static const Double_t EMAS = 0.5109989020;
380
381 //---- Numerical constants
382
383 static const Double_t log100 = TMath::Log(1e2);
384
385 //---- Input variables consistency check
386
387 if( Z_hadron == 0 || beta <= 0.0 || beta >= 1.0 || z_med == 0.0 ||
388 a_med == 0.0 || pathlength == 0.0 )
389 return 0.0;
390
391 pathlength *= 1e2; // internal units are cm
392
393 Double_t BETA2 = beta * beta;
394 Double_t GAMA2 = 1.0 / (1.0 - BETA2);
395 Double_t GAMA = TMath::Sqrt( GAMA2 );
396 Double_t ETA = beta * GAMA ;
397
398 //---- Reduced Bethe-Bloch stopping power
399
400 Double_t EXEN = ExEnerg(z_med,d_med); // in eV!
401 //- Tabulated material check
402 if( EXEN == 0.0 )
403 return 0.0;
404
405 Double_t BETH = TMath::Log(2e6*EMAS*BETA2*GAMA2/EXEN) - BETA2;
406
407 //---- Reduced density correction
408
409 Double_t PLAS = 28.8084 * TMath::Sqrt(d_med*z_med/a_med);
410 Double_t C = 2.0*TMath::Log(PLAS) - 2.0*TMath::Log(EXEN) - 1.0;
411 Double_t X = TMath::Log10(ETA);
412 Double_t X0,X1,M;
413 HaDensi(z_med,d_med,X0,X1,M);
414 //- Tabulated density consistency
415 if((X0+X1+M) == 0.0)
416 return 0.0;
417 Double_t A = -1.0 * ( C + log100*X0 ) / TMath::Power(X1-X0,M);
418 Double_t DENS;
419 if(X<X0)
420 DENS = 0.0;
421 else if(X<X1)
422 DENS = log100*X + C + A*TMath::Power(X1-X,M);
423 else
424 DENS = log100*X + C;
425 DENS *= 0.5;
426
427 Double_t ETA2 = 1.0 / (ETA*ETA) ;
428 Double_t ETA4 = ETA2 * ETA2 ;
429 Double_t ETA6 = ETA4 * ETA2 ;
430
431 //---- Reduced shell correction
432
433 Double_t SHE0 = 4.2237e-1*ETA2 + 3.040e-2*ETA4 - 3.80e-4*ETA6;
434 Double_t SHE1 = 3.8580e0 *ETA2 - 1.668e-1*ETA4 + 1.58e-3*ETA6;
435 Double_t SHEL = 1e-6 * EXEN * EXEN * (SHE0 + 1e-3*SHE1*EXEN) / z_med;
436
437 //---- Total hadron stopping power
438
439 Double_t HSTP = COEF * z_med * Double_t(Z_hadron*Z_hadron) / a_med;
440 HSTP = HSTP * ( BETH - DENS - SHEL ) / BETA2;
441
442 //---- Electron energy loss
443
444 Double_t eloss = HSTP * d_med * pathlength * 1e-3; // in GeV
445
446 return eloss;
447}
448
449//_____________________________________________________________________________
451{
452
453 Double_t EXEN = 0.0;
454
455//---- Some Z=1 isotopes
456
457 if( TMath::Abs(z_med-1.0)<0.5) {
458 //- Gaseous hydrogen
459 if(d_med<0.01)
460 EXEN = 19.2;
461 //- Liquid Hydrogen
462 // else if(d_med<0.1)
463 // EXEN = 21.8;
464 //---- Liquid Deuterium
465 else
466 EXEN = 21.8;
467 }
468 //---- Some Z=2 isotopes
469
470 //- Gaseous/Liquid Helium
471
472 else if( TMath::Abs(z_med-2.0)<eps )
473 EXEN = 41.8;
474
475 //---- Plastic scintillator (Polyvinyltolulene 2-CH[3]C[6]H[4]CH=CH[2])
476 //
477 // z_eff = 3.36842 a_eff = 6.21996 d_med = 1.03200
478
479 else if( TMath::Abs(z_med-3.37)<eps )
480 EXEN = 64.7;
481
482 //---- Kapton (Polymide film C[22]H[10]N[2]O[5])
483 //
484 // z_eff = 5.02564 a_eff = 9.80345 d_med = 1.42000
485
486 else if( TMath::Abs(z_med-5.03)<eps )
487 EXEN = 79.6;
488
489 //---- Some Z=6 isotopes
490
491 else if( TMath::Abs(z_med-6.0)<eps )
492 EXEN = 78.0;
493
494 //---- Air (dry, near sea level, 78% N2 + 22% O2)
495 //
496 // z_eff = 7.22000 a_eff = 14.46343 d_med = 1.20480E-03
497
498 else if( TMath::Abs(z_med-7.22)<eps )
499 EXEN = 85.7;
500
501//---- Aluminum
502
503 else if( TMath::Abs(z_med-13.0)<eps )
504 EXEN = 166.0;
505
506//---- Copper
507
508 else if( TMath::Abs(z_med-29.0)<eps )
509 EXEN = 322.0;
510
511//---- Titanium
512
513 else if( TMath::Abs(z_med-22.0)<eps )
514 EXEN = 233.0;
515
516//---- Table overflow
517
518 else {
519 cout << endl;
520 cout << "Warning... Unknown selected material !!" << endl;
521 cout << "z_med = " << z_med << " d_med = " << d_med << endl;
522 cout << "Implement THaElossCorrection::ExEnerg routine for proper use."
523 << endl << endl;
524 }
525
526 return EXEN;
527}
528
529//_____________________________________________________________________________
531 Double_t& X0, Double_t& X1, Double_t& M )
532{
533
534 //---- Some Z=1 isotopes
535
536 if( TMath::Abs( z_med-1.0 ) < eps ) {
537 //- Gaseous hydrogen
538 if( d_med < 0.01 ) {
539 X0 = 1.8639;
540 X1 = 3.2718;
541 M = 5.7273;
542 }
543 //- Liquid Hydrogen
544//FIXME: these numbers are identical to the liquid deuterium case below, which
545// looks suspiciously like a copy-and-paste error. It is like this already in
546// the original Fortran code (I checked). See also a similar case in ExEnerg()
547// above. We should verify/correct these data.
548// else if( d_med < 0.1 ) {
549// X0 = 0.4759;
550// X1 = 1.9215;
551// M = 5.6249;
552// }
553 //---- Liquid Deuterium
554 else {
555 X0 = 0.4759;
556 X1 = 1.9215;
557 M = 5.6249;
558 }
559 }
560 //---- Some Z=2 isotopes
561
562 else if( TMath::Abs( z_med-2.0 ) < eps ) {
563 //- Gaseous/Liquid Helium
564 X0 = 2.2017;
565 X1 = 3.6122;
566 M = 5.8347;
567 }
568
569 //---- Plastic scintillator (Polyvinyltolulene 2-CH[3]C[6]H[4]CH=CH[2])
570 //
571 // z_eff = 3.36842 a_eff = 6.21996 d_med = 1.03200
572
573 else if( TMath::Abs( z_med-3.37 ) < eps ) {
574 X0 = 0.1464;
575 X1 = 2.4855;
576 M = 3.2393;
577 }
578
579 //---- Kapton (Polymide film C[22]H[10]N[2]O[5])
580 //
581 // z_eff = 5.02564 a_eff = 9.80345 d_med = 1.42000
582
583 else if( TMath::Abs( z_med-5.03 ) < eps ) {
584 X0 = 0.1509;
585 X1 = 2.5631;
586 M = 3.1921;
587 }
588
589 //---- Some Z=6 isotopes
590
591 else if( TMath::Abs( z_med-6.0 ) < eps ) {
592 //- Carbon (graphite, density 1.700 g/cm3)
593 if( d_med < 1.750) {
594 X0 = 0.0480;
595 X1 = 2.5387;
596 M = 2.9532;
597 }
598 //- Carbon (graphite, density 2.000 g/cm3)
599 else if( d_med < 2.050) {
600 X0 = -0.0351;
601 X1 = 2.4860;
602 M = 3.0036;
603 }
604 //- Carbon (graphite, density 2.265 g/cm3)
605 else if( d_med < 2.270) {
606 X0 = -0.0178;
607 X1 = 2.3415;
608 M = 2.8697;
609 }
610 }
611
612//---- Air (dry, near sea level, 78% N2 + 22% O2)
613//
614// z_eff = 7.22000 a_eff = 14.46343 d_med = 1.20480E-03
615
616 else if( TMath::Abs( z_med-7.22 ) < eps ) {
617 X0 = 1.7418;
618 X1 = 4.2759;
619 M = 3.3994;
620 }
621
622//---- Aluminum
623
624 else if( TMath::Abs( z_med-13.0 ) < eps ) {
625 X0 = 0.1708;
626 X1 = 3.0127;
627 M = 3.6345;
628 }
629
630//---- Titanium
631
632 else if( TMath::Abs( z_med-22.0 ) < eps ) {
633 X0 = 0.0957;
634 X1 = 3.0386;
635 M = 3.0302;
636 }
637
638//---- Table overflow
639
640 else {
641 cout << endl;
642 cout << "Warning... Inconsistent material density... " << endl;
643 cout << "z_med = " << z_med << " d_med = " << d_med << endl;
644 cout << "Implement THaElossCorrection::HaDensi routine for proper use."
645 << endl << endl;
646 X0 = 0.;
647 X1 = 0.;
648 M = 0.;
649 }
650
651}
652
653//_____________________________________________________________________________
655
int Int_t
const Data_t kBig
Definition DataType.h:15
#define f(i)
#define e(i)
bool Bool_t
double Double_t
const char Option_t
Option_t Option_t TPoint TPoint const char mode
char name[80]
static const Double_t eps
virtual Int_t ReadRunDatabase(const TDatime &date)
static Int_t LoadDB(FILE *file, const TDatime &date, const DBRequest *request, const char *prefix, Int_t search=0, const char *here="THaAnalysisObject::LoadDB")
static Int_t DefineVarsFromList(const void *list, EType type, EMode mode, const char *def_prefix, const TObject *obj, const char *prefix, const char *here, const char *comment_subst="")
THaAnalysisObject * FindModule(const char *name, const char *classname, bool do_error=true)
virtual FILE * OpenRunDBFile(const TDatime &date)
Bool_t IsInit() const
virtual Int_t DefineVariables(EMode mode=kDefine)
void SetPathlength(Double_t pathlength)
static void HaDensi(Double_t z_med, Double_t d_med, Double_t &X0, Double_t &X1, Double_t &M)
virtual void Clear(Option_t *opt="")
THaElossCorrection(const char *name, const char *description, const char *input="", Double_t particle_mass=0.511e-3, Int_t hadron_charge=1)
void SetMedium(Double_t Z, Double_t A, Double_t density)
virtual Int_t ReadRunDatabase(const TDatime &date)
static Double_t ElossHadron(Int_t Z_hadron, Double_t beta, Double_t z_med, Double_t a_med, Double_t d_med, Double_t pathlength)
static Double_t ElossElectron(Double_t beta, Double_t z_med, Double_t a_med, Double_t d_med, Double_t pathlength)
static Double_t ExEnerg(Double_t z_med, Double_t d_med)
void SetInputModule(const char *name)
THaVertexModule * fVertexModule
void SetTestMode(Bool_t enable=true, Double_t eloss_value=0.0)
void PrintInitError(const char *here)
virtual void Clear(Option_t *opt="")
const char * Data() const
double beta(double x, double y)
RVec< PromoteType< T > > log2(const RVec< T > &v)
constexpr Double_t C()
Double_t Power(Double_t x, Double_t y)
Double_t Log(Double_t x)
Double_t Sqrt(Double_t x)
Double_t Abs(Double_t d)
Double_t Max(Double_t a, Double_t b)
Double_t Log10(Double_t x)
STL namespace.
TMarker m
ClassImp(TPyArg)