ATLAS Offline Software
FastCaloSim.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Header include
6 #include "FastCaloSim.h"
7 
8 // FastCaloSim includes
12 
13 // Random generator includes
15 
16 // Geant4 particle includes
17 #include "G4Gamma.hh"
18 #include "G4Electron.hh"
19 #include "G4Positron.hh"
20 #include "G4PionPlus.hh"
21 #include "G4PionMinus.hh"
22 
23 // HepMCHelpers include
25 
26 // G4 sensitive detector includes
27 #include "G4SDManager.hh"
29 
30 #undef FCS_DEBUG
31 
32 
33 
34 FastCaloSim::FastCaloSim(const std::string& name,
35  const ServiceHandle<IAthRNGSvc>& rndmGenSvc,
36  const Gaudi::Property<std::string>& randomEngineName,
37  const PublicToolHandle<IFastCaloSimCaloTransportation>& FastCaloSimCaloTransportation,
38  const PublicToolHandle<IFastCaloSimCaloExtrapolation>& FastCaloSimCaloExtrapolation,
39  const PublicToolHandle<IG4CaloTransportTool>& G4CaloTransportTool,
40  const ServiceHandle<ISF::IFastCaloSimParamSvc>& FastCaloSimSvc,
41  const Gaudi::Property<std::string>& CaloCellContainerSDName,
42  const Gaudi::Property<bool>& doG4Transport,
44 
45 : G4VFastSimulationModel(name),
46  m_rndmGenSvc(rndmGenSvc), m_randomEngineName(randomEngineName),
47  m_FastCaloSimCaloTransportation(FastCaloSimCaloTransportation),
48  m_FastCaloSimCaloExtrapolation(FastCaloSimCaloExtrapolation),
49  m_G4CaloTransportTool(G4CaloTransportTool),
50  m_FastCaloSimSvc(FastCaloSimSvc),
51  m_CaloCellContainerSDName(CaloCellContainerSDName),
52  m_doG4Transport(doG4Transport),
53  m_FastCaloSimTool(FastCaloSimTool)
54 {
55 }
56 
57 void FastCaloSim::StartOfAthenaEvent(const EventContext& ctx ){
58 
61 
62 
63  return;
64 }
65 
66 void FastCaloSim::EndOfAthenaEvent(const EventContext&){
67 
68 
69  return;
70 }
71 
72 
73 G4bool FastCaloSim::IsApplicable(const G4ParticleDefinition& particleType)
74 {
75  // Check whether we can simulate the particle with FastCaloSim
76  bool isPhoton = &particleType == G4Gamma::GammaDefinition();
77  bool isElectron = &particleType == G4Electron::ElectronDefinition();
78  bool isPositron = &particleType == G4Positron::PositronDefinition();
79  bool isHadron = MC::isHadron(particleType.GetPDGEncoding());
80 
81  // FastCaloSim is applicable if it is photon, electron, positron or any hadron
82  bool IsApplicable = isPhoton || isElectron || isPositron || isHadron;
83 
84  #ifdef FCS_DEBUG
85  const std::string pName = particleType.GetParticleName();
86  G4cout<< "[FastCaloSim::IsApplicable] Got " << pName <<G4endl;
87  if(IsApplicable) G4cout<<"[FastCaloSim::IsApplicable] APPLICABLE"<<G4endl;
88  else G4cout<<"[FastCaloSim::IsApplicable] NOT APPLICABLE"<<G4endl;
89  #endif
90 
91 
92  return IsApplicable;
93 }
94 
95 G4bool FastCaloSim::ModelTrigger(const G4FastTrack& fastTrack)
96 {
97 
98  #ifdef FCS_DEBUG
99  G4cout<<"[FastCaloSim::ModelTrigger] Got particle with " <<"\n"
100  <<" pdg=" <<fastTrack.GetPrimaryTrack() -> GetDefinition()->GetPDGEncoding() <<"\n"
101  <<" Ekin="<<fastTrack.GetPrimaryTrack() -> GetKineticEnergy() <<"\n"
102  <<" p=" <<fastTrack.GetPrimaryTrack() -> GetMomentum().mag() <<"\n"
103  <<" x=" <<fastTrack.GetPrimaryTrack() -> GetPosition().x() <<"\n"
104  <<" y=" <<fastTrack.GetPrimaryTrack() -> GetPosition().y() <<"\n"
105  <<" z=" <<fastTrack.GetPrimaryTrack() -> GetPosition().z() <<"\n"
106  <<" r=" <<fastTrack.GetPrimaryTrack() -> GetPosition().perp() <<"\n"
107  <<" eta=" <<fastTrack.GetPrimaryTrack() -> GetMomentum().eta() <<"\n"
108  <<" phi=" <<fastTrack.GetPrimaryTrack() -> GetMomentum().phi() <<"\n"
109  <<G4endl;
110  #endif
111 
112 
113  // Simulate particles below 50 keV with Geant4 to have same config as ISF implementation
114  if (fastTrack.GetPrimaryTrack() -> GetKineticEnergy() < 0.05) {
115  #ifdef FCS_DEBUG
116  G4cout<<"[FastCaloSim::ModelTrigger] Particle below 50 keV threshold. Passing to G4. "<<G4endl;
117  #endif
118  return false;
119  }
120 
121  // Check if triggered particle is really on the ID-Calo (parametrization) boundary
122  if (!passedIDCaloBoundary(fastTrack)) {
123  #ifdef FCS_DEBUG
124  G4cout<<"[FastCaloSim::ModelTrigger] Particle failed passedIDCaloBoundary z="<<fastTrack.GetPrimaryTrack() -> GetPosition().z()<<" r="<<fastTrack.GetPrimaryTrack() -> GetPosition().perp()<<G4endl;
125  #endif
126  return false;
127  }
128 
129  // Set minimum kinetic energy of pions and other hadrons required to be passed to FastCaloSim
130  float minEkinPions = 200;
131  float minEkinOtherHadrons = 400;
132 
133  // Get particle definition
134  const G4ParticleDefinition * G4Particle = fastTrack.GetPrimaryTrack() -> GetDefinition();
135  // Get particle kinetic energy
136  const float Ekin = fastTrack.GetPrimaryTrack() -> GetKineticEnergy();
137 
138  // Check particle type
139  bool isPhoton = G4Particle == G4Gamma::Definition();
140  bool isElectron = G4Particle == G4Electron::Definition();
141  bool isPositron = G4Particle == G4Positron::Definition();
142  bool isPionPlus = G4Particle == G4PionPlus::Definition();
143  bool isPionMinus = G4Particle == G4PionMinus::Definition();
144 
145  // Pass all photons, electrons and positrons to FastCaloSim
146  if (isPhoton || isElectron || isPositron){
147  #ifdef FCS_DEBUG
148  G4cout<<"[FastCaloSim::ModelTrigger] Model triggered"<<G4endl;
149  #endif
150  return true;
151  }
152 
153  // Require minimum kinetic energy of pions needed to be passed to FastCaloSim
154  if (isPionPlus || isPionMinus){
155  bool passMinEkinPions = Ekin > minEkinPions;
156 
157  #ifdef FCS_DEBUG
158  if(passMinEkinPions) G4cout<<"[FastCaloSim::ModelTrigger] Model triggered"<<G4endl;
159  else G4cout<<"[FastCaloSim::ModelTrigger] Pion with Ekin="<<Ekin<<" below the minimum "<<minEkinPions<<" MeV threshold. Model not triggered."<<G4endl;
160  #endif
161 
162  return passMinEkinPions;
163 
164  }
165 
166  // Require minimum kinetic energy of other hadrons needed to be passed to FastCaloSim
167  bool passMinEkinOtherHadrons = Ekin > minEkinOtherHadrons;
168 
169  #ifdef FCS_DEBUG
170  if(passMinEkinOtherHadrons) G4cout<<"[FastCaloSim::ModelTrigger] Model triggered"<<G4endl;
171  else G4cout<<"[FastCaloSim::ModelTrigger] Other hadron with Ekin="<<Ekin<<" below the minimum "<<minEkinOtherHadrons<<" MeV threshold. Model not triggered."<<G4endl;
172  #endif
173 
174  return passMinEkinOtherHadrons;
175 }
176 
177 void FastCaloSim::DoIt(const G4FastTrack& fastTrack, G4FastStep& fastStep)
178 {
179 
181  TFCSTruthState truthState;
182  TFCSExtrapolationState extrapolState;
183 
184  // Get Geant4 primary track
185  const G4Track * G4PrimaryTrack = fastTrack.GetPrimaryTrack();
186  // Get Geant4 particle definition
187  const G4ParticleDefinition * G4Particle = G4PrimaryTrack -> GetDefinition();
188  // Get Geant4 particle pdgID
189  signed int pdgID = G4Particle -> GetPDGEncoding();
190 
191  // Do not simulate particles below 10 MeV
192  if(G4PrimaryTrack -> GetKineticEnergy() < 10){
193  #ifdef FCS_DEBUG
194  G4cout<<"[FastCaloSim::DoIt] Skipping particle with Ekin: " << G4PrimaryTrack -> GetKineticEnergy() <<" MeV. Below the 10 MeV threshold"<<G4endl;
195  #endif
196  fastStep.KillPrimaryTrack();
197  return;
198  }
199  // Decide on which FastCaloSim parametrization to use (electron, photon or pion)
200  if(G4Particle == G4Electron::Definition() || G4Particle == G4Positron::Definition() || G4Particle == G4Gamma::Definition())
201  {
202  // Use egamma parametrization for simulation of electrons and photons
203  truthState.set_pdgid(pdgID);
204  }
205  else{
206  // Use pion parametrization for simulation of all hadrons
207  truthState.set_pdgid(G4PionPlus::Definition() -> GetPDGEncoding());
208  }
209 
210  // Set the kinematics of the FastCaloSim truth state
211  truthState.SetPtEtaPhiM(G4PrimaryTrack -> GetMomentum().perp(),
212  G4PrimaryTrack -> GetMomentum().eta(),
213  G4PrimaryTrack -> GetMomentum().phi(),
214  G4Particle -> GetPDGMass());
215 
216  // Set the vertex of the FastCaloSim truth state
217  truthState.set_vertex(G4PrimaryTrack -> GetPosition().x(),
218  G4PrimaryTrack -> GetPosition().y(),
219  G4PrimaryTrack -> GetPosition().z());
220 
221 
222  /* For anti protons and anti-neutrons the kinetic energy should be
223  calculated as Ekin = E() + M() instead of E() - M() this is
224  achieved by setting an Ekin offset of 2*M() to the truth state */
225  if(pdgID == -2212 || pdgID == -2112) truthState.set_Ekin_off(2 * G4Particle -> GetPDGMass());
226 
227 
228  // Perform particle transportation through calorimeter system eiher with ATLAS tracking tools or with Geant4
229  std::vector<G4FieldTrack> caloSteps = m_doG4Transport ? m_G4CaloTransportTool -> transport(*G4PrimaryTrack)
230  : m_FastCaloSimCaloTransportation -> transport(&truthState, false);
231 
232  // Extrapolate transported stepos to ID-Calo boundary and all layers of the calorimeter system
233  m_FastCaloSimCaloExtrapolation->extrapolate(extrapolState, &truthState, caloSteps);
234 
235 
236 
237  // Do not simulate further if extrapolation to ID - Calo boundary fails
238  if(extrapolState.IDCaloBoundary_eta() == -999){
239  #ifdef FCS_DEBUG
240  G4cout<<"[FastCaloSim::DoIt] Killing particle as extrapolation failed"<<G4endl;
241  #endif
242  fastStep.KillPrimaryTrack();
243  return;
244  }
245  // Perform the actual FastCaloSim simulation
246  if(m_FastCaloSimSvc->simulate(simState, &truthState, &extrapolState).isFailure()){
247  G4Exception("FastCaloSimSvc", "FailedSimulationCall", FatalException, "FastCaloSimSvc: Simulation call failed.");
248  abort();
249  }
250 
251  #ifdef FCS_DEBUG
252  G4cout<<"[FastCaloSim::DoIt] Energy returned: " << simState.E() << G4endl;
253  G4cout<<"[FastCaloSim::DoIt] Energy fraction for layer: " << G4endl;
254  for (int s = 0; s < 24; s++) G4cout<<"[FastCaloSim::DoIt] Sampling " << s << " energy " << simState.E(s) << G4endl;
255  #endif
256 
257  // Retrieve the associated CaloCellContainer sensitive detector
258  CaloCellContainerSD * caloCellContainerSD = getCaloCellContainerSD();
259  // Record the cells
260  caloCellContainerSD->recordCells(simState);
261 
262  // Clean up the auxiliar info from the simulation state
263  simState.DoAuxInfoCleanup();
264 
265  // kill the primary track
266  fastStep.KillPrimaryTrack();
267  fastStep.SetPrimaryTrackPathLength(0.0);
268 }
269 
270 
272 
273  G4SDManager *sdm = G4SDManager::GetSDMpointer();
274  G4VSensitiveDetector * vsd = sdm->FindSensitiveDetector((G4String)m_CaloCellContainerSDName);
275 
276  if (!vsd){
277  G4Exception("FastCaloSimSvc", "FailedFindSensitiveDetector", FatalException, "FastCaloSimSvc: Failed getting CaloCellContainer SD.");
278  abort();
279  }
280  // Cast G4VSensitiveDetector to CaloCellContainerSD
281  CaloCellContainerSD * caloCellContainerSD = dynamic_cast<CaloCellContainerSD*>(vsd);
282 
283  if (!caloCellContainerSD){
284  G4Exception("FastCaloSimSvc", "FailedCastSensitiveDetector", FatalException, "FastCaloSimSvc: Failed casting G4VSensitiveDetector.");
285  abort();
286  }
287  return caloCellContainerSD;
288 }
289 
290 
291 G4bool FastCaloSim::passedIDCaloBoundary(const G4FastTrack& fastTrack){
292 
293 
294  /* Method checks if particle has crossed the ID-Calo boundary, defined using three cylinders with pairs of r/z values
295  We also perform a directional check to make sure that the particle does not originate from any backscatter from the MS or CALO */
296 
297  // NOTE:
298  // For the inner beam pipe section, innerBeamPipeZ = 4185 corresponds to original AFII boundary, while
299  // innerBeamPipeZ = 4587 corresponds to the CALO::CALO boundary which should be used instead as there
300  // is no triggering volume at this point and we will trigger slightly later than the AFII boundary, so
301  // passedIDCaloBoundary would fail and we would simulate this part with Geant4
302 
303  // Barrel
304  const float barrelR = 1148;
305  const float barrelZ = 3549.5;
306  // Inner beam pipe section
307  const float innerBeamPipeR = 120;
308  const float innerBeamPipeZ = 4587;
309  // Outer beam pipe section
310  const float outerBeamPipeR = 41;
311  const float outerBeamPipeZ = 6783;
312 
313  // Get particle position
314  const G4ThreeVector particlePosition = fastTrack.GetPrimaryTrack() -> GetPosition();
315  // Get r and z values of position
316  const float r = particlePosition.perp();
317  const float z = particlePosition.z();
318  // Get direction of particle
319  const G4ThreeVector particleDirection = fastTrack.GetPrimaryTrack() -> GetMomentum();
320  // Construct the helper line to decide if particle comes from ID or is backscatter from CALO
321  const G4ThreeVector helperLine = particlePosition + particleDirection;
322 
323  // Set 5cm trigger tolerance, i.e. the 'width' of the trigger boundary
324  // be careful not to set this too low, else Geant4 might overjump your trigger boundary and simulate everything with G4
325  const float triggerTolerance = 50;
326 
327  // Barrel boundary (horizontal surfaces)
328  if (std::abs(z) <= barrelZ + triggerTolerance) {
329  if (r >= barrelR && r < barrelR + triggerTolerance) return helperLine.perp() >= barrelR;
330  }
331  // Beam pipe boundary (horizontal surfaces)
332  if (std::abs(z) >= barrelZ && std::abs(z) <= innerBeamPipeZ + triggerTolerance){
333  if (r >= innerBeamPipeR && r < innerBeamPipeR + triggerTolerance) return helperLine.perp() >= innerBeamPipeR;
334  }
335  if (std::abs(z) >= innerBeamPipeZ && std::abs(z) <= outerBeamPipeZ){
336  if (r >= outerBeamPipeR && r < outerBeamPipeR + triggerTolerance) return helperLine.perp() >= outerBeamPipeR;
337  }
338  // Barrel boundary (vertical surfaces)
339  if (r >= outerBeamPipeR && r<= innerBeamPipeR){
340  if (std::abs(z) >= innerBeamPipeZ && std::abs(z) < innerBeamPipeZ + triggerTolerance) return std::abs(helperLine.z()) >= innerBeamPipeZ;
341  }
342  // Beam pipe boundary (vertical surfaces)
343  if (r >= innerBeamPipeR && r <= barrelR){
344  if (std::abs(z) >= barrelZ && std::abs(z) < barrelZ + triggerTolerance) return std::abs(helperLine.z()) >= barrelZ;
345  }
346 
347  return false;
348 
349 }
350 
FastCaloSimCaloExtrapolation
Definition: FastCaloSimCaloExtrapolation.h:32
ATHRNG::RNGWrapper::setSeed
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition: RNGWrapper.h:169
CaloCellContainerSD.h
beamspotman.r
def r
Definition: beamspotman.py:676
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
TFCSSimulationState::DoAuxInfoCleanup
void DoAuxInfoCleanup()
Definition: TFCSSimulationState.cxx:79
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:64
FastCaloSim::StartOfAthenaEvent
void StartOfAthenaEvent(const EventContext &ctx)
Definition: FastCaloSim.cxx:57
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:35
TFCSTruthState::set_Ekin_off
void set_Ekin_off(double val)
Definition: TFCSTruthState.h:23
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
CaloCellContainerSD::recordCells
void recordCells(TFCSSimulationState &)
Definition: CaloCellContainerSD.cxx:65
FastCaloSim::m_FastCaloSimTool
FastCaloSimTool * m_FastCaloSimTool
Definition: FastCaloSim.h:85
FastCaloSim::FastCaloSim
FastCaloSim(const std::string &name, const ServiceHandle< IAthRNGSvc > &rndmGenSvc, const Gaudi::Property< std::string > &randomEngineName, const PublicToolHandle< IFastCaloSimCaloTransportation > &FastCaloSimCaloTransportation, const PublicToolHandle< IFastCaloSimCaloExtrapolation > &FastCaloSimCaloExtrapolation, const PublicToolHandle< IG4CaloTransportTool > &G4CaloTransportTool, const ServiceHandle< ISF::IFastCaloSimParamSvc > &FastCaloSimSvc, const Gaudi::Property< std::string > &CaloCellContainerSDName, const Gaudi::Property< bool > &doG4Transport, FastCaloSimTool *FastCaloSimTool)
Definition: FastCaloSim.cxx:34
FastCaloSim::m_FastCaloSimSvc
ServiceHandle< ISF::IFastCaloSimParamSvc > m_FastCaloSimSvc
Definition: FastCaloSim.h:78
TFCSExtrapolationState
Definition: TFCSExtrapolationState.h:13
x
#define x
particleType
Definition: particleType.h:29
CaloCellContainerSD
Definition: CaloCellContainerSD.h:22
FastCaloSim::getCaloCellContainerSD
CaloCellContainerSD * getCaloCellContainerSD()
Retrieves the associated sensitive detector responsible for writing out the CaloCellContainer.
Definition: FastCaloSim.cxx:271
FastCaloSim::m_FastCaloSimCaloTransportation
PublicToolHandle< IFastCaloSimCaloTransportation > m_FastCaloSimCaloTransportation
Definition: FastCaloSim.h:70
FastCaloSim.h
FastCaloSim::m_randomEngineName
Gaudi::Property< std::string > m_randomEngineName
Definition: FastCaloSim.h:66
z
#define z
xAOD::EgammaHelpers::isElectron
bool isElectron(const xAOD::Egamma *eg)
is the object an electron (not Fwd)
Definition: EgammaxAODHelpers.cxx:12
FastCaloSim::EndOfAthenaEvent
void EndOfAthenaEvent(const EventContext &ctx)
Definition: FastCaloSim.cxx:66
TFCSExtrapolationState::IDCaloBoundary_eta
double IDCaloBoundary_eta() const
Definition: TFCSExtrapolationState.h:63
FastCaloSim::m_FastCaloSimCaloExtrapolation
PublicToolHandle< IFastCaloSimCaloExtrapolation > m_FastCaloSimCaloExtrapolation
Definition: FastCaloSim.h:72
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
isHadron
bool isHadron(const T &p)
Definition: AtlasPID.h:207
FastCaloSim::ModelTrigger
G4bool ModelTrigger(const G4FastTrack &) override final
Determines the applicability of the fast sim model to this particular track.
Definition: FastCaloSim.cxx:95
RNGWrapper.h
TFCSTruthState.h
y
#define y
TFCSExtrapolationState.h
xAOD::EgammaHelpers::isPhoton
bool isPhoton(const xAOD::Egamma *eg)
is the object a photon
Definition: EgammaxAODHelpers.cxx:21
FastCaloSimCaloTransportation
Definition: FastCaloSimCaloTransportation.h:21
TFCSTruthState::set_vertex
void set_vertex(const TLorentzVector &val)
Definition: TFCSTruthState.h:19
FastCaloSim::m_rngWrapper
ATHRNG::RNGWrapper * m_rngWrapper
Definition: FastCaloSim.h:67
FastCaloSim::DoIt
void DoIt(const G4FastTrack &, G4FastStep &) override final
Definition: FastCaloSim.cxx:177
FastCaloSim::m_doG4Transport
Gaudi::Property< bool > m_doG4Transport
Definition: FastCaloSim.h:82
TFCSSimulationState::E
double E() const
Definition: TFCSSimulationState.h:42
TFCSSimulationState.h
FastCaloSim::m_G4CaloTransportTool
PublicToolHandle< IG4CaloTransportTool > m_G4CaloTransportTool
Definition: FastCaloSim.h:74
FastCaloSim::m_CaloCellContainerSDName
Gaudi::Property< std::string > m_CaloCellContainerSDName
Definition: FastCaloSim.h:80
FastCaloSim::passedIDCaloBoundary
G4bool passedIDCaloBoundary(const G4FastTrack &fastTrack)
Check if the particle is located at the proper ID-Calo parametrization boundary and is travelling out...
Definition: FastCaloSim.cxx:291
G4CaloTransportTool
A tool which transports particles through the Geant4 geometry.
Definition: G4CaloTransportTool.h:25
TFCSTruthState
Definition: TFCSTruthState.h:13
TFCSSimulationState
Definition: TFCSSimulationState.h:32
FastCaloSim::IsApplicable
G4bool IsApplicable(const G4ParticleDefinition &) override final
Definition: FastCaloSim.cxx:73
FastCaloSimTool
Definition: FastCaloSimTool.h:24
HepMCHelpers.h
FastCaloSim::m_rndmGenSvc
ServiceHandle< IAthRNGSvc > m_rndmGenSvc
Definition: FastCaloSim.h:65
TFCSTruthState::set_pdgid
void set_pdgid(int val)
Definition: TFCSTruthState.h:18
ServiceHandle< IAthRNGSvc >