GEMC  2.3
Geant4 Monte-Carlo Framework
cormo_hitprocess.cc
Go to the documentation of this file.
1 // G4 headers
2 #include "G4Poisson.hh"
3 #include "Randomize.hh"
4 
5 // gemc headers
6 #include "cormo_hitprocess.h"
7 
8 // CLHEP units
9 #include "CLHEP/Units/PhysicalConstants.h"
10 using namespace CLHEP;
11 
12 map<string, double> cormo_HitProcess :: integrateDgt(MHit* aHit, int hitn)
13 {
14  map<string, double> dgtz;
15  vector<identifier> identity = aHit->GetId();
16 
17  int sector = identity[0].id;
18  int layer = identity[1].id;
19  int paddle = identity[2].id;
20 
21  // Digitization Parameters
22  double light_yield=1600/MeV; // number of optical photons pruced in the scintillator per MeV of deposited energy
23  double att_length=108*cm; // light at tenuation length
24  double sensor_surface=pow(3.5*cm,2)*pi; // area of photo sensor
25  double paddle_surface=pow(10*cm,2); // paddle surface
26  double light_coll=sensor_surface/paddle_surface; // ratio of photo_sensor area over paddle section ~ light collection efficiency
27 
28  double sensor_qe=0.15; // photo sensor quantum efficiency
29  double sensor_gain=0.472*1.6*1.275; // pmt gain x electron charge in pC (4x10^6)x(1.6x10^-7) ->val * 1.6 * 0.6 = 0,963 modifica 21/01/10
30  double adc_conv=10; // conversion factor from pC to ADC (typical sensitivy of CAEN VME QDC is of 0.1 pC/ch)
31  double adc_ped=0; // ADC Pedestal
32  double veff=13*cm/ns; // light velocity in scintillator
33  double tdc_conv=1/0.001/ns; // TDC conversion factor
34 
35 
36  // initialize ADC and TDC
37  double etotL = 0;
38  double etotR = 0;
39  double timeL = 0;
40  double timeR = 0;
41  int ADCL = 0;
42  int ADCR = 0;
43  int TDCL = 4096;
44  int TDCR = 4096;
45 
46  double etotB = 0; // signal propagating to backward end of paddle hit happened in
47  double etotF = 0; // signal propagating to forward end of the paddle the hit happened in, round u-turn and along neighbouring paddle
48  double timeB = 0;
49  double timeF = 0;
50  int ADCB = 0;
51  int ADCF = 0;
52  int TDCB = 4096;
53  int TDCF = 4096;
54 
55 
56  // Get the paddle length: in cormo paddles are along y
57 // double length = aHit->GetDetector().dimensions[2];
58  double length = 20*cm;
59 
60  // Get info about detector material to eveluate Birks effect
61  double birks_constant=aHit->GetDetector().GetLogical()->GetMaterial()->GetIonisation()->GetBirksConstant();
62  // cout << " Birks constant is: " << birks_constant << endl;
63  // cout << aHit->GetDetector().GetLogical()->GetMaterial()->GetName() << endl;
64 
65 
66  double time_min[4] = {0,0,0,0};
67 
68  vector<G4ThreeVector> Lpos = aHit->GetLPos();
69  vector<G4double> Edep = aHit->GetEdep();
70  vector<G4double> Dx = aHit->GetDx();
71  // Charge for each step
72  vector<int> charge = aHit->GetCharges();
73  vector<G4double> times = aHit->GetTime();
74 
75  unsigned int nsteps = Edep.size();
76  double Etot = 0;
77  for(unsigned int s=0; s<nsteps; s++) Etot = Etot + Edep[s];
78 
79  if(Etot>0)
80  {
81  for(unsigned int s=0; s<nsteps; s++)
82  {
83  // Distances from left, right
84  double dLeft = length + Lpos[s].y();
85  double dRight = length - Lpos[s].y();
86 
87  // cout << "\n Distances: " << endl;
88  // cout << "\t dLeft, dRight, dBack, dFwd: " << dLeft << ", " << dRight << ", " << dBack << ", " << dFwd << endl;
89 
90  // apply Birks effect
91 // double stepl = 0.;
92 
93 // if (s == 0){
94 // stepl = sqrt(pow((Lpos[s+1].x() - Lpos[s].x()),2) + pow((Lpos[s+1].y() - Lpos[s].y()),2) + pow((Lpos[s+1].z() - Lpos[s].z()),2));
95 // }
96 // else {
97 // stepl = sqrt(pow((Lpos[s].x() - Lpos[s-1].x()),2) + pow((Lpos[s].y() - Lpos[s-1].y()),2) + pow((Lpos[s].z() - Lpos[s-1].z()),2));
98 // }
99 
100  double Edep_B = BirksAttenuation(Edep[s],Dx[s],charge[s],birks_constant);
101 
102  // cout << "\t Birks Effect: " << " Edep=" << Edep[s] << " StepL=" << stepl
103  // << " PID =" << pids[s] << " charge =" << charge[s] << " Edep_B=" << Edep_B << endl;
104 
105  if (light_coll > 1) light_coll = 1.; // To make sure you don't miraculously get more energy than you started with
106 
107  etotL = etotL + Edep_B/2 * exp(-dLeft/att_length) * light_coll;
108  etotR = etotR + Edep_B/2 * exp(-dRight/att_length) * light_coll;
109 
110  etotB = etotB + Edep[s]/2 * exp(-dLeft/att_length) * light_coll;
111  etotF = etotF + Edep[s]/2 * exp(-dRight/att_length) * light_coll;
112 
113  // cout << "step: " << s << " etotL, etotR, etotB, etotF: " << etotL << ", " << etotR << ", " << etotB << ", " << etotF << endl;
114 
115  // timeL= timeL + (times[s] + dLeft/veff) / nsteps;
116  // timeR= timeR + (times[s] + dRight/veff) / nsteps;
117 
118  timeL= timeL + (times[s] + dLeft/veff) / nsteps;
119  timeR= timeR + (times[s] + dRight/veff) / nsteps;
120 
121  timeB= timeB + (times[s] + dLeft/veff) / nsteps;
122  timeF= timeF + (times[s] + dRight/veff) / nsteps;
123 
124  if(etotL > 0.) {
125  if(s==0 || (time_min[0]>(times[s]+dLeft/veff))) time_min[0]=times[s]+dLeft/veff;
126  }
127  //.q cout << "min " << time_min[0] << "min " << times[s]+dLeft/veff << endl;
128  if(etotR > 0.) {
129  if(s==0 || (time_min[1]>(times[s]+dRight/veff))) time_min[1]=times[s]+ dRight/veff;
130  }
131 
132  if(etotB > 0.) {
133  if(s==0 || (time_min[2]>(times[s]+dLeft/veff))) time_min[2]=times[s]+ dLeft/veff;
134  }
135  if(etotF > 0.) {
136  if(s==0 || (time_min[3]>(times[s]+dRight/veff))) time_min[3]=times[s]+ dRight/veff;
137  }
138 
139  }
140 
141  double peL=G4Poisson(etotL*light_yield*sensor_qe);
142  double peR=G4Poisson(etotR*light_yield*sensor_qe);
143  double sigmaTL=sqrt(pow(0.2*nanosecond,2.)+pow(1.*nanosecond,2.)/(peL+1.));
144  double sigmaTR=sqrt(pow(0.2*nanosecond,2.)+pow(1.*nanosecond,2.)/(peR+1.));
145  // double sigmaTL=0;
146  // double sigmaTR=0;
147  TDCL=(int) ((time_min[0]+G4RandGauss::shoot(0.,sigmaTL)) * tdc_conv);
148  TDCR=(int) ((time_min[1]+G4RandGauss::shoot(0.,sigmaTR)) * tdc_conv);
149  if(TDCL<0) TDCL=0;
150  if(TDCR<0) TDCR=0;
151  ADCL=(int) (peL*sensor_gain*adc_conv + adc_ped);
152  ADCR=(int) (peR*sensor_gain*adc_conv + adc_ped);
153  // cout << "ADCL: " << ADCL << " " << peL << " " << sensor_gain << " " << adc_conv << endl;
154 
155 
156  double peB=G4Poisson(etotB*light_yield*sensor_qe);
157  double peF=G4Poisson(etotF*light_yield*sensor_qe);
158  double sigmaTB=sqrt(pow(0.2*nanosecond,2.)+pow(1.*nanosecond,2.)/(peB+1.));
159  double sigmaTF=sqrt(pow(0.2*nanosecond,2.)+pow(1.*nanosecond,2.)/(peF+1.));
160  // double sigmaTB=0;
161  // double sigmaTF=0;
162  TDCB=(int) ((time_min[2] + G4RandGauss::shoot(0.,sigmaTB)) * tdc_conv);
163  TDCF=(int) ((time_min[3] + G4RandGauss::shoot(0.,sigmaTF)) * tdc_conv);
164  if(TDCB<0) TDCB=0;
165  if(TDCF<0) TDCF=0;
166  ADCB=(int) (G4Poisson(etotB*light_yield*sensor_qe)*sensor_gain*adc_conv + adc_ped);
167  ADCF=(int) (G4Poisson(etotF*light_yield*sensor_qe)*sensor_gain*adc_conv + adc_ped);
168 
169  //cout << "energy right: " << ADCR / (adc_conv*sensor_gain*sensor_qe*light_yield) << " E left: " << ADCL / (adc_conv*sensor_gain*sensor_qe*light_yield) << endl;
170  //cout << "energy forw: " << ADCF / (adc_conv*sensor_gain*sensor_qe*light_yield) << " E back: " << ADCB / (adc_conv*sensor_gain*sensor_qe*light_yield) << endl;
171 
172  //cout << " Light collection: " << light_coll << endl;
173 
174  }
175  // closes (Etot > 0) loop
176 
177 
178  if(verbosity>4)
179  {
180  cout << log_msg << " layer: " << layer << ", paddle: " << paddle ;
181  cout << log_msg << " Etot=" << Etot/MeV << endl;
182  cout << log_msg << " TDCL=" << TDCL << " TDCR=" << TDCR << " ADCL=" << ADCL << " ADCR=" << ADCR << endl;
183  cout << log_msg << " TDCB=" << TDCB << " TDCF=" << TDCF << " ADCB=" << ADCB << " ADCF=" << ADCF << endl;
184  }
185 
186  dgtz["hitn"] = hitn;
187  dgtz["sector"] = sector;
188  dgtz["layer"] = layer;
189  dgtz["paddle"] = paddle;
190  dgtz["adcl"] = ADCL;
191  dgtz["adcr"] = ADCR;
192  dgtz["tdcl"] = TDCL;
193  dgtz["tdcr"] = TDCR;
194  dgtz["adcb"] = ADCB;
195  dgtz["adcf"] = ADCF;
196  dgtz["tdcb"] = TDCB;
197  dgtz["tdcf"] = TDCF;
198 
199  return dgtz;
200 }
201 
202 
203 vector<identifier> cormo_HitProcess :: processID(vector<identifier> id, G4Step *step, detector Detector)
204 {
205  id[id.size()-1].id_sharing = 1;
206  return id;
207 }
208 
209 
210 
211 double cormo_HitProcess::BirksAttenuation(double destep, double stepl, int charge, double birks)
212 {
213  //Example of Birk attenuation law in organic scintillators.
214  //adapted from Geant3 PHYS337. See MIN 80 (1970) 239-244
215  //
216  // Taken from GEANT4 examples advanced/amsEcal and extended/electromagnetic/TestEm3
217  //
218  double response = destep;
219  if (birks*destep*stepl*charge != 0.)
220  {
221  response = destep/(1. + birks*destep/stepl);
222  }
223  return response;
224 }
225 
226 
227 double cormo_HitProcess::BirksAttenuation2(double destep,double stepl,int charge,double birks)
228 {
229  //Extension of Birk attenuation law proposed by Chou
230  // see G.V. O'Rielly et al. Nucl. Instr and Meth A368(1996)745
231  //
232  //
233  double C=9.59*1E-4*mm*mm/MeV/MeV;
234  double response = destep;
235  if (birks*destep*stepl*charge != 0.)
236  {
237  response = destep/(1. + birks*destep/stepl + C*pow(destep/stepl,2.));
238  }
239  return response;
240 }
241 
242 
243 map< string, vector <int> > cormo_HitProcess :: multiDgt(MHit* aHit, int hitn)
244 {
245  map< string, vector <int> > MH;
246 
247  return MH;
248 }
249 
250 
251 
252 
253 
G4LogicalVolume * GetLogical()
Returns Logical Volume pointer.
Definition: detector.h:113
vector< identifier > processID(vector< identifier >, G4Step *, detector)
map< string, double > integrateDgt(MHit *, int)
double verbosity
vector< identifier > GetId()
Definition: Hit.h:103
map< string, vector< int > > multiDgt(MHit *, int)
vector< G4ThreeVector > GetLPos()
Definition: Hit.h:76
Definition: Hit.h:22
vector< double > GetTime()
Definition: Hit.h:89
double BirksAttenuation2(double, double, int, double)
double BirksAttenuation(double, double, int, double)
vector< double > GetEdep()
Definition: Hit.h:83
detector GetDetector()
Definition: Hit.h:108
vector< int > GetCharges()
Definition: Hit.h:116
vector< double > GetDx()
Definition: Hit.h:86