DD4hep  1.32.1
Detector Description Toolkit for High Energy Physics
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Geant4InputAction.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // @author P.Kostka (main author)
11 // @author M.Frank (code reshuffeling into new DDG4 scheme)
12 //
13 //====================================================================
14 
15 // Framework include files
16 #include <DD4hep/Memory.h>
17 #include <DD4hep/Plugins.h>
18 #include <DDG4/Geant4Primary.h>
19 #include <DDG4/Geant4Context.h>
20 #include <DDG4/Geant4Kernel.h>
21 #include <DDG4/Geant4InputAction.h>
22 #include <DDG4/Geant4RunAction.h>
23 
24 #include <G4Event.hh>
25 
26 using namespace dd4hep::sim;
28 using PropertyMask = dd4hep::detail::ReferenceBitMask<int>;
29 
30 
32 Geant4EventReader::Geant4EventReader(const std::string& nam) : m_name(nam)
33 {
34 }
35 
38 }
39 
42  if( 0 == m_inputAction ) {
43  printout(FATAL,"Geant4EventReader", "No input action registered!");
44  throw std::runtime_error("Geant4EventReader: No input action registered!");
45  }
46  return m_inputAction->context();
47 }
48 
51  m_inputAction = action;
52 }
53 
56  if ( hasDirectAccess() ) {
57  ++m_currEvent;
58  return EVENT_READER_OK;
59  }
60  std::vector<Particle*> particles;
61  Vertices vertices ;
62 
63  ++m_currEvent;
64  EventReaderStatus sc = readParticles(m_currEvent,vertices,particles);
65  for_each(particles.begin(),particles.end(),detail::deleteObject<Particle>);
66  for_each(vertices.begin(),vertices.end(),detail::deleteObject<Vertex>);
67  return sc;
68 }
69 
71 void Geant4EventReader::checkParameters(std::map< std::string, std::string > &parameters) {
72 
73  if( parameters.empty() ) {
74  return;
75  }
76  for (auto const& pairNV : parameters ) {
77  printout(FATAL,"EventReader::checkParameters","Unknown parameter name: %s with value %s",
78  pairNV.first.c_str(),
79  pairNV.second.c_str());
80  }
81  throw std::runtime_error("Unknown parameter for event reader");
82 
83 }
84 
85 #if 0
87 Geant4EventReader::moveToEvent(int event_number) {
88  if ( event_number >= INT_MIN ) {
89  return EVENT_READER_OK; // Logic below does not work as expected.
90  } // This shortcuts it!
91  // APS: would have been nice to know what exactly doesn't work...
92  if ( m_currEvent == event_number ) {
93  return EVENT_READER_OK;
94  }
95  else if ( hasDirectAccess() ) {
96  m_currEvent = event_number;
97  return EVENT_READER_OK;
98  }
99  else if ( event_number<m_currEvent ) {
100  return EVENT_READER_ERROR;
101  }
102  else {
103  for(int i=m_currEvent; i<event_number;++i)
104  skipEvent();
105  m_currEvent = event_number;
106  return EVENT_READER_OK;
107  }
108  return EVENT_READER_ERROR;
109 }
110 #else
113 Geant4EventReader::moveToEvent(int /* event_number */) {
114  return EVENT_READER_OK;
115 }
116 #endif
117 
119 Geant4InputAction::Geant4InputAction(Geant4Context* ctxt, const std::string& nam)
120  : Geant4GeneratorAction(ctxt,nam), m_reader(0), m_currentEventNumber(0)
121 {
122  declareProperty("Input", m_input);
123  declareProperty("Sync", m_firstEvent=0);
124  declareProperty("Mask", m_mask = 0);
125  declareProperty("MomentumScale", m_momScale = 1.0);
126  declareProperty("HaveAbort", m_abort = true);
127  declareProperty("Parameters", m_parameters = {});
128  declareProperty("AlternativeDecayStatuses", m_alternativeDecayStatuses = {});
129  declareProperty("AlternativeStableStatuses", m_alternativeStableStatuses = {});
130  m_needsControl = true;
131 
132  runAction().callAtBegin(this, &Geant4InputAction::beginRun);
133 }
134 
137 }
138 
140 void Geant4InputAction::beginRun(const G4Run*) {
141  createReader();
142 }
143 
145  if(m_reader) {
146  return;
147  }
148  if ( m_input.empty() ) {
149  except("InputAction: No input file declared!");
150  }
151  std::string err;
152  TypeName tn = TypeName::split(m_input,"|");
153  try {
154  m_reader = PluginService::Create<Geant4EventReader*>(tn.first,tn.second);
155  if ( 0 == m_reader ) {
156  PluginDebug dbg;
157  m_reader = PluginService::Create<Geant4EventReader*>(tn.first,tn.second);
158  abortRun("Error creating reader plugin.",
159  "Failed to create file reader of type %s. Cannot open dataset %s",
160  tn.first.c_str(),tn.second.c_str());
161  }
164  m_reader->setInputAction( this );
166  } catch(const std::exception& e) {
167  err = e.what();
168  }
169  if ( !err.empty() ) {
170  abortRun(err,"Error when creating reader for file %s",m_input.c_str());
171  }
172 }
173 
174 
176 std::string Geant4InputAction::issue(int i) const {
177  std::stringstream str;
178  str << "Geant4InputAction[" << name() << "]: Event " << i << " ";
179  return str.str();
180 }
181 
183 int Geant4InputAction::readParticles(int evt_number,
184  Vertices& vertices,
185  std::vector<Particle*>& particles)
186 {
187  //in case readParticles is called directly outside of having a run, we make sure a reader exists
188  createReader();
189  int evid = evt_number + m_firstEvent;
190  int status = m_reader->moveToEvent(evid);
191  if(status == Geant4EventReader::EVENT_READER_EOF ) {
192  long nEvents = context()->kernel().property("NumEvents").value<long>();
193  if(nEvents < 0) {
194  //context()->kernel().runManager().AbortRun(true);
195  throw DD4hep_End_Of_File();
196  }
197  }
198 
199  if ( Geant4EventReader::EVENT_READER_OK != status ) {
200  std::string msg = issue(evid)+"Error when moving to event - ";
201  if ( status == Geant4EventReader::EVENT_READER_EOF ) msg += " EOF: [end of file].";
202  else msg += " Unknown error condition";
203  if ( m_abort ) {
204  abortRun(msg,"Error when reading file %s",m_input.c_str());
205  return status;
206  }
207  error(msg.c_str());
208  except("Error when reading file %s.", m_input.c_str());
209  return status;
210  }
211  status = m_reader->readParticles(evid, vertices, particles);
212  if(status == Geant4EventReader::EVENT_READER_EOF ) {
213  long nEvents = context()->kernel().property("NumEvents").value<long>();
214  if(nEvents < 0) {
215  //context()->kernel().runManager().AbortRun(true);
216  throw DD4hep_End_Of_File();
217  }
218  }
219 
220  if ( Geant4EventReader::EVENT_READER_OK != status ) {
221  std::string msg = issue(evid)+"Error when moving to event - ";
222  if ( status == Geant4EventReader::EVENT_READER_EOF ) msg += " EOF: [end of file].";
223  else msg += " Unknown error condition";
224  if ( m_abort ) {
225  abortRun(msg,"Error when reading file %s",m_input.c_str());
226  return status;
227  }
228  error(msg.c_str());
229  except("Error when reading file %s.", m_input.c_str());
230  }
231  return status;
232 }
233 
235 void Geant4InputAction::operator()(G4Event* event) {
236  std::vector<Particle*> primaries;
237  Geant4Event& evt = context()->event();
239  Vertices vertices ;
240  int result;
241 
242  result = readParticles(m_currentEventNumber, vertices, primaries);
243 
244  event->SetEventID(m_firstEvent + m_currentEventNumber);
246 
247  if ( result != Geant4EventReader::EVENT_READER_OK ) { // handle I/O error, but how?
248  return;
249  }
250 
252  prim->add(m_mask, inter);
253 
254  // check if there is at least one particle
255  if ( primaries.empty() ) return;
256 
257  // check if there is at least one primary vertex
258  if ( vertices.empty() ) return;
259 
260  print("+++ Particle interaction with %d generator particles and %d vertices ++++++++++++++++++++++++",
261  int(primaries.size()), int(vertices.size()) );
262 
263 
264  for(size_t i=0; i<vertices.size(); ++i ) {
265  inter->vertices[m_mask].emplace_back( vertices[i] );
266  }
267 
268  // build collection of MCParticles
269  for(auto* primPart : primaries) {
270  Geant4ParticleHandle p(primPart);
271  const double mom_scale = m_momScale;
272  PropertyMask status(p->status);
273  p->psx = mom_scale*p->psx;
274  p->psy = mom_scale*p->psy;
275  p->psz = mom_scale*p->psz;
276 
277  //FIXME: this needs to be done now in the readers ...
278  // // if ( p->parents.size() == 0 ) {
279  // // if ( status.isSet(G4PARTICLE_GEN_EMPTY) || status.isSet(G4PARTICLE_GEN_DOCUMENTATION) )
280  // // vtx->in.insert(p->id); // Beam particles and primary quarks etc.
281  // // else
282  // // vtx->out.insert(p->id); // Stuff, to be given to Geant4 together with daughters
283  // // }
284 
285  inter->particles.emplace(p->id,p);
286  p.dumpWithMomentumAndVertex(outputLevel()-1,name(),"->");
287  }
288 }
289 
290 void Geant4InputAction::setGeneratorStatus(int genStatus, PropertyMask& status) {
291  if ( genStatus == 0 ) status.set(G4PARTICLE_GEN_EMPTY);
292  else if ( genStatus == 1 ) status.set(G4PARTICLE_GEN_STABLE);
293  else if ( genStatus == 2 ) status.set(G4PARTICLE_GEN_DECAYED);
294  else if ( genStatus == 3 ) status.set(G4PARTICLE_GEN_DOCUMENTATION);
295  else if ( genStatus == 4 ) status.set(G4PARTICLE_GEN_BEAM);
296  else if ( m_alternativeDecayStatuses.count(genStatus) ) status.set(G4PARTICLE_GEN_DECAYED);
297  else if ( m_alternativeStableStatuses.count(genStatus) ) status.set(G4PARTICLE_GEN_STABLE);
298  else
299  status.set(G4PARTICLE_GEN_OTHER);
300 
301  return;
302 }
dd4hep::sim::Geant4PrimaryEvent
Class modelling a complete primary event with multiple interactions.
Definition: Geant4Primary.h:143
dd4hep::sim::Geant4EventReader::EVENT_READER_EOF
@ EVENT_READER_EOF
Definition: Geant4InputAction.h:75
dd4hep::sim::Geant4InputAction::m_reader
Geant4EventReader * m_reader
Event reader object.
Definition: Geant4InputAction.h:174
dd4hep::sim::G4PARTICLE_GEN_STABLE
@ G4PARTICLE_GEN_STABLE
Definition: Geant4Particle.h:71
dd4hep::sim::Geant4EventReader::context
Geant4Context * context() const
Get the context (from the input action)
Definition: Geant4InputAction.cpp:41
dd4hep::sim::Geant4EventReader::EventReaderStatus
EventReaderStatus
Status codes of the event reader object. Anything with NOT low-bit set is an error.
Definition: Geant4InputAction.h:68
dd4hep::sim::Geant4InputAction::m_abort
bool m_abort
Flag to call abortEvent in case of failure (default: true)
Definition: Geant4InputAction.h:178
dd4hep::exception
void exception(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:69
Geant4InputAction
Basic geant4 event reader class. This interface/base-class must be implemented by concrete readers.
dd4hep::sim::Geant4PrimaryInteraction
Class modelling a single interaction with multiple primary vertices and particles.
Definition: Geant4Primary.h:95
dd4hep::sim::Geant4InputAction::m_mask
int m_mask
Property; interaction mask.
Definition: Geant4InputAction.h:170
dd4hep::sim::Geant4InputAction::m_currentEventNumber
int m_currentEventNumber
current event number without initially skipped events
Definition: Geant4InputAction.h:176
dd4hep::sim::Geant4Kernel::property
Property & property(const std::string &name)
Access single property.
Definition: Geant4Kernel.cpp:298
Geant4RunAction.h
dd4hep::sim::Geant4Action::abortRun
void abortRun(const std::string &exception, const char *fmt,...) const
Abort Geant4 Run by throwing a G4Exception with type RunMustBeAborted.
Definition: Geant4Action.cpp:266
dd4hep::sim::Geant4PrimaryInteraction::vertices
VertexMap vertices
The map of primary vertices for the particles.
Definition: Geant4Primary.h:110
dd4hep::sim::TypeName::second
std::string second
Definition: Geant4Action.h:85
dd4hep::sim::Geant4PrimaryInteraction::particles
ParticleMap particles
The map of particles participating in this primary interaction.
Definition: Geant4Primary.h:112
dd4hep::sim::Geant4EventReader::~Geant4EventReader
virtual ~Geant4EventReader()
Default destructor.
Definition: Geant4InputAction.cpp:37
dd4hep::sim::Geant4Context::event
Geant4Event & event() const
Access the geant4 event – valid only between BeginEvent() and EndEvent()!
Definition: Geant4Context.cpp:84
m_reader
UriReader * m_reader
Pointer to URI reader.
Definition: DocumentHandler.cpp:154
dd4hep::sim::G4PARTICLE_GEN_DOCUMENTATION
@ G4PARTICLE_GEN_DOCUMENTATION
Definition: Geant4Particle.h:73
dd4hep::sim::Geant4InputAction::m_firstEvent
int m_firstEvent
Property: SYNCEVT.
Definition: Geant4InputAction.h:168
dd4hep::sim::Geant4EventReader::m_currEvent
int m_currEvent
Current event number.
Definition: Geant4InputAction.h:83
dd4hep::sim::Geant4EventReader::EVENT_READER_ERROR
@ EVENT_READER_ERROR
Definition: Geant4InputAction.h:69
dd4hep::sim::Geant4Event::extension
T * extension(bool alert=true)
Access to type safe extension object. Exception is thrown if the object is invalid.
Definition: Geant4Context.h:151
dd4hep::sim::Geant4Action::except
void except(const char *fmt,...) const
Support of exceptions: Print fatal message and throw runtime_error.
Definition: Geant4Action.cpp:256
dd4hep::sim::Geant4InputAction::operator()
virtual void operator()(G4Event *event) override
Callback to generate primary particles.
dd4hep::sim::Geant4EventReader::readParticles
virtual EventReaderStatus readParticles(int event_number, Vertices &vertices, Particles &particles)=0
Read an event and fill a vector of MCParticles.
dd4hep::sim::G4PARTICLE_GEN_EMPTY
@ G4PARTICLE_GEN_EMPTY
Definition: Geant4Particle.h:70
dd4hep::sim::Geant4InputAction::beginRun
void beginRun(const G4Run *)
Perform some actions before the run starts, like opening the event inputs.
dd4hep::sim::Geant4InputAction::m_input
std::string m_input
Property: input file.
Definition: Geant4InputAction.h:166
dd4hep::sim::Geant4Action::error
void error(const char *fmt,...) const
Support of error messages.
Definition: Geant4Action.cpp:231
dd4hep::sim::Geant4EventReader::moveToEvent
virtual EventReaderStatus moveToEvent(int event_number)
Move to the indicated event number.
Definition: Geant4InputAction.cpp:113
dd4hep::sim::Geant4InputAction::Geant4InputAction
Geant4InputAction(Geant4Context *context, const std::string &name)
Standard constructor.
dd4hep::sim::Geant4EventReader::registerRunParameters
virtual void registerRunParameters()
Register Run Parameters.
Definition: Geant4InputAction.h:144
dd4hep::sim::Geant4GeneratorAction
Concrete implementation of the Geant4 generator action base class.
Definition: Geant4GeneratorAction.h:47
dd4hep::sim::Geant4EventReader::skipEvent
virtual EventReaderStatus skipEvent()
Skip event. To be implemented for sequential sources.
Definition: Geant4InputAction.cpp:55
dd4hep::sim::Geant4EventReader::setParameters
virtual EventReaderStatus setParameters(std::map< std::string, std::string > &)
pass parameters to the event reader object
Definition: Geant4InputAction.h:138
Plugins.h
dd4hep::sim::TypeName::first
std::string first
Definition: Geant4Action.h:84
dd4hep::sim::G4PARTICLE_GEN_DECAYED
@ G4PARTICLE_GEN_DECAYED
Definition: Geant4Particle.h:72
dd4hep::sim::Geant4InputAction::issue
std::string issue(int i) const
helper to report Geant4 exceptions
dd4hep::sim::Geant4InputAction::setGeneratorStatus
void setGeneratorStatus(int generatorStatus, PropertyMask &status)
Convert the generator status into a common set of generator status bits.
dd4hep::sim::Geant4Action::name
const std::string & name() const
Access name of the action.
Definition: Geant4Action.h:280
dd4hep::sim::Geant4EventReader::m_inputAction
Geant4InputAction * m_inputAction
The input action context.
Definition: Geant4InputAction.h:85
dd4hep::sim::Geant4InputAction::~Geant4InputAction
virtual ~Geant4InputAction()
Default destructor.
dd4hep::sim::Geant4Action::outputLevel
PrintLevel outputLevel() const
Access the output level.
Definition: Geant4Action.h:296
dd4hep::sim::TypeName::split
static TypeName split(const std::string &type_name)
Split string pair according to default delimiter ('/')
Definition: Geant4Action.cpp:40
dd4hep::sim::Geant4Action::print
void print(const char *fmt,...) const
Support for messages with variable output level using output level.
Definition: Geant4Action.cpp:144
dd4hep::sim::Geant4EventReader::checkParameters
virtual void checkParameters(std::map< std::string, std::string > &)
make sure that all parameters have been processed, otherwise throw exceptions
Definition: Geant4InputAction.cpp:71
dd4hep::sim::G4PARTICLE_GEN_BEAM
@ G4PARTICLE_GEN_BEAM
Definition: Geant4Particle.h:74
Memory.h
dd4hep::Property::value
TYPE value() const
Retrieve value.
Definition: ComponentProperties.h:123
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: EDM4hepFileReader.cpp:41
dd4hep::sim::Geant4Context::kernel
Geant4Kernel & kernel() const
Access to the kernel object.
Definition: Geant4Context.h:233
Geant4InputAction.h
Vertices
Geant4InputAction::Vertices Vertices
Definition: Geant4InputAction.cpp:27
dd4hep::sim::DD4hep_End_Of_File
Helper class to indicate the end of the input file.
Definition: Geant4Kernel.h:43
dd4hep::sim::Geant4InputAction::m_alternativeStableStatuses
std::set< int > m_alternativeStableStatuses
Property: set of alternative stable statuses that MC generators might use for stable particles.
Definition: Geant4InputAction.h:186
dd4hep::sim::Geant4EventReader::EVENT_READER_OK
@ EVENT_READER_OK
Definition: Geant4InputAction.h:70
Geant4Primary.h
dd4hep::sim::Geant4ParticleHandle
Data structure to access derived MC particle information.
Definition: Geant4Particle.h:181
dd4hep::sim::TypeName
Helper class to handle strings of the format "type/name".
Definition: Geant4Action.h:82
Geant4Kernel.h
PropertyMask
dd4hep::detail::ReferenceBitMask< int > PropertyMask
Definition: EDM4hepFileReader.cpp:38
dd4hep::sim::Geant4InputAction::m_alternativeDecayStatuses
std::set< int > m_alternativeDecayStatuses
Property: set of alternative decay statuses that MC generators might use for unstable particles.
Definition: Geant4InputAction.h:183
dd4hep::sim::Geant4InputAction::createReader
void createReader()
Create the input reader.
dd4hep::sim::Geant4InputAction::Vertices
std::vector< Vertex * > Vertices
Definition: Geant4InputAction.h:163
dd4hep::sim::Geant4EventReader::Vertices
std::vector< Vertex * > Vertices
Definition: Geant4InputAction.h:66
dd4hep::sim::Geant4EventReader::setInputAction
void setInputAction(Geant4InputAction *action)
Set the input action.
Definition: Geant4InputAction.cpp:50
dd4hep::sim::Geant4InputAction::m_momScale
double m_momScale
Property: Momentum downscaler for debugging.
Definition: Geant4InputAction.h:172
dd4hep::sim::Geant4EventReader::hasDirectAccess
bool hasDirectAccess() const
Flag if direct event access (by event sequence number) is supported (Default: false)
Definition: Geant4InputAction.h:116
dd4hep::sim::Geant4EventReader::Geant4EventReader
Geant4EventReader(const std::string &nam)
Initializing constructor.
Definition: Geant4InputAction.cpp:32
dd4hep::sim::Geant4Event
User event context for DDG4.
Definition: Geant4Context.h:121
dd4hep::sim::G4PARTICLE_GEN_OTHER
@ G4PARTICLE_GEN_OTHER
Definition: Geant4Particle.h:76
Geant4Context.h
dd4hep::sim::Geant4PrimaryEvent::add
void add(int id, Geant4PrimaryInteraction *interaction)
Add a new interaction object to the event.
Definition: Geant4Primary.cpp:92
dd4hep::sim::Geant4InputAction::m_parameters
std::map< std::string, std::string > m_parameters
Property: named parameters to configure file readers or input actions.
Definition: Geant4InputAction.h:180
dd4hep::sim::Geant4InputAction::readParticles
int readParticles(int event_number, Vertices &vertices, Particles &particles)
Read an event and return a LCCollectionVec of MCParticles.
dd4hep::sim::Geant4Context
Generic context to extend user, run and event information.
Definition: Geant4Context.h:201
dd4hep::sim::Geant4Action::context
Geant4Context * context() const
Access the context.
Definition: Geant4Action.h:270