DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
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  m_needsControl = true;
130 
131  runAction().callAtBegin(this, &Geant4InputAction::beginRun);
132 }
133 
136 }
137 
139 void Geant4InputAction::beginRun(const G4Run*) {
140  createReader();
141 }
142 
144  if(m_reader) {
145  return;
146  }
147  if ( m_input.empty() ) {
148  except("InputAction: No input file declared!");
149  }
150  std::string err;
151  TypeName tn = TypeName::split(m_input,"|");
152  try {
153  m_reader = PluginService::Create<Geant4EventReader*>(tn.first,tn.second);
154  if ( 0 == m_reader ) {
155  PluginDebug dbg;
156  m_reader = PluginService::Create<Geant4EventReader*>(tn.first,tn.second);
157  abortRun("Error creating reader plugin.",
158  "Failed to create file reader of type %s. Cannot open dataset %s",
159  tn.first.c_str(),tn.second.c_str());
160  }
163  m_reader->setInputAction( this );
165  } catch(const std::exception& e) {
166  err = e.what();
167  }
168  if ( !err.empty() ) {
169  abortRun(err,"Error when creating reader for file %s",m_input.c_str());
170  }
171 }
172 
173 
175 std::string Geant4InputAction::issue(int i) const {
176  std::stringstream str;
177  str << "Geant4InputAction[" << name() << "]: Event " << i << " ";
178  return str.str();
179 }
180 
182 int Geant4InputAction::readParticles(int evt_number,
183  Vertices& vertices,
184  std::vector<Particle*>& particles)
185 {
186  //in case readParticles is called directly outside of having a run, we make sure a reader exists
187  createReader();
188  int evid = evt_number + m_firstEvent;
189  int status = m_reader->moveToEvent(evid);
190  if(status == Geant4EventReader::EVENT_READER_EOF ) {
191  long nEvents = context()->kernel().property("NumEvents").value<long>();
192  if(nEvents < 0) {
193  //context()->kernel().runManager().AbortRun(true);
194  throw DD4hep_End_Of_File();
195  }
196  }
197 
198  if ( Geant4EventReader::EVENT_READER_OK != status ) {
199  std::string msg = issue(evid)+"Error when moving to event - ";
200  if ( status == Geant4EventReader::EVENT_READER_EOF ) msg += " EOF: [end of file].";
201  else msg += " Unknown error condition";
202  if ( m_abort ) {
203  abortRun(msg,"Error when reading file %s",m_input.c_str());
204  return status;
205  }
206  error(msg.c_str());
207  except("Error when reading file %s.", m_input.c_str());
208  return status;
209  }
210  status = m_reader->readParticles(evid, vertices, particles);
211  if(status == Geant4EventReader::EVENT_READER_EOF ) {
212  long nEvents = context()->kernel().property("NumEvents").value<long>();
213  if(nEvents < 0) {
214  //context()->kernel().runManager().AbortRun(true);
215  throw DD4hep_End_Of_File();
216  }
217  }
218 
219  if ( Geant4EventReader::EVENT_READER_OK != status ) {
220  std::string msg = issue(evid)+"Error when moving to event - ";
221  if ( status == Geant4EventReader::EVENT_READER_EOF ) msg += " EOF: [end of file].";
222  else msg += " Unknown error condition";
223  if ( m_abort ) {
224  abortRun(msg,"Error when reading file %s",m_input.c_str());
225  return status;
226  }
227  error(msg.c_str());
228  except("Error when reading file %s.", m_input.c_str());
229  }
230  return status;
231 }
232 
234 void Geant4InputAction::operator()(G4Event* event) {
235  std::vector<Particle*> primaries;
236  Geant4Event& evt = context()->event();
238  Vertices vertices ;
239  int result;
240 
241  result = readParticles(m_currentEventNumber, vertices, primaries);
242 
243  event->SetEventID(m_firstEvent + m_currentEventNumber);
245 
246  if ( result != Geant4EventReader::EVENT_READER_OK ) { // handle I/O error, but how?
247  return;
248  }
249 
251  prim->add(m_mask, inter);
252 
253  // check if there is at least one particle
254  if ( primaries.empty() ) return;
255 
256  // check if there is at least one primary vertex
257  if ( vertices.empty() ) return;
258 
259  print("+++ Particle interaction with %d generator particles and %d vertices ++++++++++++++++++++++++",
260  int(primaries.size()), int(vertices.size()) );
261 
262 
263  for(size_t i=0; i<vertices.size(); ++i ) {
264  inter->vertices[m_mask].emplace_back( vertices[i] );
265  }
266 
267  // build collection of MCParticles
268  for(auto* primPart : primaries) {
269  Geant4ParticleHandle p(primPart);
270  const double mom_scale = m_momScale;
271  PropertyMask status(p->status);
272  p->psx = mom_scale*p->psx;
273  p->psy = mom_scale*p->psy;
274  p->psz = mom_scale*p->psz;
275 
276  //FIXME: this needs to be done now in the readers ...
277  // // if ( p->parents.size() == 0 ) {
278  // // if ( status.isSet(G4PARTICLE_GEN_EMPTY) || status.isSet(G4PARTICLE_GEN_DOCUMENTATION) )
279  // // vtx->in.insert(p->id); // Beam particles and primary quarks etc.
280  // // else
281  // // vtx->out.insert(p->id); // Stuff, to be given to Geant4 together with daughters
282  // // }
283 
284  inter->particles.emplace(p->id,p);
285  p.dumpWithMomentumAndVertex(outputLevel()-1,name(),"->");
286  }
287 }
288 
289 void Geant4InputAction::setGeneratorStatus(int genStatus, PropertyMask& status) {
290  if ( genStatus == 0 ) status.set(G4PARTICLE_GEN_EMPTY);
291  else if ( genStatus == 1 ) status.set(G4PARTICLE_GEN_STABLE);
292  else if ( genStatus == 2 ) status.set(G4PARTICLE_GEN_DECAYED);
293  else if ( genStatus == 3 ) status.set(G4PARTICLE_GEN_DOCUMENTATION);
294  else if ( genStatus == 4 ) status.set(G4PARTICLE_GEN_BEAM);
295  else if ( m_alternativeDecayStatuses.count(genStatus) ) status.set(G4PARTICLE_GEN_DECAYED);
296  else
297  status.set(G4PARTICLE_GEN_OTHER);
298 
299  return;
300 }
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:155
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:126
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: Geant4Output2EDM4hep.cpp:49
PropertyMask
dd4hep::detail::ReferenceBitMask< int > PropertyMask
Definition: HepMC3EventReader.cpp:37
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::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
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