All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ParticleListAction.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file ParticleListAction.cxx
3 /// \brief Use Geant4's user "hooks" to maintain a list of particles generated by Geant4.
4 ///
5 /// \author seligman@nevis.columbia.edu
6 ////////////////////////////////////////////////////////////////////////
7 
9 #include "lardataobj/Simulation/sim.h" // sim::NoParticleId
10 #include "nug4/G4Base/PrimaryParticleInformation.h"
11 #include "nug4/ParticleNavigation/ParticleList.h"
12 
13 #include "cetlib_except/exception.h"
14 #include "messagefacility/MessageLogger/MessageLogger.h"
15 
16 #include "Geant4/G4DynamicParticle.hh"
17 #include "Geant4/G4ParticleDefinition.hh"
18 #include "Geant4/G4PrimaryParticle.hh"
19 #include "Geant4/G4Step.hh"
20 #include "Geant4/G4StepPoint.hh"
21 #include "Geant4/G4String.hh"
22 #include "Geant4/G4ThreeVector.hh"
23 #include "Geant4/G4Track.hh"
24 #include "Geant4/G4VProcess.hh"
25 #include "Geant4/G4VUserPrimaryParticleInformation.hh"
26 
27 #include <TLorentzVector.h>
28 
29 #include <algorithm>
30 #include <cassert>
31 
32 //const G4bool debug = false; // unused
33 
34 // Photon variables defined at each step, for use
35 // in temporary velocity bug fix. -wforeman
37 bool entra = true;
38 
39 namespace larg4 {
40 
41  // Initialize static members.
46 
47  //----------------------------------------------------------------------------
48  // Dropped particle test
49 
50  bool
51  ParticleListAction::isDropped(simb::MCParticle const* p)
52  {
53  return !p || p->Trajectory().empty();
54  } // ParticleListAction::isDropped()
55 
56  //----------------------------------------------------------------------------
57  // Constructor.
59  bool storeTrajectories,
61  bool keepMCParticleList, /* = true */
62  bool storeDroppedMCParticles
63  )
64  : fenergyCut(energyCut * CLHEP::GeV)
65  , fparticleList(keepMCParticleList ? std::make_unique<sim::ParticleList>() : nullptr)
66  , fdroppedParticleList(storeDroppedMCParticles ? std::make_unique<sim::ParticleList>() : nullptr)
67  , fstoreTrajectories(storeTrajectories)
68  , fKeepEMShowerDaughters(keepEMShowerDaughters)
69  {}
70 
71  //----------------------------------------------------------------------------
72  // Begin the event
73  void
75  {
76  // Clear any previous particle information.
78  if (fparticleList) fparticleList->clear();
80  fParentIDMap.clear();
83  fCurrentPdgCode = 0;
84  }
85 
86  //-------------------------------------------------------------
87  // figure out the ultimate parentage of the particle with track ID
88  // trackid
89  // assume that the current track id has already been added to
90  // the fParentIDMap
91  int
92  ParticleListAction::GetParentage(int trackid, bool useOrigTrackIDMap) const
93  {
94  int parentid = sim::NoParticleId;
95  const std::map<int, int>* parentIDMap = useOrigTrackIDMap ? &fParentIDMap_OrigTrackID : &fParentIDMap;
96 
97  // search the fParentIDMap recursively until we have the parent id
98  // of the first EM particle that led to this one
99  std::map<int, int>::const_iterator itr = parentIDMap->find(trackid);
100  while (itr != parentIDMap->end()) {
101  MF_LOG_DEBUG("ParticleListAction") << "parentage for " << trackid << " " << (*itr).second;
102 
103  // set the parentid to the current parent ID, when the loop ends
104  // this id will be the first EM particle
105  parentid = (*itr).second;
106  itr = parentIDMap->find(parentid);
107  }
108  MF_LOG_DEBUG("ParticleListAction") << "final parent ID " << parentid;
109 
110  return parentid;
111  }
112 
113  //----------------------------------------------------------------------------
114  // Create our initial simb::MCParticle object and add it to the sim::ParticleList.
115  void
117  {
118  // Particle type.
119  G4ParticleDefinition* particleDefinition = track->GetDefinition();
120  G4int pdgCode = particleDefinition->GetPDGEncoding();
121 
122  // Get Geant4's ID number for this track. This will be the same
123  // ID number that we'll use in the ParticleList.
124  // It is offset by the number of tracks accumulated from the previous Geant4
125  // runs (if any)
126  G4int trackID = track->GetTrackID() + fTrackIDOffset;
127  fCurrentTrackID = trackID;
128  fCurrentOrigTrackID = trackID;
129  fCurrentPdgCode = pdgCode;
130 
131  if (!fparticleList) {
132  // the rest is about adding a new particle to the list: skip
133  return; // note that fCurrentParticle is clear()'ed
134  }
135 
136  // And the particle's parent (same offset as above):
137  G4int parentID = track->GetParentID() + fTrackIDOffset;
138 
139  std::string process_name = "unknown";
140  bool drop_shower_daughter = false;
141 
142  // Is there an MCTruth object associated with this G4Track? We
143  // have to go up a "chain" of information to find out:
144  const G4DynamicParticle* dynamicParticle = track->GetDynamicParticle();
145  const G4PrimaryParticle* primaryParticle = dynamicParticle->GetPrimaryParticle();
146  simb::GeneratedParticleIndex_t primaryIndex = simb::NoGeneratedParticleIndex;
147  if (primaryParticle != 0) {
148  const G4VUserPrimaryParticleInformation* gppi = primaryParticle->GetUserInformation();
149  const g4b::PrimaryParticleInformation* ppi =
150  dynamic_cast<const g4b::PrimaryParticleInformation*>(gppi);
151  if (ppi != 0) {
152  primaryIndex = ppi->MCParticleIndex();
153 
154  // If we've made it this far, a PrimaryParticleInformation
155  // object exists and we are using a primary particle, set the
156  // process name accordingly
157  process_name = "primary";
158 
159  // primary particles should have parentID = 0, even if there
160  // are multiple MCTruths for this event
161  parentID = 0;
162  } // end else no primary particle information
163  } // Is there a G4PrimaryParticle?
164  // If this is not a primary particle...
165  else {
166  // check if this particle was made in an EM shower, don't put it in the particle
167  // list as we don't care about secondaries, tertiaries, etc for these showers
168  // figure out what process is making this track - skip it if it is
169  // one of pair production, compton scattering, photoelectric effect
170  // bremstrahlung, annihilation, any ionization - who wants to save
171  // a buttload of electrons that arent from a CC interaction?
172  process_name = track->GetCreatorProcess()->GetProcessName();
173  drop_shower_daughter = (!fKeepEMShowerDaughters && (process_name.find("conv") != std::string::npos ||
174  process_name.find("LowEnConversion") != std::string::npos ||
175  process_name.find("Pair") != std::string::npos ||
176  process_name.find("compt") != std::string::npos ||
177  process_name.find("Compt") != std::string::npos ||
178  process_name.find("Brem") != std::string::npos ||
179  process_name.find("phot") != std::string::npos ||
180  process_name.find("Photo") != std::string::npos ||
181  process_name.find("Ion") != std::string::npos ||
182  process_name.find("annihil") != std::string::npos));
183  if (drop_shower_daughter) {
184 
185  // figure out the ultimate parentage of this particle
186  // first add this track id and its parent to the fParentIDMap
187  fParentIDMap[trackID] = parentID;
188 
189  fCurrentTrackID = -1 * this->GetParentage(trackID); // the real trackID remains stored in fCurrentOrigTrackID
190 
191  // check that fCurrentTrackID is in the particle list - it is possible
192  // that this particle's parent is a particle that did not get tracked.
193  // An example is a partent that was made due to muMinusCaptureAtRest
194  // and the daughter was made by the phot process. The parent likely
195  // isn't saved in the particle list because it is below the energy cut
196  // which will put a bogus track id value into the sim::IDE object for
197  // the sim::SimChannel if we don't check it.
199 
200  } // end if keeping EM shower daughters
201 
202  // Check the energy of the particle. If it falls below the energy
203  // cut, don't add it to our list.
204  G4double energy = track->GetKineticEnergy();
205  if (energy < fenergyCut) {
207 
208  // do add the particle to the parent id map though
209  // and set the current track id to be it's ultimate parent
210  fParentIDMap[trackID] = parentID;
211  fParentIDMap_OrigTrackID[trackID] = parentID;
212 
213  fCurrentTrackID = -1 * this->GetParentage(trackID);
214  fCurrentOrigTrackID = -1 * this->GetParentage(trackID, true);
215 
216  return;
217  }
218 
219  // check to see if the parent particle has been stored in the particle navigator
220  // if not, then see if it is possible to walk up the fParentIDMap to find the
221  // ultimate parent of this particle. Use that ID as the parent ID for this
222  // particle
223  if (!fparticleList->KnownParticle(parentID) && !(fdroppedParticleList && fdroppedParticleList->KnownParticle(parentID))) {
224  // do add the particle to the parent id map
225  // just in case it makes a daughter that we have to track as well
226  fParentIDMap[trackID] = parentID;
227  fParentIDMap_OrigTrackID[trackID] = parentID;
228  int pid = this->GetParentage(parentID);
229 
230  // if we still can't find the parent in the particle navigator,
231  // we have to give up
232  if (!fparticleList->KnownParticle(pid) && !(fdroppedParticleList && fdroppedParticleList->KnownParticle(parentID))) {
233  MF_LOG_WARNING("ParticleListAction")
234  << "can't find parent id: " << parentID << " in the particle list, or fParentIDMap."
235  << " Make " << parentID << " the mother ID for"
236  << " track ID " << fCurrentTrackID << " in the hope that it will aid debugging.";
237  }
238  else
239  parentID = pid;
240  }
241 
242  } // end if not a primary particle
243 
244  // This is probably the PDG mass, but just in case:
245  double mass = dynamicParticle->GetMass() / CLHEP::GeV;
246 
247  // Create the sim::Particle object.
250  new simb::MCParticle(trackID, pdgCode, process_name, parentID, mass);
251  fCurrentParticle.truthIndex = primaryIndex;
252 
253  // if we are not filtering, we have a decision already
254  if (!fFilter) fCurrentParticle.keep = true;
255 
256  // Polarization.
257  const G4ThreeVector& polarization = track->GetPolarization();
258  fCurrentParticle.particle->SetPolarization(
259  TVector3(polarization.x(), polarization.y(), polarization.z()));
260 
261  // if KeepEMShowerDaughters = False and we decided to drop this particle,
262  // record it before throwing it away.
263  if (drop_shower_daughter) {
264  fCurrentParticle.drop = true;
266  return;
267  }
268 
269  // Save the particle in the ParticleList.
271  }
272 
273  //----------------------------------------------------------------------------
274  void
276  {
277  if (!fCurrentParticle.hasParticle()) return;
278  assert(fparticleList);
279 
280  if (aTrack) {
281  fCurrentParticle.particle->SetWeight(aTrack->GetWeight());
282  G4String process =
283  aTrack->GetStep()->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName();
284  fCurrentParticle.particle->SetEndProcess(process);
285  }
286 
287  // We would keep it if it wasn't for KeepEMShowerDaughters = false
288  // It goes into fDroppedParticleList in case LArG4 is configured
289  // to keep a minimal version of it.
290  if (fCurrentParticle.drop) {
293  return;
294  }
295 
296  // if we have found no reason to keep it, drop it!
297  // (we might still need parentage information though)
298  if (!fCurrentParticle.keep) {
299  fparticleList->Archive(fCurrentParticle.particle.get());
300  // after the particle is archived, it is deleted
302  return;
303  }
304 
305  // store truth record pointer, only if it is available
306  if (fCurrentParticle.isPrimary()) {
308  }
309 
310  return;
311  }
312 
313  //----------------------------------------------------------------------------
314  // With every step, add to the particle's trajectory.
315  void
317  {
318 
319  if (!fCurrentParticle.hasParticle()) { return; }
320 
321  // Temporary fix for problem where DeltaTime on the first step
322  // of optical photon propagation is calculated incorrectly. -wforeman
323  globalTime = step->GetTrack()->GetGlobalTime();
324  velocity_G4 = step->GetTrack()->GetVelocity();
325  velocity_step = step->GetStepLength() / step->GetDeltaTime();
326  if ((step->GetTrack()->GetDefinition()->GetPDGEncoding() == 0) &&
327  fabs(velocity_G4 - velocity_step) > 0.0001) {
328  // Subtract the faulty step time from the global time,
329  // and add the correct step time based on G4 velocity.
330  step->GetPostStepPoint()->SetGlobalTime(globalTime - step->GetDeltaTime() +
331  step->GetStepLength() / velocity_G4);
332  }
333 
334  // For the most part, we just want to add the post-step
335  // information to the particle's trajectory. There's one
336  // exception: In PreTrackingAction, the correct time information
337  // is not available. So add the correct vertex information here.
338 
339  if (fCurrentParticle.particle->NumberTrajectoryPoints() == 0) {
340 
341  // Get the pre/along-step information from the G4Step.
342  const G4StepPoint* preStepPoint = step->GetPreStepPoint();
343 
344  const G4ThreeVector position = preStepPoint->GetPosition();
345  G4double time = preStepPoint->GetGlobalTime();
346 
347  // Remember that LArSoft uses cm, ns, GeV.
348  TLorentzVector fourPos(position.x() / CLHEP::cm,
349  position.y() / CLHEP::cm,
350  position.z() / CLHEP::cm,
351  time / CLHEP::ns);
352 
353  const G4ThreeVector momentum = preStepPoint->GetMomentum();
354  const G4double energy = preStepPoint->GetTotalEnergy();
355  TLorentzVector fourMom(momentum.x() / CLHEP::GeV,
356  momentum.y() / CLHEP::GeV,
357  momentum.z() / CLHEP::GeV,
358  energy / CLHEP::GeV);
359 
360  // Add the first point in the trajectory.
361  AddPointToCurrentParticle(fourPos, fourMom, "Start");
362 
363  } // end if this is the first step
364 
365  // At this point, the particle is being transported through the
366  // simulation. This method is being called for every voxel that
367  // the track passes through, but we don't want to update the
368  // trajectory information if we're just updating voxels. To check
369  // for this, look at the process name for the step, and compare it
370  // against the voxelization process name (set in PhysicsList.cxx).
371  G4String process = step->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName();
372  G4bool ignoreProcess = process.contains("LArVoxel") || process.contains("OpDetReadout");
373 
374  MF_LOG_DEBUG("ParticleListAction::SteppingAction")
375  << ": DEBUG - process='" << process << "'"
376  << " ignoreProcess=" << ignoreProcess << " fstoreTrajectories=" << fstoreTrajectories;
377 
378  // We store the initial creation point of the particle
379  // and its final position (ie where it has no more energy, or at least < 1 eV) no matter
380  // what, but whether we store the rest of the trajectory depends
381  // on the process, and on a user switch
382  if (fstoreTrajectories && !ignoreProcess) {
383  // If the particle was marked to drop (EM shower daughters),
384  // then skip unless this step is last in volume.
385  //if (fCurrentParticle.drop && !step->IsLastStepInVolume()) return;
386 
387  // Get the post-step information from the G4Step.
388  const G4StepPoint* postStepPoint = step->GetPostStepPoint();
389 
390  const G4ThreeVector position = postStepPoint->GetPosition();
391  G4double time = postStepPoint->GetGlobalTime();
392 
393  // Remember that LArSoft uses cm, ns, GeV.
394  TLorentzVector fourPos(position.x() / CLHEP::cm,
395  position.y() / CLHEP::cm,
396  position.z() / CLHEP::cm,
397  time / CLHEP::ns);
398 
399  const G4ThreeVector momentum = postStepPoint->GetMomentum();
400  const G4double energy = postStepPoint->GetTotalEnergy();
401  TLorentzVector fourMom(momentum.x() / CLHEP::GeV,
402  momentum.y() / CLHEP::GeV,
403  momentum.z() / CLHEP::GeV,
404  energy / CLHEP::GeV);
405 
406  // Add another point in the trajectory.
407  AddPointToCurrentParticle(fourPos, fourMom, std::string(process));
408  }
409  }
410 
411  //----------------------------------------------------------------------------
412  /// Utility class for the EndOfEventAction method: update the
413  /// daughter relationships in the particle list.
415  : public std::unary_function<sim::ParticleList::value_type, void> {
416  public:
418  void
419  SetParticleList(sim::ParticleList* p)
420  {
421  particleList = p;
422  }
423  void
424  operator()(sim::ParticleList::value_type& particleListEntry)
425  {
426  // We're looking at this Particle in the list.
427  int particleID = particleListEntry.first;
428 
429  // The parent ID of this particle;
430  // we ask the particle list since the particle itself might have been lost
431  // ("archived"), but the particle list still holds the information we need
432  int parentID = particleList->GetMotherOf(particleID);
433 
434  // If the parentID <= 0, this is a primary particle.
435  if (parentID <= 0) return;
436 
437  // If we get here, this particle is somebody's daughter. Add
438  // it to the list of daughter particles for that parent.
439 
440  // Get the parent particle from the list.
441  sim::ParticleList::iterator parentEntry = particleList->find(parentID);
442 
443  if (parentEntry == particleList->end()) {
444  // We have an "orphan": a particle whose parent isn't
445  // recorded in the particle list. This is not signficant;
446  // it's possible for a particle not to be saved in the list
447  // because it failed an energy cut, but for it to have a
448  // daughter that passed the cut (e.g., a nuclear decay).
449  return;
450  }
451  if (!parentEntry->second) return; // particle archived, nothing to update
452 
453  // Add the current particle to the daughter list of the
454  // parent.
455  simb::MCParticle* parent = (*parentEntry).second;
456  parent->AddDaughter(particleID);
457  }
458 
459  private:
460  sim::ParticleList* particleList;
461  };
462 
463  //----------------------------------------------------------------------------
464  // There's one last thing to do: All the particles have their
465  // parent IDs set (in PostTrackingAction), but we haven't set the
466  // daughters yet. That's done in this method.
467  void
469  {
470  if (!fparticleList) return;
471 
472  // Set up the utility class for the "for_each" algorithm. (We only
473  // need a separate set-up for the utility class because we need to
474  // give it the pointer to the particle list. We're using the STL
475  // "for_each" instead of the C++ "for loop" because it's supposed
476  // to be faster.
477  UpdateDaughterInformation updateDaughterInformation;
478  updateDaughterInformation.SetParticleList(fparticleList.get());
479 
480  // Update the daughter information for each particle in the list.
481  std::for_each(fparticleList->begin(), fparticleList->end(), updateDaughterInformation);
482  }
483 
484  //----------------------------------------------------------------------------
485  // Returns the ParticleList accumulated during the current event.
486  const sim::ParticleList*
488  {
489  if (!fparticleList) return nullptr;
490 
491  // check if the ParticleNavigator has entries, and if
492  // so grab the highest track id value from it to
493  // add to the fTrackIDOffset
494  int highestID = 0;
495  for (auto pn = fparticleList->begin(); pn != fparticleList->end(); pn++)
496  if ((*pn).first > highestID) highestID = (*pn).first;
497 
498  // If we have stored dropped particles,
499  // include them in the offset.
500  if (fdroppedParticleList) {
501  for (auto pn = fdroppedParticleList->begin(); pn != fdroppedParticleList->end(); pn++)
502  if ((*pn).first > highestID) highestID = (*pn).first;
503  }
504 
505  //Only change the fTrackIDOffset if there is in fact a particle to add to the event
506  if ((fparticleList->size()) != 0) { fTrackIDOffset = highestID + 1; }
507 
508  return fparticleList.get();
509  }
510 
511  //----------------------------------------------------------------------------
512  simb::GeneratedParticleIndex_t
514  {
515  auto const iInfo = GetPrimaryTruthMap().find(trackId);
516  return (iInfo == GetPrimaryTruthMap().end()) ? simb::NoGeneratedParticleIndex : iInfo->second;
517  } // ParticleListAction::GetPrimaryTruthIndex()
518 
519  //----------------------------------------------------------------------------
520  // Yields the ParticleList accumulated during the current event.
521  sim::ParticleList&&
523  {
524  if (!fparticleList) {
525  // check with `hasList()` before calling this method
526  throw cet::exception("ParticleListAction")
527  << "ParticleListAction::YieldList(): particle list not build by user request.\n";
528  }
529  // check if the ParticleNavigator has entries, and if
530  // so grab the highest track id value from it to
531  // add to the fTrackIDOffset
532  int highestID = 0;
533  for (auto pn = fparticleList->begin(); pn != fparticleList->end(); pn++)
534  if ((*pn).first > highestID) highestID = (*pn).first;
535 
536  // If we have stored dropped particles,
537  // include them in the offset.
538  if (fdroppedParticleList) {
539  for (auto pn = fdroppedParticleList->begin(); pn != fdroppedParticleList->end(); pn++)
540  if ((*pn).first > highestID) highestID = (*pn).first;
541  }
542 
543  //Only change the fTrackIDOffset if there is in fact a particle to add to the event
544  if ((fparticleList->size()) != 0) { fTrackIDOffset = highestID + 1; }
545 
546  return std::move(*fparticleList);
547  } // ParticleList&& ParticleListAction::YieldList()
548 
549  //----------------------------------------------------------------------------
550  // Yields the (dropped) ParticleList accumulated during the current event.
551  sim::ParticleList&&
553  {
554  if (!fdroppedParticleList) {
555  throw cet::exception("ParticleListAction")
556  << "ParticleListAction::YieldDroppedList(): dropped particle list not build by user request.\n";
557  }
558  // check if the ParticleNavigator has entries, and if
559  // so grab the highest track id value from it to
560  // add to the fTrackIDOffset
561  int highestID = 0;
562  for (auto pn = fparticleList->begin(); pn != fparticleList->end(); pn++)
563  if ((*pn).first > highestID) highestID = (*pn).first;
564 
565  // If we have stored dropped particles,
566  // include them in the offset.
567  for (auto pn = fdroppedParticleList->begin(); pn != fdroppedParticleList->end(); pn++)
568  if ((*pn).first > highestID) highestID = (*pn).first;
569 
570  //Only change the fTrackIDOffset if there is in fact a particle to add to the event
571  if ((fparticleList->size()) != 0) { fTrackIDOffset = highestID + 1; }
572 
573  return std::move(*fdroppedParticleList);
574  } // ParticleList&& ParticleListAction::YieldDroppedList()
575  //----------------------------------------------------------------------------
576  void
578  TLorentzVector const& mom,
579  std::string const& process)
580  {
581 
582  // Add the first point in the trajectory.
583  fCurrentParticle.particle->AddTrajectoryPoint(pos, mom, process);
584 
585  // also see if we can decide to keep the particle
586  if (!fCurrentParticle.keep) fCurrentParticle.keep = fFilter->mustKeep(pos);
587 
588  } // ParticleListAction::AddPointToCurrentParticle()
589 
590  //----------------------------------------------------------------------------
591 
592 } // namespace LArG4
util::quantities::gigaelectronvolt GeV
ParticleListAction(double energyCut, bool storeTrajectories=false, bool keepEMShowerDaughters=false, bool keepMCParticleList=true, bool storeDroppedMCParticles=false)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
G4bool fstoreTrajectories
Whether to store particle trajectories with each particle.
void AddPointToCurrentParticle(TLorentzVector const &pos, TLorentzVector const &mom, std::string const &process)
Adds a trajectory point to the current particle, and runs the filter.
static int fCurrentPdgCode
pdg code of current particle
virtual void BeginOfEventAction(const G4Event *)
std::map< int, GeneratedParticleIndex_t > fPrimaryTruthMap
Map: particle track ID -&gt; index of primary information in MC truth.
std::unique_ptr< sim::ParticleList > fdroppedParticleList
std::map< int, int > fParentIDMap_OrigTrackID
key is current track ID, value is parent ID – for real G4 track ID tracking only
GeneratedParticleIndex_t truthIndex
Index of the particle in the original generator truth record.
int GetParentage(int trackid, bool useOrigTrackIDMap=false) const
pdgs p
Definition: selectors.fcl:22
const sim::ParticleList * GetList() const
process_name use argoneut_mc_hitfinder track
void operator()(sim::ParticleList::value_type &particleListEntry)
double velocity_step
GeneratedParticleIndex_t truthInfoIndex() const
Returns the index of the particle in the generator truth record.
std::map< int, int > fParentIDMap
key is current track ID, value is parent ID
virtual void PreTrackingAction(const G4Track *)
BEGIN_PROLOG note Geant4 assumes this is in MeV keepEMShowerDaughters
void clear()
Resets the information (does not release memory it does not own)
sim::ParticleList && YieldList()
Use Geant4&#39;s user &quot;hooks&quot; to maintain a list of particles generated by Geant4.
static bool isDropped(simb::MCParticle const *p)
returns whether the specified particle has been marked as dropped
bool fKeepEMShowerDaughters
whether to keep EM shower secondaries, tertiaries, etc
virtual void PostTrackingAction(const G4Track *)
static const int NoParticleId
Definition: sim.h:21
A value measured in the specified unit.
Definition: quantities.h:566
bool entra
MF_LOG_WARNING("SimWire")<< "SimWire is an example module that works for the "<< "MicroBooNE detector. Each experiment should implement "<< "its own version of this module to simulate electronics "<< "response."
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
void SetParticleList(sim::ParticleList *p)
sim::ParticleList && YieldDroppedList()
Yields the (dropped) ParticleList accumulated during the current event.
GeneratedParticleIndex_t GetPrimaryTruthIndex(int trackId) const
Returns the index of primary truth (sim::NoGeneratorIndex if none).
double velocity_G4
fKeepEMShowerDaughters(p.get< bool >("keepEMShowerDaughters", true))
std::unique_ptr< util::PositionInVolumeFilter > fFilter
filter for particles to be kept
std::unique_ptr< sim::ParticleList > fparticleList
bool isPrimary() const
Returns whether there is a particle.
double globalTime
cet::exempt_ptr< simb::MCParticle > particle
Object representing particle.
float mass
Definition: dedx.py:47
BEGIN_PROLOG note Geant4 assumes this is in MeV does not store electromagnetic shower daughter storeTrajectories
static int fCurrentOrigTrackID
except for EM shower particles where it always shows the original track ID
virtual void EndOfEventAction(const G4Event *)
bool hasParticle() const
Returns whether there is a particle.
virtual void SteppingAction(const G4Step *)
Tools and modules for checking out the basics of the Monte Carlo.
std::map< int, GeneratedParticleIndex_t > const & GetPrimaryTruthMap() const
bool keep
if there was decision to keep
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG process_name