18 #include "G4Electron.hh"
19 #include "G4Positron.hh"
20 #include "G4PionPlus.hh"
21 #include "G4PionMinus.hh"
24 #include "G4ParticleTable.hh"
27 #include "CLHEP/Random/RandFlat.h"
33 #include "G4SDManager.hh"
40 const Gaudi::Property<std::string>& randomEngineName,
46 const Gaudi::Property<std::string>& CaloCellContainerSDName,
47 const Gaudi::Property<bool>& doG4Transport,
48 const Gaudi::Property<bool>& doPhotons,
49 const Gaudi::Property<bool>& doElectrons,
50 const Gaudi::Property<bool>& doHadrons,
51 const Gaudi::Property<float>& AbsEtaMin,
52 const Gaudi::Property<float>& AbsEtaMax,
53 const Gaudi::Property<float>& EkinMinPhotons,
54 const Gaudi::Property<float>& EkinMaxPhotons,
55 const Gaudi::Property<float>& EkinMinElectrons,
56 const Gaudi::Property<float>& EkinMaxElectrons,
57 const Gaudi::Property<bool>& doEMECFCS,
58 const Gaudi::Property<bool>& doPunchThrough,
61 : G4VFastSimulationModel(
name),
62 m_rndmGenSvc(rndmGenSvc), m_randomEngineName(randomEngineName),
67 m_FastCaloSimSvc(FastCaloSimSvc),
68 m_CaloCellContainerSDName(CaloCellContainerSDName),
69 m_doG4Transport(doG4Transport),
70 m_doPhotons(doPhotons),
71 m_doElectrons(doElectrons),
72 m_doHadrons(doHadrons),
73 m_AbsEtaMin(AbsEtaMin),
74 m_AbsEtaMax(AbsEtaMax),
75 m_EkinMinPhotons(EkinMinPhotons),
76 m_EkinMaxPhotons(EkinMaxPhotons),
77 m_EkinMinElectrons(EkinMinElectrons),
78 m_EkinMaxElectrons(EkinMaxElectrons),
79 m_doEMECFCS(doEMECFCS),
80 m_doPunchThrough(doPunchThrough),
105 bool isPositron = &
particleType == G4Positron::PositronDefinition();
112 const std::string pName =
particleType.GetParticleName();
113 G4cout<<
"[FastCaloSim::IsApplicable] Got " << pName <<G4endl;
114 if(isApplicable) G4cout<<
"[FastCaloSim::IsApplicable] APPLICABLE"<<G4endl;
115 else G4cout<<
"[FastCaloSim::IsApplicable] NOT APPLICABLE"<<G4endl;
126 G4cout<<
"[FastCaloSim::ModelTrigger] Got particle with " <<
"\n"
127 <<
" pdg=" <<fastTrack.GetPrimaryTrack() -> GetDefinition()->GetPDGEncoding() <<
"\n"
128 <<
" Ekin="<<fastTrack.GetPrimaryTrack() -> GetKineticEnergy() <<
"\n"
129 <<
" p=" <<fastTrack.GetPrimaryTrack() -> GetMomentum().mag() <<
"\n"
130 <<
" x=" <<fastTrack.GetPrimaryTrack() -> GetPosition().x() <<
"\n"
131 <<
" y=" <<fastTrack.GetPrimaryTrack() -> GetPosition().y() <<
"\n"
132 <<
" z=" <<fastTrack.GetPrimaryTrack() -> GetPosition().z() <<
"\n"
133 <<
" r=" <<fastTrack.GetPrimaryTrack() -> GetPosition().perp() <<
"\n"
134 <<
" eta=" <<fastTrack.GetPrimaryTrack() -> GetMomentum().eta() <<
"\n"
135 <<
" phi=" <<fastTrack.GetPrimaryTrack() -> GetMomentum().phi() <<
"\n"
140 const G4ParticleDefinition * G4Particle = fastTrack.GetPrimaryTrack() -> GetDefinition();
142 const float Ekin = fastTrack.GetPrimaryTrack() -> GetKineticEnergy();
144 const float eta_pos = (fastTrack.GetPrimaryTrack() -> GetPosition()).
eta();
147 bool isPhoton = G4Particle == G4Gamma::Definition();
148 bool isElectron = G4Particle == G4Electron::Definition();
149 bool isPositron = G4Particle == G4Positron::Definition();
150 bool isPionPlus = G4Particle == G4PionPlus::Definition();
151 bool isPionMinus = G4Particle == G4PionMinus::Definition();
160 if (!(withinEtaRange && (withinEkinRangePhotons || withinEkinRangeElectrons))) {
162 G4cout<<
"[FastCaloSim::ModelTrigger] Model not triggered"<<G4endl;
168 if (fastTrack.GetPrimaryTrack() -> GetKineticEnergy() < 0.05) {
170 G4cout<<
"[FastCaloSim::ModelTrigger] Particle below 50 keV threshold. Passing to G4. "<<G4endl;
178 G4cout<<
"[FastCaloSim::ModelTrigger] Particle failed passedIDCaloBoundary z="<<fastTrack.GetPrimaryTrack() -> GetPosition().z()<<
" r="<<fastTrack.GetPrimaryTrack() -> GetPosition().perp()<<G4endl;
184 float minEkinPions = 200;
185 float minEkinOtherHadrons = 400;
190 G4cout<<
"[FastCaloSim::ModelTrigger] Model triggered"<<G4endl;
196 if (isPionPlus || isPionMinus){
197 bool passMinEkinPions = Ekin > minEkinPions;
200 if(passMinEkinPions) G4cout<<
"[FastCaloSim::ModelTrigger] Model triggered"<<G4endl;
201 else G4cout<<
"[FastCaloSim::ModelTrigger] Pion with Ekin="<<Ekin<<
" below the minimum "<<minEkinPions<<
" MeV threshold. Model not triggered."<<G4endl;
204 return passMinEkinPions;
209 bool passMinEkinOtherHadrons = Ekin > minEkinOtherHadrons;
212 if(passMinEkinOtherHadrons) G4cout<<
"[FastCaloSim::ModelTrigger] Model triggered"<<G4endl;
213 else G4cout<<
"[FastCaloSim::ModelTrigger] Other hadron with Ekin="<<Ekin<<
" below the minimum "<<minEkinOtherHadrons<<
" MeV threshold. Model not triggered."<<G4endl;
216 return passMinEkinOtherHadrons;
227 const G4Track * G4PrimaryTrack = fastTrack.GetPrimaryTrack();
229 const G4ParticleDefinition * G4Particle = G4PrimaryTrack -> GetDefinition();
231 signed int pdgID = G4Particle -> GetPDGEncoding();
234 if(G4PrimaryTrack -> GetKineticEnergy() < 10){
236 G4cout<<
"[FastCaloSim::DoIt] Skipping particle with Ekin: " << G4PrimaryTrack -> GetKineticEnergy() <<
" MeV. Below the 10 MeV threshold"<<G4endl;
238 fastStep.KillPrimaryTrack();
242 if(G4Particle == G4Electron::Definition() || G4Particle == G4Positron::Definition() || G4Particle == G4Gamma::Definition())
249 truthState.
set_pdgid(G4PionPlus::Definition() -> GetPDGEncoding());
253 truthState.SetPtEtaPhiM(G4PrimaryTrack -> GetMomentum().
perp(),
254 G4PrimaryTrack -> GetMomentum().
eta(),
255 G4PrimaryTrack -> GetMomentum().
phi(),
256 G4Particle -> GetPDGMass());
259 truthState.
set_vertex(G4PrimaryTrack -> GetPosition().
x(),
260 G4PrimaryTrack -> GetPosition().
y(),
261 G4PrimaryTrack -> GetPosition().
z());
267 if(pdgID == -2212 || pdgID == -2112) truthState.
set_Ekin_off(2 * G4Particle -> GetPDGMass());
280 G4cout<<
"[FastCaloSim::DoIt] Killing particle as extrapolation failed"<<G4endl;
282 fastStep.KillPrimaryTrack();
286 if(
m_FastCaloSimSvc->simulate(simState, &truthState, &extrapolState).isFailure()){
287 G4Exception(
"FastCaloSimSvc",
"FailedSimulationCall", FatalException,
"FastCaloSimSvc: Simulation call failed.");
292 G4cout<<
"[FastCaloSim::DoIt] pdgID of G4PrimaryTrack: " << pdgID << G4endl;
293 G4cout<<
"[FastCaloSim::DoIt] Energy returned: " << simState.
E() << G4endl;
294 G4cout<<
"[FastCaloSim::DoIt] Energy fraction for layer: " << G4endl;
295 for (
int s = 0;
s < 24;
s++) G4cout<<
"[FastCaloSim::DoIt] Sampling " <<
s <<
" energy " << simState.
E(
s) << G4endl;
306 G4ParticleTable *ptable = G4ParticleTable::GetParticleTable();
309 const double simE = simState.
E();
312 std::vector<double> simEfrac;
313 for (
unsigned int i = 0;
i < 24;
i++){simEfrac.push_back(simState.
Efrac(
i));}
323 fastStep.KillPrimaryTrack();
324 fastStep.SetPrimaryTrackPathLength(0.0);
329 G4SDManager *sdm = G4SDManager::GetSDMpointer();
333 G4Exception(
"FastCaloSimSvc",
"FailedFindSensitiveDetector", FatalException,
"FastCaloSimSvc: Failed getting CaloCellContainer SD.");
339 if (!caloCellContainerSD){
340 G4Exception(
"FastCaloSimSvc",
"FailedCastSensitiveDetector", FatalException,
"FastCaloSimSvc: Failed casting G4VSensitiveDetector.");
343 return caloCellContainerSD;
360 const float barrelR = 1148;
361 const float barrelZ = 3549.5;
363 const float innerBeamPipeR = 120;
364 const float innerBeamPipeZ = 4587;
366 const float outerBeamPipeR = 41;
367 const float outerBeamPipeZ = 6783;
370 const G4ThreeVector particlePosition = fastTrack.GetPrimaryTrack() -> GetPosition();
372 const float r = particlePosition.perp();
373 const float z = particlePosition.z();
375 const G4ThreeVector particleDirection = fastTrack.GetPrimaryTrack() -> GetMomentum();
377 const G4ThreeVector helperLine = particlePosition + particleDirection;
381 const float triggerTolerance = 50;
384 if (std::abs(
z) <= barrelZ + triggerTolerance) {
385 if (
r >= barrelR &&
r < barrelR + triggerTolerance)
return helperLine.perp() >= barrelR;
388 if (std::abs(
z) >= barrelZ && std::abs(
z) <= innerBeamPipeZ + triggerTolerance){
389 if (
r >= innerBeamPipeR &&
r < innerBeamPipeR + triggerTolerance)
return helperLine.perp() >= innerBeamPipeR;
391 if (std::abs(
z) >= innerBeamPipeZ && std::abs(
z) <= outerBeamPipeZ){
392 if (
r >= outerBeamPipeR &&
r < outerBeamPipeR + triggerTolerance)
return helperLine.perp() >= outerBeamPipeR;
395 if (
r >= outerBeamPipeR &&
r<= innerBeamPipeR){
396 if (std::abs(
z) >= innerBeamPipeZ && std::abs(
z) < innerBeamPipeZ + triggerTolerance)
return std::abs(helperLine.z()) >= innerBeamPipeZ;
399 if (
r >= innerBeamPipeR &&
r <= barrelR){
400 if (std::abs(
z) >= barrelZ && std::abs(
z) < barrelZ + triggerTolerance)
return std::abs(helperLine.z()) >= barrelZ;