BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
BesTofDigitizerEcV2.cc
Go to the documentation of this file.
1//---------------------------------------------------------------------------//
2//// BOOST --- BESIII Object_Oriented Simulation Tool //
3////---------------------------------------------------------------------------//
4////Description:
5////Author: Dengzy
6////Created: Mar, 2004
7////Modified:
8////Comment:
9////---------------------------------------------------------------------------//
10////$Id: BesTofDigitizerEcV2.cc
11
12#include "TofSim/BesTofDigitizerEcV2.hh"
13#include "G4DigiManager.hh"
14#include "G4Poisson.hh"
15#include "G4RunManager.hh"
16#include "G4Svc/IG4Svc.h"
17#include "GaudiKernel/Bootstrap.h"
18#include "GaudiKernel/IDataProviderSvc.h"
19#include "GaudiKernel/ISvcLocator.h"
20#include "Randomize.hh"
21#include "TofSim/BesTofDigi.hh"
22#include "TofSim/BesTofGeoParameter.hh"
23#include "TofSim/BesTofHit.hh"
24// #include "G4Svc/G4Svc.h"
25#include "G4PhysicalConstants.hh"
26#include "G4SystemOfUnits.hh"
27
29 ReadData();
30 m_timeBinSize = 0.005;
31
32 // retrieve G4Svc
33 ISvcLocator* svcLocator = Gaudi::svcLocator();
34 IG4Svc* tmpSvc;
35 StatusCode sc = svcLocator->service( "G4Svc", tmpSvc );
36 m_G4Svc = tmpSvc;
37}
38
41
42 m_ecR1 = tofPara->GetEcR1();
43 m_tau1Ec = tofPara->GetTau1Ec();
44 m_tau2Ec = tofPara->GetTau2Ec();
45 m_tau3Ec = tofPara->GetTau3Ec();
46 m_tauRatioEc = tofPara->GetTauRatioEc();
47 m_refIndexEc = tofPara->GetRefIndexEc();
48 m_phNConstEc = tofPara->GetPhNConstEc();
49 m_Cpe2pmtEc = tofPara->GetCpe2pmtEc();
50 m_rAngleEc = tofPara->GetRAngleEc();
51 m_QEEc = tofPara->GetQEEc();
52 m_CEEc = tofPara->GetCEEc();
53 m_peCorFacEc = tofPara->GetPeCorFacEc();
54 m_attenEc = tofPara->GetAttenEc();
55
56 m_ttsMeanEc = tofPara->GetTTSmeanEc();
57 m_ttsSigmaEc = tofPara->GetTTSsigmaEc();
58 m_PMTgainEc = tofPara->GetPMTgainEc();
59 m_CeEc = tofPara->GetCeEc();
60 m_riseTimeEc = tofPara->GetRiseTimeEc();
61 m_LLthreshEc = tofPara->GetLLthreshEc();
62 m_HLthreshEc = tofPara->GetHLthreshEc();
63 m_preGainEc = tofPara->GetPreGainEc();
64 m_noiseSigmaEc = tofPara->GetNoiseSigmaEc();
65}
66
68
70 m_beamTime = m_G4Svc->GetBeamTime() * ns;
72
73 G4DigiManager* digiManager = G4DigiManager::GetDMpointer();
74
75 G4int THCID = digiManager->GetHitsCollectionID( "BesTofHitsCollection" );
76 m_THC = (BesTofHitsCollection*)( digiManager->GetHitsCollection( THCID ) );
77
78 if ( m_THC )
79 {
80 // for each digi, compute TDC and ADC
81 G4int partId, scinNb, nHits;
82 G4double edep;
83 BesTofHit* hit;
84 partId = scint->GetPartId();
85 scinNb = scint->GetScinNb();
86 edep = scint->GetEdep();
87 nHits = scint->GetHitIndexes()->size();
88
89 TofPmtInit();
90
91 if ( edep > 0.01 )
92 {
93 for ( G4int j = 0; j < nHits; j++ )
94 {
95 hit = ( *m_THC )[( *( scint->GetHitIndexes() ) )[j]];
96 TofPmtAccum( hit );
97 }
98
99 // get final tdc and adc
100 TofPmtRspns( partId );
101
102 G4double temp0 = m_ADC[0] + m_TDC[0];
103 G4double temp1 = m_ADC[1] + m_TDC[1];
104 if ( ( partId == 1 && temp0 > 0 && temp1 > 0 ) || ( ( partId != 1 ) && temp0 > 0 ) )
105 {
106 if ( m_ADC[0] > 1000 ) m_ADC[0] = 1000;
107 if ( m_ADC[1] > 1000 ) m_ADC[1] = 1000;
108 BesTofDigi* digi = new BesTofDigi;
110 digi->SetPartId( partId );
111 digi->SetScinNb( scinNb );
112 digi->SetForwADC( m_ADC[0] );
113 digi->SetBackADC( m_ADC[1] );
114 if ( m_TDC[0] != -999 ) m_TDC[0] = m_TDC[0] + m_beamTime;
115 if ( m_TDC[1] != -999 ) m_TDC[1] = m_TDC[1] + m_beamTime;
116 digi->SetForwTDC( m_TDC[0] );
117 digi->SetBackTDC( m_TDC[1] );
118 m_besTofDigitsCollection->insert( digi );
119 }
120 }
121 }
122}
123
125 m_trackIndex = -999;
126 m_globalTime = 9999;
127 m_t1st[0] = 100;
128 m_t1st[1] = 100;
129 m_tLast[0] = 0.;
130 m_tLast[1] = 0;
131 m_totalPhot[0] = 0;
132 m_totalPhot[1] = 0;
133 for ( G4int i = 0; i < 2; i++ )
134 for ( G4int j = 0; j < m_profBinNEcV2; j++ ) m_nPhot[j][i] = 0;
135}
136
138 G4double cvelScint = c_light / m_refIndexEc;
139 // Get information of this step
140 G4ThreeVector pos = hit->GetPos();
141 G4int trackIndex = hit->GetTrackIndex();
142 G4int partId = hit->GetPartId();
143 G4double edep = hit->GetEdep();
144 G4double stepL = hit->GetStepL();
145 G4double deltaT = hit->GetDeltaT();
146 G4double timeFlight = hit->GetTime() - m_beamTime;
147 if ( timeFlight < m_globalTime )
148 {
149 m_globalTime = timeFlight;
150 m_trackIndex = trackIndex;
151 }
152
153 G4ThreeVector pDirection = hit->GetPDirection();
154 G4double nx = pDirection.x();
155 G4double ny = pDirection.y();
156 G4double nz = pDirection.z();
157
158 // Cpe2pmt=cathode area/scint area
159 // peCorFac=correction factor for eff. of available Npe
160
161 // number of photons generated in this step
162 G4int NphStep;
163 NphStep = G4int( edep * m_phNConstEc * m_Cpe2pmtEc * 0.66 * m_QEEc * m_CEEc * m_peCorFacEc );
164
165 G4double ddS, ddT;
166 if ( NphStep > 0 )
167 {
168 for ( G4int i = 0; i < NphStep; i++ )
169 {
170 // uniform scintilation in each step
171 ddS = stepL * G4UniformRand();
172 ddT = deltaT * G4UniformRand();
173 G4ThreeVector emtPos;
174 emtPos.setX( pos.x() + nx * ddS );
175 emtPos.setY( pos.y() + ny * ddS );
176 emtPos.setZ( pos.z() + nz * ddS );
177
178 // check scinillation light whether to hit the pmt or not
179 // forb=0/1 for forward(z>0, east) and backward(z<0, west)
180 G4double pathL = 0;
181 G4int forb;
182 DirectPh( partId, emtPos, pathL, forb );
183
184 // check if photon can reach PMT or not, after attenuation
185 G4double ran = G4UniformRand();
186 if ( pathL > 0 && exp( -pathL / m_attenEc ) > ran )
187 {
188 // propagation time in scintillator
189 G4double scinSwim = pathL / cvelScint;
190 // scintillation timing
191 // G4double scinTime=GenPhoton(partId);
192 G4double scinTime = Scintillation( partId );
193
194 // PMT transit time
195 G4double transitTime = TransitTime();
196 // sum up all time components
197 G4double endTime = timeFlight + ddT + scinSwim + scinTime + transitTime;
198
199 // store timing into binned buffer
200 AccuSignal( endTime, forb );
201
202 // update 1st and last timings here
203 if ( m_t1st[forb] > endTime ) m_t1st[forb] = endTime;
204 if ( m_tLast[forb] < endTime ) m_tLast[forb] = endTime;
205 }
206 }
207 }
208}
209
210void BesTofDigitizerEcV2::DirectPh( G4int partId, G4ThreeVector emtPos, G4double& pathL,
211 G4int& forb ) {
212 // generation photon have random direction
213 // optical parameters of scintillation simulation
214 // G4double cos_spanEc = 1-1/m_refIndex;
215 G4double cos_spanEc = 1;
216 G4double ran;
217 // dcos=cos_span*(ran*2.0-1.0);
218 ran = G4UniformRand();
219 // assuming uniform phi distribution, simulate cos distr only
220 G4double dcosEc = cos_spanEc * ( ran * 2.0 - 1.0 );
221 G4double r2 = sqrt( emtPos.x() * emtPos.x() + emtPos.y() * emtPos.y() );
222 if ( dcosEc > 0.0 && dcosEc != 1 )
223 {
224 forb = 0; // forward
225 pathL = ( r2 - m_ecR1 ) / ( 1.0 - dcosEc );
226 }
227 else if ( dcosEc < 0 && dcosEc != -1 )
228 {
229 forb = 0;
230 pathL = ( 2 * 838 - r2 - m_ecR1 ) / ( 1.0 + dcosEc );
231 }
232}
233
234G4double BesTofDigitizerEcV2::Scintillation( G4int partId ) {
235 G4double tmp_tauRatio, tmp_tau1, tmp_tau2, tmp_tau3;
236 tmp_tauRatio = m_tauRatioEc;
237 tmp_tau1 = m_tau1Ec;
238 tmp_tau2 = m_tau2Ec;
239 tmp_tau3 = m_tau3Ec;
240
241 G4double UniformR = tmp_tauRatio / ( 1 + tmp_tauRatio );
242 G4double EmissionTime;
243 if ( G4UniformRand() > UniformR )
244 {
245 while ( 1 )
246 {
247 EmissionTime = -tmp_tau2 * log( G4UniformRand() );
248 if ( G4UniformRand() - exp( EmissionTime / tmp_tau2 - EmissionTime / tmp_tau1 ) > 1.E-8 )
249 break;
250 }
251 }
252 else EmissionTime = -tmp_tau3 * log( G4UniformRand() );
253 return EmissionTime;
254}
255
256/*G4double BesTofDigitizerEcV2::GenPhoton(G4int partId)
257{
258 //get scintilation time
259 G4double scinTime;
260 static G4double scinA[26000];
261 G4double random[2];
262 G4double inverseRegion, ran1, ran2, problive;
263 static G4int istore=-1;
264 if(istore<0)
265 {
266 istore=1;
267 for(G4int i=0;i<26000;i++)
268 scinA[i]=Scintillation( (i+1) *0.001 , partId);
269 }
270 while(1)
271 {
272 HepRandom::getTheEngine()->flatArray(2, random);
273 inverseRegion=random[0]*2.00975218688231;
274 ran1=-4.5*log(1-inverseRegion/(0.45*4.5));
275 ran2=0.45*exp(-1.*ran1/4.5)*random[1];
276 problive=scinA[G4int(ran1*1000)+1];
277 if(problive>=ran2)
278 { scinTime=ran1; break; }
279 }
280 return scinTime;
281}*/
282
284 // get time transit spread
285 return G4RandGauss::shoot( m_ttsMeanEc, m_ttsSigmaEc );
286}
287
288void BesTofDigitizerEcV2::AccuSignal( G4double endTime, G4int forb ) {
289 G4int ihst;
290 ihst = G4int( endTime / m_timeBinSize );
291 if ( ihst > 0 && ihst < m_profBinNEcV2 )
292 {
293 m_nPhot[ihst][forb] = m_nPhot[ihst][forb] + 1;
294 m_totalPhot[forb] = m_totalPhot[forb] + 1;
295 }
296}
297
299 // to generate PMT signal shape for single photoelectron.
300 // only one time for a job.
301 static G4double snpe[m_snpeBinNEcV2];
302 static G4int istore_snpe = -1;
303
304 // Model: f(t)=Gain*mv_1pe* t**2 * exp-(t/tau)**2/normal-const
305 // normalization const =sqrt(pi)*tau*tau*tau/4.0
306 G4double tau = m_riseTimeEc;
307 G4double norma_const = sqrt( M_PI ) * tau * tau * tau / 4.0; // in unit of ns**3
308 G4double echarge = 1.6e-7; // in unit of PC
309
310 // time profile of pmt signals for Back and Forward PMT.
311 G4double profPmt[m_profBinNEcV2][2];
312
313 G4double t;
314 G4int n1, n2, ii;
315 G4int phtn;
316
317 if ( istore_snpe < 0 )
318 {
319 istore_snpe = 1;
320 for ( G4int i = 0; i < m_snpeBinNEcV2; i++ )
321 {
322 t = ( i + 1 ) * m_timeBinSize;
323 snpe[i] = m_PMTgainEc * m_CeEc * t * t * exp( -( t / tau ) * ( t / tau ) ) / norma_const;
324 }
325 }
326 // for barrel and endcap tof: fb=2 or 1
327 G4int fb = 1;
328
329 for ( G4int j = 0; j < 2; j++ )
330 {
331 m_TDC[j] = -999.0;
332 m_ADC[j] = -999.0;
333 }
334 for ( G4int j = 0; j < fb; j++ )
335 {
336 if ( m_totalPhot[j] > 0 )
337 {
338 n1 = G4int( m_t1st[j] / m_timeBinSize );
339 n2 = G4int( m_tLast[j] / m_timeBinSize );
340
341 for ( G4int i = 0; i < m_profBinNEcV2; i++ ) profPmt[i][j] = 0.0;
342
343 // generate PMT pulse
345 for ( G4int i = n1; i < n2; i++ )
346 {
347 phtn = m_nPhot[i][j];
348 if ( phtn > 0 )
349 {
350 for ( G4int ihst = 0; ihst < m_snpeBinNEcV2; ihst++ )
351 {
352 ii = i + ihst;
353 if ( ii < m_profBinNEcV2 ) profPmt[ii][j] += phtn * snpe[ihst];
354 }
355 }
356 }
357
358 // add preamplifier and noise
359 for ( int i = 0; i < m_profBinNEcV2; i++ )
360 {
361 if ( profPmt[i][j] > 0 )
362 profPmt[i][j] =
363 m_preGainEc * profPmt[i][j] + G4RandGauss::shoot( 0, m_noiseSigmaEc );
364 }
365
366 // get pulse height
367 G4double max = 0;
368 for ( int i = 0; i < m_profBinNEcV2; i++ )
369 {
370 if ( profPmt[i][j] > max ) max = profPmt[i][j];
371 }
372
373 G4double tmp_HLthresh, tmp_LLthresh;
374 if ( partId == 1 )
375 {
376 tmp_HLthresh = m_HLthreshEc;
377 tmp_LLthresh = m_LLthreshEc;
378 }
379 else
380 {
381 tmp_HLthresh = m_HLthreshEc;
382 tmp_LLthresh = m_LLthreshEc;
383 }
384
385 // get final tdc and adc
386 if ( max >= tmp_HLthresh )
387 {
388 for ( int i = 0; i < m_profBinNEcV2; i++ )
389 {
390 if ( profPmt[i][j] >= tmp_LLthresh )
391 {
392 m_TDC[j] = i * m_timeBinSize;
393 m_ADC[j] = m_preGainEc * m_totalPhot[j] * echarge * m_PMTgainEc;
394 break;
395 }
396 }
397 }
398 }
399 }
400}
#define max(a, b)
EvtComplex exp(const EvtComplex &c)
G4TDigiCollection< BesTofDigi > BesTofDigitsCollection
G4THitsCollection< BesTofHit > BesTofHitsCollection
int n2
Definition SD0Tag.cxx:59
int n1
Definition SD0Tag.cxx:58
#define M_PI
Definition TConstant.h:4
void AccuSignal(G4double, G4int)
G4double Scintillation(G4int)
void DirectPh(G4int, G4ThreeVector, G4double &, G4int &)
virtual void Digitize(ScintSingle *, BesTofDigitsCollection *)
void TofPmtAccum(BesTofHit *)
static BesTofGeoParameter * GetInstance()
int t()
Definition t.c:1
#define ns(x)
Definition xmltok.c:1355