LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
larg4::LArG4 Class Reference

Runs Geant4 simulation and propagation of electrons and photons to readout. More...

Inheritance diagram for larg4::LArG4:
art::EDProducer art::detail::Producer art::detail::LegacyModule art::Modifier art::ModuleBase art::ProductRegistryHelper

Public Types

using ModuleType = EDProducer
 
template<typename UserConfig , typename KeysToIgnore = void>
using Table = Modifier::Table< UserConfig, KeysToIgnore >
 

Public Member Functions

 LArG4 (fhicl::ParameterSet const &pset)
 
void doBeginJob (SharedResources const &resources)
 
void doEndJob ()
 
void doRespondToOpenInputFile (FileBlock const &fb)
 
void doRespondToCloseInputFile (FileBlock const &fb)
 
void doRespondToOpenOutputFiles (FileBlock const &fb)
 
void doRespondToCloseOutputFiles (FileBlock const &fb)
 
bool doBeginRun (RunPrincipal &rp, ModuleContext const &mc)
 
bool doEndRun (RunPrincipal &rp, ModuleContext const &mc)
 
bool doBeginSubRun (SubRunPrincipal &srp, ModuleContext const &mc)
 
bool doEndSubRun (SubRunPrincipal &srp, ModuleContext const &mc)
 
bool doEvent (EventPrincipal &ep, ModuleContext const &mc, std::atomic< std::size_t > &counts_run, std::atomic< std::size_t > &counts_passed, std::atomic< std::size_t > &counts_failed)
 
void fillProductDescriptions ()
 
void registerProducts (ProductDescriptions &productsToRegister)
 
ModuleDescription const & moduleDescription () const
 
void setModuleDescription (ModuleDescription const &)
 
std::array< std::vector< ProductInfo >, NumBranchTypes > const & getConsumables () const
 
void sortConsumables (std::string const &current_process_name)
 
std::unique_ptr< Worker > makeWorker (WorkerParams const &wp)
 
template<typename T , BranchType BT>
ViewToken< T > consumesView (InputTag const &tag)
 
template<typename T , BranchType BT>
ViewToken< T > mayConsumeView (InputTag const &tag)
 

Protected Member Functions

ConsumesCollector & consumesCollector ()
 
template<typename T , BranchType = InEvent>
ProductToken< T > consumes (InputTag const &)
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > consumesView (InputTag const &)
 
template<typename T , BranchType = InEvent>
void consumesMany ()
 
template<typename T , BranchType = InEvent>
ProductToken< T > mayConsume (InputTag const &)
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > mayConsumeView (InputTag const &)
 
template<typename T , BranchType = InEvent>
void mayConsumeMany ()
 

Private Member Functions

void produce (art::Event &evt) override
 
void beginJob () override
 
void beginRun (art::Run &run) override
 
std::unique_ptr< util::PositionInVolumeFilterCreateParticleVolumeFilter (std::set< std::string > const &vol_names) const
 Pointer used for correctly updating the clock data state. More...
 

Private Attributes

std::unique_ptr< g4b::G4HelperfG4Help {nullptr}
 G4 interface object. More...
 
larg4::ParticleListActionfparticleListAction
 Geant4 user action to particle information. More...
 
std::string fG4PhysListName
 predefined physics list to use if not making a custom one More...
 
std::string fG4MacroPath
 
bool fCheckOverlaps
 Whether to use the G4 overlap checker. More...
 
bool fMakeMCParticles
 Whether to keep a sim::MCParticle list. More...
 
bool fStoreDroppedMCParticles
 Whether to keep a sim::MCParticleLite list of dropped particles. More...
 
bool fdumpParticleList
 Whether each event's sim::ParticleList will be displayed. More...
 
bool fdumpSimChannels
 Whether each event's sim::Channel will be displayed. More...
 
bool fUseLitePhotons
 
bool fStoreReflected {false}
 
int fSmartStacking
 Whether to instantiate and use class to. More...
 
double fOffPlaneMargin = 0.
 
std::vector< std::string > fInputLabels
 
std::vector< std::string > fKeepParticlesInVolumes
 Only write particles that have trajectories through these volumes. More...
 
bool fSparsifyTrajectories
 Sparsify MCParticle Trajectories. More...
 
CLHEP::HepRandomEngine & fEngine
 
detinfo::DetectorPropertiesData fDetProp
 Must outlive fAllPhysicsLists! More...
 
AllPhysicsLists fAllPhysicsLists
 
LArVoxelReadoutGeometryfVoxelReadoutGeometry
 

Detailed Description

Runs Geant4 simulation and propagation of electrons and photons to readout.

This module collects generated particles from one or more generators and processes them through Geant4.

Input

The module reads the particles to process from simb::MCTruth records. Each particle generator is required to produce a vector of such records: std::vector<simb::MCTruth>.

The module allows two operation modes:

  1. process specific generators: the label of the generator modules to be processed is specified explicitly in LArG4 configuration
  2. process all truth information generated so far: no generator is specified in the LArG4 module configuration, and the module will process all data products of type std::vector<simb::MCTruth>, in a non-specified order

For each simb::MCTruth, a Geant4 run is started. The interface with Geant4 is via a helper class provided by nug4. Only the particles in the truth record which have status code (simb::MCParticle::StatusCode()) equal to 1 are processed. These particles are called, in LArG4 jargon, primaries.

Output

The LArG4 module produces:

  • a collection of sim::SimChannel: each sim::SimChannel represents the set of energy depositions in liquid argon which drifted and were observed on a certain channel; it includes physics effects like attenuation, diffusion, electric field distortion, etc. Information of the generating Geant4 "track" is retained;
  • a collection of sim::SimPhotons or sim::SimPhotonsLite: each sim::SimPhotons represents the set of individual photons reaching a channel of the optical detector; it includes physics effects as well as quantum efficiency of the detector (to reduce data size early in the process); sim::SimPhotonsLite drops the information of the single photons and stores only collective information (e.g. their number).
  • a collection of sim::OpDetBacktrackerRecord (to be documented)
  • a collection of sim::AuxDetSimChannel (to be documented)
  • a collection of simb::MCParticle: the particles generated in the interaction of the primary particles with the material in the world are stored, but minor filtering by geometry and by physics is possible. An association of them with the originating simb::MCTruth object is also produced.

Notes on the conventions

  • all and the particles in the truth record (simb::MCTruth) which have status code (simb::MCParticle::StatusCode()) equal to 1 are passed to Geant4. These particles are called, in LArG4 jargon, primaries. The interface with Geant4 is via a helper class provided by nug4.
  • normally, information about each particle that Geant4 propagates (which Geant4 calls tracks), primary or not, is saved as an individual simb::MCParticle object into the output particle list. Each simb::MCParticle includes a Geant4-like track ID which is also recorded into each sim::IDE deposited by that particle. This information can be used to track all the deposition from a particle, or to backtrack the particle responsible of a deposition (but see below...). Note that the stored track ID may be different than the one Geant4 used (and, in particular, it's guaranteed to be unique within a sim::LArG4 instance output).
  • there are options (some set in sim::LArG4Parameters service) which allow for Geant4 tracks not to be saved as simb::MCParticle (e.g. ParticleKineticEnergyCut, KeepEMShowerDaughters). When these particles have deposited energy, their sim::IDE will report the ID of the first parent Geant4 track which is saved in the simb::MCParticle list, but with its sign flipped. Therefore, when tracking or backtracking (see above), comparisons should be performed using the absolute value of the sim::IDE (e.g. std::abs(ide.trackID)).

Timing

The LArG4 module produces sim::SimChannel objects from generated simb::MCParticle. Each particle ("primary") is assigned the time taken from its vertex (a 4-vector), which is expected to be represented in nanoseconds. The sim::SimChannel object is a collection of sim::IDE in time. The position in the sim::IDE is the location where some ionization occurred. The time associated to a sim::IDE is stored in tick units. The time it represents is the time when the ionization happened, which is the time of the primary particle plus the propagation time to the ionization location, plus the drift time, which the ionized electrons take to reach the anode wire. This time is then shifted to the frame of the electronics time via detinfo::DetectorClocks::G4ToElecTime(), which adds a configurable time offset. The time is converted into ticks via detinfo::DetectorClocks::TPCClock(), and this is the final value associated to the sim::IDE. For a more complete overview, see https://cdcvs.fnal.gov/redmine/projects/larsoft/wiki/Simulation#Simulation-Timing

Randomness

The random number generators used by this process are:

  • 'GEANT' instance: used by Geant4
  • 'propagation' instance: used in electron propagation

Configuration parameters

  • G4PhysListName (string, default: "larg4::PhysicsList"): whether to use the G4 overlap checker, which catches different issues than ROOT
  • CheckOverlaps (bool, default: false): whether to use the G4 overlap checker
  • DumpParticleList (bool, default: false): whether to print all MCParticles tracked; requires MakeMCParticles being true
  • DumpSimChannels (bool, default: false): whether to print all depositions on each SimChannel
  • SmartStacking (int, default: 0): whether to use class to dictate how tracks are put on stack (nonzero is on)
  • MakeMCParticles (flag, default: true): keep a list of the particles seen in the detector, and eventually save it; you almost always want this on
  • KeepParticlesInVolumes (list of strings, default: empty): list of volumes in which to keep simb::MCParticle objects (empty keeps all); requires MakeMCParticles being true
  • GeantCommandFile (string, required): G4 macro file to pass to G4Helper for setting G4 command
  • Seed (integer, not defined by default): if defined, override the seed for random number generator used in Geant4 simulation (which is obtained from NuRandomService by default)
  • PropagationSeed (integer, not defined by default): if defined, override the seed for the random generator used for electrons propagation to the wire planes (obtained from the NuRandomService by default)
  • InputLabels (list of strings, default: process all truth): optional list of generator labels whose produced simb::MCTruth will be simulated; if not specified, all simb::MCTruth vector data products are simulated
  • ChargeRecoveryMargin (double, default: 0): sets the maximum distance from a plane for the wire charge recovery to occur, in centimeters; for details on how it works, see larg4::LArVoxelReadout::SetOffPlaneChargeRecoveryMargin(). A value of 0 effectively disables this feature. All TPCs will have the same margin applied.

Simulation details

Source of the operational parameters

Some of the physical properties have their values set in FHiCL configuration (e.g. detinfo::LArParameters). Then, GEANT4 is informed of them via larg4::MaterialPropertyLoader. The material property table in GEANT4 is then used by other LArSoft components to discover the parameter values.

Among the parameters registered to GEANT4, the scintillation yields, i.e. how many scintillation photons are produced on average by 1 MeV of deposited energy, are also stored by type of ioniziong particle. These scintillation yields do include a prescale factor (that may include, for example, the photomultiplier quantum efficiency), from the ScintPreScale parameter of detinfo::LArPropertiesStandard or equivalent.

Reflectivity to optical photons

Two models are supported for the simulation of (scintillation) light crossing detector surfaces:

  1. the standard one from GEANT4, implemented in G4OpBoundaryProcess
  2. a simplified one, implemented in larg4::OpBoundaryProcessSimple

The model is chosen according to the value of detinfo::DetectorProperties::SimpleBoundary(), and the choice is currently exerted by larg4::OpticalPhysics.

The simplified model is faster and simpler: it only deals with absorption and reflection (both specular and diffues). This is the "default" model used in most contexts.

GEANT4 model is more complete and slower. It may take some art to fully configure all the properties of the materials at the sides of the surfaces. The price is a detailed simulation that includes among others refraction and wavelength shifting.

Scintillation

When using the fast optical simulation, which is the "standard" running mode, energy depositions from GEANT4 are "converted" into a number of scintillation photons by the global larg4::IonizationAndScintillation object instance, which internally utilizes the algorithm set up via configuration parameter IonAndScintCalculator in LArG4Parameters service (at the time of writing, "Separate" is supported and "NEST" is accepted too). The number of scintillation photons per energy unit is read from GEANT4 material properties table. It includes already quantum efficiency ("prescale") and it may depend on the type of ionizing particle, depending on the configuration (LArPropertiesStandard parameter ScintByParticleType). This value ("yield") is used as the average of a Poisson distribution from which the actual number of scintillation photons is extracted case by case. The implementation larg4::ISCalculationSeparate may also include medium saturation effects as well, if configured, but only if the scintillation yield is set not to depend on the type of ionizing particle. The number of scintillation photons is then distributed between the fast and slow component by a yield ratio also set in the material parameters, and the single photons are distributed in time accordingly to their component.

Definition at line 315 of file LArG4_module.cc.

Member Typedef Documentation

Definition at line 17 of file EDProducer.h.

template<typename UserConfig , typename KeysToIgnore = void>
using art::detail::Producer::Table = Modifier::Table<UserConfig, KeysToIgnore>
inherited

Definition at line 26 of file Producer.h.

Constructor & Destructor Documentation

larg4::LArG4::LArG4 ( fhicl::ParameterSet const &  pset)
explicit

Definition at line 406 of file LArG4_module.cc.

References art::errors::Configuration, art::detail::EngineCreator::createEngine(), e, fAllPhysicsLists, fCheckOverlaps, fDetProp, fdumpParticleList, fdumpSimChannels, fEngine, fG4MacroPath, fG4PhysListName, sim::LArG4Parameters::FillSimEnergyDeposits(), fInputLabels, fKeepParticlesInVolumes, fMakeMCParticles, fOffPlaneMargin, fSmartStacking, fSparsifyTrajectories, fStoreDroppedMCParticles, fStoreReflected, fUseLitePhotons, MF_LOG_DEBUG, sim::LArG4Parameters::NoElectronPropagation(), sim::LArG4Parameters::NoPhotonPropagation(), art::ProductRegistryHelper::produces(), art::errors::ServiceNotFound, phot::PhotonVisibilityService::StoreReflected(), and sim::LArG4Parameters::UseLitePhotons().

407  : art::EDProducer{pset}
408  , fG4PhysListName(pset.get<std::string>("G4PhysListName", "larg4::PhysicsList"))
409  , fCheckOverlaps(pset.get<bool>("CheckOverlaps", false))
410  , fMakeMCParticles(pset.get<bool>("MakeMCParticles", true))
411  , fStoreDroppedMCParticles(pset.get<bool>("StoreDroppedMCParticles", false))
412  , fdumpParticleList(pset.get<bool>("DumpParticleList", false))
413  , fdumpSimChannels(pset.get<bool>("DumpSimChannels", false))
414  , fSmartStacking(pset.get<int>("SmartStacking", 0))
415  , fOffPlaneMargin(pset.get<double>("ChargeRecoveryMargin", 0.0))
416  , fKeepParticlesInVolumes(pset.get<std::vector<std::string>>("KeepParticlesInVolumes", {}))
417  , fSparsifyTrajectories(pset.get<bool>("SparsifyTrajectories", false))
418  , fEngine(art::ServiceHandle<rndm::NuRandomService>()->registerAndSeedEngine(
419  createEngine(0, "HepJamesRandom", "propagation"),
420  "HepJamesRandom",
421  "propagation",
422  pset,
423  "PropagationSeed"))
426  {
427  MF_LOG_DEBUG("LArG4") << "Debug: LArG4()";
428 
429  if (!fMakeMCParticles) { // configuration option consistency
430  if (fdumpParticleList) {
432  << "Option `DumpParticleList` can't be set if `MakeMCParticles` is unset.\n";
433  }
434  if (!fKeepParticlesInVolumes.empty()) {
436  << "Option `KeepParticlesInVolumes` can't be set if `MakeMCParticles` is unset.\n";
437  }
438  } // if
439 
440  if (pset.has_key("Seed")) {
442  << "The configuration of LArG4 module has the discontinued 'Seed' parameter.\n"
443  "Seeds are now controlled by two parameters: 'GEANTSeed' and 'PropagationSeed'.";
444  }
445  // setup the random number service for Geant4, the "G4Engine" label is a
446  // special tag setting up a global engine for use by Geant4/CLHEP;
447  // obtain the random seed from NuRandomService,
448  // unless overridden in configuration with key "Seed" or "GEANTSeed"
449  // FIXME: THIS APPEARS TO BE A NO-OP; IS IT NEEDED?
450  (void)art::ServiceHandle<rndm::NuRandomService>()->registerAndSeedEngine(
451  createEngine(0, "G4Engine", "GEANT"), "G4Engine", "GEANT", pset, "GEANTSeed");
452 
453  //get a list of generators to use, otherwise, we'll end up looking for anything that's
454  //made an MCTruth object
455  bool useInputLabels =
456  pset.get_if_present<std::vector<std::string>>("InputLabels", fInputLabels);
457  if (!useInputLabels) fInputLabels.resize(0);
458 
461 
462  if (!lgp->NoPhotonPropagation()) {
463  try {
466  }
467  catch (art::Exception const& e) {
468  // If the service is not configured, then just keep the default
469  // false for reflected light. If reflected photons are simulated
470  // without PVS they will show up in the regular SimPhotons collection
471  if (e.categoryCode() != art::errors::ServiceNotFound) throw;
472  }
473 
474  if (!fUseLitePhotons) {
475  produces<std::vector<sim::SimPhotons>>();
476  if (fStoreReflected) { produces<std::vector<sim::SimPhotons>>("Reflected"); }
477  }
478  else {
479  produces<std::vector<sim::SimPhotonsLite>>();
480  produces<std::vector<sim::OpDetBacktrackerRecord>>();
481  if (fStoreReflected) {
482  produces<std::vector<sim::SimPhotonsLite>>("Reflected");
483  produces<std::vector<sim::OpDetBacktrackerRecord>>("Reflected");
484  }
485  }
486  }
487 
488  if (lgp->FillSimEnergyDeposits()) {
489  produces<std::vector<sim::SimEnergyDeposit>>("TPCActive");
490  produces<std::vector<sim::SimEnergyDeposit>>("Other");
491  }
492 
493  if (fMakeMCParticles) {
494  produces<std::vector<simb::MCParticle>>();
495  produces<art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo>>();
496  }
497  if (fStoreDroppedMCParticles) { produces<std::vector<sim::MCParticleLite>>(); }
498  if (!lgp->NoElectronPropagation()) produces<std::vector<sim::SimChannel>>();
499  produces<std::vector<sim::AuxDetSimChannel>>();
500 
501  // constructor decides if initialized value is a path or an environment variable
502  cet::search_path sp("FW_SEARCH_PATH");
503 
504  sp.find_file(pset.get<std::string>("GeantCommandFile"), fG4MacroPath);
505  struct stat sb;
506  if (fG4MacroPath.empty() || stat(fG4MacroPath.c_str(), &sb) != 0)
507  // failed to resolve the file name
508  throw cet::exception("NoG4Macro") << "G4 macro file " << fG4MacroPath << " not found!\n";
509  }
std::vector< std::string > fInputLabels
base_engine_t & createEngine(seed_t seed)
bool fStoreDroppedMCParticles
Whether to keep a sim::MCParticleLite list of dropped particles.
std::string fG4MacroPath
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
bool fMakeMCParticles
Whether to keep a sim::MCParticle list.
bool NoPhotonPropagation() const
std::vector< std::string > fKeepParticlesInVolumes
Only write particles that have trajectories through these volumes.
bool fSparsifyTrajectories
Sparsify MCParticle Trajectories.
int fSmartStacking
Whether to instantiate and use class to.
bool fdumpSimChannels
Whether each event&#39;s sim::Channel will be displayed.
bool NoElectronPropagation() const
bool FillSimEnergyDeposits() const
bool fdumpParticleList
Whether each event&#39;s sim::ParticleList will be displayed.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool fUseLitePhotons
#define MF_LOG_DEBUG(id)
std::string fG4PhysListName
predefined physics list to use if not making a custom one
bool fCheckOverlaps
Whether to use the G4 overlap checker.
bool fStoreReflected
AllPhysicsLists fAllPhysicsLists
detinfo::DetectorPropertiesData fDetProp
Must outlive fAllPhysicsLists!
Float_t e
Definition: plot.C:35
CLHEP::HepRandomEngine & fEngine
double fOffPlaneMargin
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool UseLitePhotons() const

Member Function Documentation

void larg4::LArG4::beginJob ( )
overrideprivatevirtual

Reimplemented from art::EDProducer.

Definition at line 512 of file LArG4_module.cc.

References g4b::UserActionManager::AddAndAdoptAction(), larg4::IonizationAndScintillation::CreateInstance(), fCheckOverlaps, fEngine, fG4Help, fG4MacroPath, fG4PhysListName, fMakeMCParticles, fOffPlaneMargin, fparticleListAction, fSmartStacking, fStoreDroppedMCParticles, fUseLitePhotons, fVoxelReadoutGeometry, geo::GeometryCore::GDMLFile(), larg4::MaterialPropertyLoader::GetPropertiesFromServices(), g4b::UserActionManager::Instance(), sim::LArG4Parameters::KeepEMShowerDaughters(), larg4::LArVoxelReadout::Setup_t::offPlaneMargin, geo::GeometryCore::OpDetGeoName(), sim::LArG4Parameters::ParticleKineticEnergyCut(), larg4::LArVoxelReadout::Setup_t::propGen, larg4::LArVoxelReadoutGeometry::Setup_t::readoutSetup, sim::LArG4Parameters::StoreTrajectories(), and larg4::MaterialPropertyLoader::UpdateGeometry().

513  {
514  fG4Help = std::make_unique<g4b::G4Helper>(fG4MacroPath, fG4PhysListName);
515 
516  if (fCheckOverlaps) fG4Help->SetOverlapCheck(true);
517 
519  fG4Help->ConstructDetector(geom->GDMLFile());
520 
521  // Get the logical volume store and assign material properties
523  auto const detProp =
525  mpl.GetPropertiesFromServices(detProp);
526  mpl.UpdateGeometry(G4LogicalVolumeStore::GetInstance());
527 
528  // Tell the detector about the parallel LAr voxel geometry.
529  std::vector<G4VUserParallelWorld*> pworlds;
530 
531  // Intialize G4 physics and primary generator action
532  fG4Help->InitPhysics();
533 
534  // create the ionization and scintillation calculator;
535  // this is a singleton (!) so it does not make sense
536  // to create it in LArVoxelReadoutGeometry
538 
539  // make a parallel world for each TPC in the detector
540  LArVoxelReadoutGeometry::Setup_t readoutGeomSetupData;
541  readoutGeomSetupData.readoutSetup.offPlaneMargin = fOffPlaneMargin;
542  readoutGeomSetupData.readoutSetup.propGen = &fEngine;
543 
545  new LArVoxelReadoutGeometry("LArVoxelReadoutGeometry", readoutGeomSetupData);
546  pworlds.push_back(fVoxelReadoutGeometry);
547  pworlds.push_back(
548  new OpDetReadoutGeometry(geom->OpDetGeoName(), "OpDetReadoutGeometry", fUseLitePhotons));
549  pworlds.push_back(new AuxDetReadoutGeometry("AuxDetReadoutGeometry"));
550 
551  fG4Help->SetParallelWorlds(pworlds);
552 
553  // moved up
554  // Intialize G4 physics and primary generator action
555  fG4Help->InitPhysics();
556 
557  // Use the UserActionManager to handle all the Geant4 user hooks.
559 
560  // User-action class for accumulating LAr voxels.
562 
563  // User-action class for accumulating particles and trajectories
564  // produced in the detector.
566  lgp->StoreTrajectories(),
567  lgp->KeepEMShowerDaughters(),
571 
572  // UserActionManager is now configured so continue G4 initialization
573  fG4Help->SetUserAction();
574 
575  // With an enormous detector with lots of rock ala LAr34 (nee LAr20)
576  // we need to be smarter about stacking.
577  if (fSmartStacking > 0) {
578  G4UserStackingAction* stacking_action = new LArStackingAction(fSmartStacking);
579  fG4Help->GetRunManager()->SetUserAction(stacking_action);
580  }
581  }
std::unique_ptr< g4b::G4Helper > fG4Help
G4 interface object.
bool fStoreDroppedMCParticles
Whether to keep a sim::MCParticleLite list of dropped particles.
bool KeepEMShowerDaughters() const
std::string fG4MacroPath
Stores material properties and sends them to GEANT4 geometry.
void GetPropertiesFromServices(detinfo::DetectorPropertiesData const &detProp)
Imports properties from LArSoft services.
bool fMakeMCParticles
Whether to keep a sim::MCParticle list.
std::string OpDetGeoName(CryostatID const &cid=cryostat_zero) const
Returns gdml string which gives sensitive opdet name.
bool StoreTrajectories() const
int fSmartStacking
Whether to instantiate and use class to.
larg4::ParticleListAction * fparticleListAction
Geant4 user action to particle information.
static void AddAndAdoptAction(UserAction *a)
void UpdateGeometry(G4LogicalVolumeStore *lvs)
Updates the material properties with the collected values.
double ParticleKineticEnergyCut() const
static UserActionManager * Instance()
bool fUseLitePhotons
static IonizationAndScintillation * CreateInstance(detinfo::DetectorPropertiesData const &detProp, CLHEP::HepRandomEngine &engine)
std::string fG4PhysListName
predefined physics list to use if not making a custom one
std::string const & GDMLFile() const
Returns the full directory path to the GDML file source.
Definition: GeometryCore.h:193
bool fCheckOverlaps
Whether to use the G4 overlap checker.
CLHEP::HepRandomEngine & fEngine
double fOffPlaneMargin
LArVoxelReadoutGeometry * fVoxelReadoutGeometry
void larg4::LArG4::beginRun ( art::Run run)
overrideprivatevirtual

Reimplemented from art::EDProducer.

Definition at line 583 of file LArG4_module.cc.

References CreateParticleVolumeFilter(), fKeepParticlesInVolumes, fparticleListAction, and larg4::ParticleListAction::ParticleFilter().

584  {
585  // prepare the filter object (null if no filtering)
586  std::set<std::string> volnameset(fKeepParticlesInVolumes.begin(),
589  }
std::vector< std::string > fKeepParticlesInVolumes
Only write particles that have trajectories through these volumes.
larg4::ParticleListAction * fparticleListAction
Geant4 user action to particle information.
void ParticleFilter(std::unique_ptr< util::PositionInVolumeFilter > &&filter)
Grabs a particle filter.
std::unique_ptr< util::PositionInVolumeFilter > CreateParticleVolumeFilter(std::set< std::string > const &vol_names) const
Pointer used for correctly updating the clock data state.
template<typename T , BranchType BT>
ProductToken< T > art::ModuleBase::consumes ( InputTag const &  tag)
protectedinherited

Definition at line 61 of file ModuleBase.h.

References art::ModuleBase::collector_, and art::ConsumesCollector::consumes().

62  {
63  return collector_.consumes<T, BT>(tag);
64  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
ProductToken< T > consumes(InputTag const &)
ConsumesCollector & art::ModuleBase::consumesCollector ( )
protectedinherited

Definition at line 57 of file ModuleBase.cc.

References art::ModuleBase::collector_.

58  {
59  return collector_;
60  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
template<typename T , BranchType BT>
void art::ModuleBase::consumesMany ( )
protectedinherited

Definition at line 75 of file ModuleBase.h.

References art::ModuleBase::collector_, and art::ConsumesCollector::consumesMany().

76  {
77  collector_.consumesMany<T, BT>();
78  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::ModuleBase::consumesView ( InputTag const &  )
protectedinherited
template<typename T , BranchType BT>
ViewToken<T> art::ModuleBase::consumesView ( InputTag const &  tag)
inherited

Definition at line 68 of file ModuleBase.h.

References art::ModuleBase::collector_, and art::ConsumesCollector::consumesView().

69  {
70  return collector_.consumesView<T, BT>(tag);
71  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
ViewToken< Element > consumesView(InputTag const &)
std::unique_ptr< util::PositionInVolumeFilter > larg4::LArG4::CreateParticleVolumeFilter ( std::set< std::string > const &  vol_names) const
private

Pointer used for correctly updating the clock data state.

Configures and returns a particle filter

Definition at line 591 of file LArG4_module.cc.

References util::empty().

Referenced by beginRun().

593  {
594  // if we don't have favourite volumes, don't even bother creating a filter
595  if (empty(vol_names)) return {};
596 
597  auto const& geom = *art::ServiceHandle<geo::Geometry const>();
598 
599  std::vector<std::vector<TGeoNode const*>> node_paths = geom.FindAllVolumePaths(vol_names);
600 
601  // collection of interesting volumes
603  GeoVolumePairs.reserve(node_paths.size()); // because we are obsessed
604 
605  //for each interesting volume, follow the node path and collect
606  //total rotations and translations
607  for (size_t iVolume = 0; iVolume < node_paths.size(); ++iVolume) {
608  std::vector<TGeoNode const*> path = node_paths[iVolume];
609 
610  auto pTransl = new TGeoTranslation(0., 0., 0.);
611  auto pRot = new TGeoRotation();
612  for (TGeoNode const* node : path) {
613  TGeoTranslation thistranslate(*node->GetMatrix());
614  TGeoRotation thisrotate(*node->GetMatrix());
615  pTransl->Add(&thistranslate);
616  *pRot = *pRot * thisrotate;
617  }
618 
619  // for some reason, pRot and pTransl don't have tr and rot bits set
620  // correctly make new translations and rotations so bits are set correctly
621  auto pTransl2 = new TGeoTranslation(
622  pTransl->GetTranslation()[0], pTransl->GetTranslation()[1], pTransl->GetTranslation()[2]);
623  double phi = 0., theta = 0., psi = 0.;
624  pRot->GetAngles(phi, theta, psi);
625  auto pRot2 = new TGeoRotation();
626  pRot2->SetAngles(phi, theta, psi);
627 
628  auto pTransf = new TGeoCombiTrans(*pTransl2, *pRot2);
629  GeoVolumePairs.emplace_back(node_paths[iVolume].back()->GetVolume(), pTransf);
630  }
631 
632  return std::make_unique<util::PositionInVolumeFilter>(std::move(GeoVolumePairs));
633  } // CreateParticleVolumeFilter()
std::vector< VolumeInfo_t > AllVolumeInfo_t
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
void art::detail::Producer::doBeginJob ( SharedResources const &  resources)
inherited

Definition at line 22 of file Producer.cc.

References art::detail::Producer::beginJobWithFrame(), and art::detail::Producer::setupQueues().

23  {
24  setupQueues(resources);
25  ProcessingFrame const frame{ScheduleID{}};
26  beginJobWithFrame(frame);
27  }
virtual void setupQueues(SharedResources const &)=0
virtual void beginJobWithFrame(ProcessingFrame const &)=0
bool art::detail::Producer::doBeginRun ( RunPrincipal rp,
ModuleContext const &  mc 
)
inherited

Definition at line 65 of file Producer.cc.

References art::detail::Producer::beginRunWithFrame(), art::RangeSet::forRun(), art::RunPrincipal::makeRun(), r, art::RunPrincipal::runID(), and art::ModuleContext::scheduleID().

66  {
67  auto r = rp.makeRun(mc, RangeSet::forRun(rp.runID()));
68  ProcessingFrame const frame{mc.scheduleID()};
69  beginRunWithFrame(r, frame);
70  r.commitProducts();
71  return true;
72  }
TRandom r
Definition: spectrum.C:23
virtual void beginRunWithFrame(Run &, ProcessingFrame const &)=0
static RangeSet forRun(RunID)
Definition: RangeSet.cc:51
bool art::detail::Producer::doBeginSubRun ( SubRunPrincipal srp,
ModuleContext const &  mc 
)
inherited

Definition at line 85 of file Producer.cc.

References art::detail::Producer::beginSubRunWithFrame(), art::RangeSet::forSubRun(), art::SubRunPrincipal::makeSubRun(), art::ModuleContext::scheduleID(), and art::SubRunPrincipal::subRunID().

86  {
87  auto sr = srp.makeSubRun(mc, RangeSet::forSubRun(srp.subRunID()));
88  ProcessingFrame const frame{mc.scheduleID()};
89  beginSubRunWithFrame(sr, frame);
90  sr.commitProducts();
91  return true;
92  }
virtual void beginSubRunWithFrame(SubRun &, ProcessingFrame const &)=0
static RangeSet forSubRun(SubRunID)
Definition: RangeSet.cc:57
void art::detail::Producer::doEndJob ( )
inherited

Definition at line 30 of file Producer.cc.

References art::detail::Producer::endJobWithFrame().

31  {
32  ProcessingFrame const frame{ScheduleID{}};
33  endJobWithFrame(frame);
34  }
virtual void endJobWithFrame(ProcessingFrame const &)=0
bool art::detail::Producer::doEndRun ( RunPrincipal rp,
ModuleContext const &  mc 
)
inherited

Definition at line 75 of file Producer.cc.

References art::detail::Producer::endRunWithFrame(), art::RunPrincipal::makeRun(), r, art::ModuleContext::scheduleID(), and art::Principal::seenRanges().

76  {
77  auto r = rp.makeRun(mc, rp.seenRanges());
78  ProcessingFrame const frame{mc.scheduleID()};
79  endRunWithFrame(r, frame);
80  r.commitProducts();
81  return true;
82  }
TRandom r
Definition: spectrum.C:23
virtual void endRunWithFrame(Run &, ProcessingFrame const &)=0
bool art::detail::Producer::doEndSubRun ( SubRunPrincipal srp,
ModuleContext const &  mc 
)
inherited

Definition at line 95 of file Producer.cc.

References art::detail::Producer::endSubRunWithFrame(), art::SubRunPrincipal::makeSubRun(), art::ModuleContext::scheduleID(), and art::Principal::seenRanges().

96  {
97  auto sr = srp.makeSubRun(mc, srp.seenRanges());
98  ProcessingFrame const frame{mc.scheduleID()};
99  endSubRunWithFrame(sr, frame);
100  sr.commitProducts();
101  return true;
102  }
virtual void endSubRunWithFrame(SubRun &, ProcessingFrame const &)=0
bool art::detail::Producer::doEvent ( EventPrincipal ep,
ModuleContext const &  mc,
std::atomic< std::size_t > &  counts_run,
std::atomic< std::size_t > &  counts_passed,
std::atomic< std::size_t > &  counts_failed 
)
inherited

Definition at line 105 of file Producer.cc.

References art::detail::Producer::checkPutProducts_, e, art::EventPrincipal::makeEvent(), art::detail::Producer::produceWithFrame(), and art::ModuleContext::scheduleID().

110  {
111  auto e = ep.makeEvent(mc);
112  ++counts_run;
113  ProcessingFrame const frame{mc.scheduleID()};
114  produceWithFrame(e, frame);
115  e.commitProducts(checkPutProducts_, &expectedProducts<InEvent>());
116  ++counts_passed;
117  return true;
118  }
bool const checkPutProducts_
Definition: Producer.h:70
Float_t e
Definition: plot.C:35
virtual void produceWithFrame(Event &, ProcessingFrame const &)=0
void art::detail::Producer::doRespondToCloseInputFile ( FileBlock const &  fb)
inherited

Definition at line 44 of file Producer.cc.

References art::detail::Producer::respondToCloseInputFileWithFrame().

45  {
46  ProcessingFrame const frame{ScheduleID{}};
48  }
virtual void respondToCloseInputFileWithFrame(FileBlock const &, ProcessingFrame const &)=0
TFile fb("Li6.root")
void art::detail::Producer::doRespondToCloseOutputFiles ( FileBlock const &  fb)
inherited

Definition at line 58 of file Producer.cc.

References art::detail::Producer::respondToCloseOutputFilesWithFrame().

59  {
60  ProcessingFrame const frame{ScheduleID{}};
62  }
virtual void respondToCloseOutputFilesWithFrame(FileBlock const &, ProcessingFrame const &)=0
TFile fb("Li6.root")
void art::detail::Producer::doRespondToOpenInputFile ( FileBlock const &  fb)
inherited

Definition at line 37 of file Producer.cc.

References art::detail::Producer::respondToOpenInputFileWithFrame().

38  {
39  ProcessingFrame const frame{ScheduleID{}};
41  }
virtual void respondToOpenInputFileWithFrame(FileBlock const &, ProcessingFrame const &)=0
TFile fb("Li6.root")
void art::detail::Producer::doRespondToOpenOutputFiles ( FileBlock const &  fb)
inherited

Definition at line 51 of file Producer.cc.

References art::detail::Producer::respondToOpenOutputFilesWithFrame().

52  {
53  ProcessingFrame const frame{ScheduleID{}};
55  }
virtual void respondToOpenOutputFilesWithFrame(FileBlock const &, ProcessingFrame const &)=0
TFile fb("Li6.root")
void art::Modifier::fillProductDescriptions ( )
inherited

Definition at line 10 of file Modifier.cc.

References art::ProductRegistryHelper::fillDescriptions(), and art::ModuleBase::moduleDescription().

11  {
13  }
void fillDescriptions(ModuleDescription const &md)
ModuleDescription const & moduleDescription() const
Definition: ModuleBase.cc:13
std::array< std::vector< ProductInfo >, NumBranchTypes > const & art::ModuleBase::getConsumables ( ) const
inherited

Definition at line 43 of file ModuleBase.cc.

References art::ModuleBase::collector_, and art::ConsumesCollector::getConsumables().

44  {
45  return collector_.getConsumables();
46  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
std::array< std::vector< ProductInfo >, NumBranchTypes > const & getConsumables() const
std::unique_ptr< Worker > art::ModuleBase::makeWorker ( WorkerParams const &  wp)
inherited

Definition at line 37 of file ModuleBase.cc.

References art::ModuleBase::doMakeWorker(), and art::NumBranchTypes.

38  {
39  return doMakeWorker(wp);
40  }
virtual std::unique_ptr< Worker > doMakeWorker(WorkerParams const &wp)=0
template<typename T , BranchType BT>
ProductToken< T > art::ModuleBase::mayConsume ( InputTag const &  tag)
protectedinherited

Definition at line 82 of file ModuleBase.h.

References art::ModuleBase::collector_, and art::ConsumesCollector::mayConsume().

83  {
84  return collector_.mayConsume<T, BT>(tag);
85  }
ProductToken< T > mayConsume(InputTag const &)
ConsumesCollector collector_
Definition: ModuleBase.h:56
template<typename T , BranchType BT>
void art::ModuleBase::mayConsumeMany ( )
protectedinherited

Definition at line 96 of file ModuleBase.h.

References art::ModuleBase::collector_, and art::ConsumesCollector::mayConsumeMany().

97  {
98  collector_.mayConsumeMany<T, BT>();
99  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::ModuleBase::mayConsumeView ( InputTag const &  )
protectedinherited
template<typename T , BranchType BT>
ViewToken<T> art::ModuleBase::mayConsumeView ( InputTag const &  tag)
inherited

Definition at line 89 of file ModuleBase.h.

References art::ModuleBase::collector_, and art::ConsumesCollector::mayConsumeView().

90  {
91  return collector_.mayConsumeView<T, BT>(tag);
92  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
ViewToken< Element > mayConsumeView(InputTag const &)
ModuleDescription const & art::ModuleBase::moduleDescription ( ) const
inherited

Definition at line 13 of file ModuleBase.cc.

References art::errors::LogicError.

Referenced by art::OutputModule::doRespondToOpenInputFile(), art::OutputModule::doWriteEvent(), art::Modifier::fillProductDescriptions(), art::OutputModule::makePlugins_(), art::OutputWorker::OutputWorker(), reco::shower::LArPandoraModularShowerCreation::produce(), art::Modifier::registerProducts(), and art::OutputModule::registerProducts().

14  {
15  if (md_.has_value()) {
16  return *md_;
17  }
18 
20  "There was an error while calling moduleDescription().\n"}
21  << "The moduleDescription() base-class member function cannot be called\n"
22  "during module construction. To determine which module is "
23  "responsible\n"
24  "for calling it, find the '<module type>:<module "
25  "label>@Construction'\n"
26  "tag in the message prefix above. Please contact artists@fnal.gov\n"
27  "for guidance.\n";
28  }
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::optional< ModuleDescription > md_
Definition: ModuleBase.h:55
void larg4::LArG4::produce ( art::Event evt)
overrideprivatevirtual

The main routine of this module: Fetch the primary particles from the event, simulate their evolution in the detector, and produce the detector response.

Implements art::EDProducer.

Definition at line 635 of file LArG4_module.cc.

References geo::GeometryCore::AuxDet(), sim::SimChannel::Channel(), larg4::AuxDetReadout::clear(), larg4::OpDetPhotonTable::ClearEnergyDeposits(), larg4::OpDetPhotonTable::ClearTable(), geo::GeometryCore::Cryostat(), DEFINE_ART_MODULE, sim::SimPhotonsLite::DetectedPhotons, sim::dump::DumpMCParticle(), sim::dump::DumpMCTruth(), util::empty(), fdumpParticleList, fdumpSimChannels, fG4Help, fInputLabels, fMakeMCParticles, fparticleListAction, fSparsifyTrajectories, fStoreDroppedMCParticles, fStoreReflected, fUseLitePhotons, fVoxelReadoutGeometry, art::Ptr< T >::get(), larg4::AuxDetReadout::GetAuxDetSimChannel(), art::ProductRetriever::getByLabel(), larg4::OpDetPhotonTable::GetLitePhotons(), art::ProductRetriever::getMany(), larg4::OpDetPhotonTable::GetPhotons(), larg4::ParticleListAction::GetPrimaryTruthIndex(), art::Event::id(), larg4::OpDetPhotonTable::Instance(), larg4::ParticleListAction::isDropped(), art::errors::LogicError, MF_LOG_DEBUG, simb::MCParticle::Mother(), geo::GeometryCore::NAuxDets(), geo::GeometryCore::Ncryostats(), geo::GeometryCore::NOpDets(), geo::AuxDetGeo::NSensitiveVolume(), geo::CryostatGeo::NTPC(), sim::SimPhotonsLite::OpChannel, simb::MCTruth::Origin(), sim::MCParticleLite::Origin(), art::Handle< T >::provenance(), art::Event::put(), larg4::ParticleListAction::ResetTrackIDOffset(), sc, util::size(), sim::ParticleList::size(), simb::MCParticle::SparsifyTrajectory(), simb::MCParticle::StatusCode(), sim::SimChannel::TDCIDEMap(), simb::MCParticle::TrackId(), larg4::ParticleListAction::YieldDroppedList(), larg4::ParticleListAction::YieldList(), larg4::OpDetPhotonTable::YieldOpDetBacktrackerRecords(), larg4::OpDetPhotonTable::YieldReflectedOpDetBacktrackerRecords(), and larg4::OpDetPhotonTable::YieldSimEnergyDeposits().

636  {
637  MF_LOG_DEBUG("LArG4") << "produce()";
638  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
639  auto const detProp =
641  LArVoxelReadoutGeometry::Sentry const set_for_event{fVoxelReadoutGeometry, clockData, detProp};
642 
643  // loop over the lists and put the particles and voxels into the event as
644  // collections
645  auto scCol = std::make_unique<std::vector<sim::SimChannel>>();
646  auto adCol = std::make_unique<std::vector<sim::AuxDetSimChannel>>();
647  auto tpassn = fMakeMCParticles ?
648  std::make_unique<
650  nullptr;
651  auto partCol = fMakeMCParticles ? std::make_unique<std::vector<simb::MCParticle>>() : nullptr;
652  auto droppedPartCol =
653  fStoreDroppedMCParticles ? std::make_unique<std::vector<sim::MCParticleLite>>() : nullptr;
654  auto PhotonCol = std::make_unique<std::vector<sim::SimPhotons>>();
655  auto PhotonColRefl = std::make_unique<std::vector<sim::SimPhotons>>();
656  auto LitePhotonCol = std::make_unique<std::vector<sim::SimPhotonsLite>>();
657  auto LitePhotonColRefl = std::make_unique<std::vector<sim::SimPhotonsLite>>();
658  auto cOpDetBacktrackerRecordCol = std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
659  auto cOpDetBacktrackerRecordColRefl =
660  std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
661 
662  std::optional<art::PtrMaker<simb::MCParticle>> makeMCPartPtr;
663  if (fMakeMCParticles) makeMCPartPtr.emplace(evt);
664 
665  // for energy deposits
666  auto edepCol_TPCActive = std::make_unique<std::vector<sim::SimEnergyDeposit>>();
667  auto edepCol_Other = std::make_unique<std::vector<sim::SimEnergyDeposit>>();
668 
669  // Fetch the lists of LAr voxels and particles.
672 
673  // Clear the detected photon table
675  if (lgp->FillSimEnergyDeposits()) OpDetPhotonTable::Instance()->ClearEnergyDeposits();
676 
677  // reset the track ID offset as we have a new collection of interactions
679 
680  //look to see if there is any MCTruth information for this
681  //event
682  std::vector<art::Handle<std::vector<simb::MCTruth>>> mclists;
683  if (empty(fInputLabels))
684  //evt.getManyByType(mclists);
685  mclists = evt.getMany<std::vector<simb::MCTruth>>();
686  else {
687  mclists.resize(fInputLabels.size());
688  for (size_t i = 0; i < fInputLabels.size(); i++)
689  evt.getByLabel(fInputLabels[i], mclists[i]);
690  }
691 
692  unsigned int nGeneratedParticles = 0;
693 
694  // Need to process Geant4 simulation for each interaction separately.
695  for (size_t mcl = 0; mcl < mclists.size(); ++mcl) {
696 
697  art::Handle<std::vector<simb::MCTruth>> mclistHandle = mclists[mcl];
698 
699  for (size_t m = 0; m < mclistHandle->size(); ++m) {
700  art::Ptr<simb::MCTruth> mct(mclistHandle, m);
701 
702  MF_LOG_DEBUG("LArG4") << *(mct.get());
703 
704  // The following tells Geant4 to track the particles in this interaction.
705  fG4Help->G4Run(mct);
706 
707  if (!partCol) continue;
708  assert(tpassn);
709 
710  // receive the particle list
712 
713  for (auto const& partPair : particleList) {
714  simb::MCParticle& p = *(partPair.second);
715  ++nGeneratedParticles;
716 
717  // if the particle has been marked as dropped, we don't save it
718  // (as of LArSoft ~v5.6 this does not ever happen because
719  // ParticleListAction has already taken care of deleting them)
720  if (ParticleListAction::isDropped(&p)) continue;
721 
722  sim::GeneratedParticleInfo const truthInfo{
724  if (!truthInfo.hasGeneratedParticleIndex() && (p.Mother() == 0)) {
725  // this means it's primary but with no information; logic error!!
727  error << "Failed to match primary particle:\n";
729  error << "\nwith particles from the truth record '"
730  << mclistHandle.provenance()->inputTag() << "':\n";
731  sim::dump::DumpMCTruth(error, *mct, 2U, " "); // 2 points per line
732  error << "\n";
733  throw error;
734  }
735 
737 
738  partCol->push_back(std::move(p));
739 
740  tpassn->addSingle(mct, (*makeMCPartPtr)(partCol->size() - 1), truthInfo);
741 
742  } // for(particleList)
743 
744  if (fStoreDroppedMCParticles && droppedPartCol) {
745  // Request a list of dropped particles
746  // Store them in MCParticleLite format
747  sim::ParticleList droppedParticleList = fparticleListAction->YieldDroppedList();
748  droppedPartCol->reserve(droppedParticleList.size());
749 
750  for (auto const& partPair : droppedParticleList) {
751  simb::MCParticle& p = *(partPair.second);
752  if (ParticleListAction::isDropped(&p)) continue;
753  if (p.StatusCode() != 1) continue;
754 
755  sim::MCParticleLite mini_mcp(p);
756  mini_mcp.Origin(mct->Origin());
757 
758  droppedPartCol->push_back(std::move(mini_mcp));
759  } // for(droppedParticleList)
760  }
761 
762  // Has the user request a detailed dump of the output objects?
763  if (fdumpParticleList) {
764  mf::LogInfo("LArG4") << "Dump sim::ParticleList; size()=" << particleList.size() << "\n"
765  << particleList;
766  }
767  }
768 
769  } // end loop over interactions
770 
771  // get the electrons from the LArVoxelReadout sensitive detector
772  // Get the sensitive-detector manager.
773  G4SDManager* sdManager = G4SDManager::GetSDMpointer();
774 
775  // Find the sensitive detector with the name "LArVoxelSD".
776  auto theOpDetDet = dynamic_cast<OpDetSensitiveDetector*>(
777  sdManager->FindSensitiveDetector("OpDetSensitiveDetector"));
778 
779  // Store the contents of the detected photon table
780  //
781  if (theOpDetDet) {
782 
783  if (!lgp->NoPhotonPropagation()) {
784 
785  for (int Reflected = 0; Reflected <= 1; Reflected++) {
786  if (Reflected && !fStoreReflected) continue;
787 
788  if (!fUseLitePhotons) {
789  MF_LOG_DEBUG("Optical") << "Storing OpDet Hit Collection in Event";
790  std::vector<sim::SimPhotons>& ThePhotons =
792  if (Reflected)
793  PhotonColRefl->reserve(ThePhotons.size());
794  else
795  PhotonCol->reserve(ThePhotons.size());
796  for (auto& it : ThePhotons) {
797  if (Reflected)
798  PhotonColRefl->push_back(std::move(it));
799  else
800  PhotonCol->push_back(std::move(it));
801  }
802  }
803  else {
804  MF_LOG_DEBUG("Optical") << "Storing OpDet Hit Collection in Event";
805 
806  std::map<int, std::map<int, int>> ThePhotons =
808 
809  if (size(ThePhotons) > 0) {
810  LitePhotonCol->reserve(ThePhotons.size());
811  for (auto const& [opChannel, detectedPhotons] : ThePhotons) {
813  ph.OpChannel = opChannel;
814  ph.DetectedPhotons = detectedPhotons;
815  if (Reflected)
816  LitePhotonColRefl->push_back(std::move(ph));
817  else
818  LitePhotonCol->push_back(std::move(ph));
819  }
820  }
821  }
822  if (Reflected)
823  *cOpDetBacktrackerRecordColRefl =
825  else
826  *cOpDetBacktrackerRecordCol =
828  }
829  } //end if no photon propagation
830 
831  if (lgp->FillSimEnergyDeposits()) {
832  // we steal the only existing copy of the energy deposit map. Oink!
834  for (auto& [volumeName, edepCol] : edepMap) {
835  // note: constant reference to a (smart) pointer to non-const data
836  auto const& destColl =
837  boost::contains(volumeName, "TPCActive") ? edepCol_TPCActive : edepCol_Other;
838  append(*destColl, std::move(edepCol));
839  } // for
840  }
841  } //end if theOpDetDet
842 
843  if (!lgp->NoElectronPropagation()) {
844 
845  // only put the sim::SimChannels into the event once, not once for every
846  // MCTruth in the event
847 
848  std::set<LArVoxelReadout*> ReadoutList; // to be cleared later on
849 
850  for (unsigned int c = 0; c < geom->Ncryostats(); ++c) {
851 
852  // map to keep track of which channels we already have SimChannels for in scCol
853  // remake this map on each cryostat as channels ought not to be shared between
854  // cryostats, just between TPC's
855 
856  std::map<unsigned int, unsigned int> channelToscCol;
857 
858  unsigned int ntpcs = geom->Cryostat(geo::CryostatID(c)).NTPC();
859  for (unsigned int t = 0; t < ntpcs; ++t) {
860  std::string name("LArVoxelSD");
861  std::ostringstream sstr;
862  sstr << name << "_Cryostat" << c << "_TPC" << t;
863 
864  // try first to find the sensitive detector specific for this TPC;
865  // do not bother writing on screen if there is none (yet)
866  G4VSensitiveDetector* sd = sdManager->FindSensitiveDetector(sstr.str(), false);
867  // if there is none, catch the general one (called just "LArVoxelSD")
868  if (!sd) sd = sdManager->FindSensitiveDetector(name, false);
869  // If this didn't work, then a sensitive detector with
870  // the name "LArVoxelSD" does not exist.
871  if (!sd) {
872  throw cet::exception("LArG4")
873  << "Sensitive detector for cryostat " << c << " TPC " << t << " not found (neither '"
874  << sstr.str() << "' nor '" << name << "' exist)\n";
875  }
876 
877  // Convert the G4VSensitiveDetector* to a LArVoxelReadout*.
878  auto larVoxelReadout = dynamic_cast<LArVoxelReadout*>(sd);
879 
880  // If this didn't work, there is a "LArVoxelSD" detector, but
881  // it's not a LArVoxelReadout object.
882  if (!larVoxelReadout) {
883  throw cet::exception("LArG4")
884  << "Sensitive detector '" << sd->GetName() << "' is not a LArVoxelReadout object\n";
885  }
886 
887  LArVoxelReadout::ChannelMap_t& channels = larVoxelReadout->GetSimChannelMap(c, t);
888  if (!empty(channels)) {
889  MF_LOG_DEBUG("LArG4") << "now put " << channels.size() << " SimChannels from C=" << c
890  << " T=" << t << " into the event";
891  }
892 
893  for (auto ch_pair : channels) {
894  sim::SimChannel& sc = ch_pair.second;
895 
896  // push sc onto scCol but only if we haven't already put something in scCol for this channel.
897  // if we have, then merge the ionization deposits. Skip the check if we only have one TPC
898 
899  if (ntpcs > 1) {
900  unsigned int ichan = sc.Channel();
901  auto itertest = channelToscCol.find(ichan);
902  if (itertest == channelToscCol.end()) {
903  channelToscCol[ichan] = scCol->size();
904  scCol->emplace_back(std::move(sc));
905  }
906  else {
907  unsigned int idtest = itertest->second;
908  auto const& tdcideMap = sc.TDCIDEMap();
909  for (auto const& tdcide : tdcideMap) {
910  for (auto const& ide : tdcide.second) {
911  double xyz[3] = {ide.x, ide.y, ide.z};
912  scCol->at(idtest).AddIonizationElectrons(ide.trackID,
913  tdcide.first,
914  ide.numElectrons,
915  xyz,
916  ide.energy,
917  ide.origTrackID);
918  } // end loop to add ionization electrons to scCol->at(idtest)
919  } // end loop over tdc to vector<sim::IDE> map
920  } // end if check to see if we've put SimChannels in for ichan yet or not
921  }
922  else {
923  scCol->emplace_back(std::move(sc));
924  } // end of check if we only have one TPC (skips check for multiple simchannels if we have just one TPC)
925  } // end loop over simchannels for this TPC
926 
927  // mark it for clearing
928  ReadoutList.insert(const_cast<LArVoxelReadout*>(larVoxelReadout));
929 
930  } // end loop over tpcs
931  } // end loop over cryostats
932 
933  for (LArVoxelReadout* larVoxelReadout : ReadoutList) {
934  larVoxelReadout->ClearSimChannels();
935  }
936  } //endif electron prop
937 
938  // only put the sim::AuxDetSimChannels into the event once, not once for every
939  // MCTruth in the event
940 
941  adCol->reserve(geom->NAuxDets());
942  for (unsigned int a = 0; a < geom->NAuxDets(); ++a) {
943 
944  // there should always be at least one senstive volume because
945  // we make one for the full aux det if none are specified in the
946  // gdml file - see AuxDetGeo.cxx
947  for (size_t sv = 0; sv < geom->AuxDet(a).NSensitiveVolume(); ++sv) {
948 
949  // N.B. this name convention is used when creating the
950  // AuxDetReadout SD in AuxDetReadoutGeometry
951  std::stringstream name;
952  name << "AuxDetSD_AuxDet" << a << "_" << sv;
953  G4VSensitiveDetector* sd = sdManager->FindSensitiveDetector(name.str().c_str());
954  if (!sd) {
955  throw cet::exception("LArG4")
956  << "Sensitive detector '" << name.str() << "' does not exist\n";
957  }
958 
959  // Convert the G4VSensitiveDetector* to a AuxDetReadout*.
960  larg4::AuxDetReadout* auxDetReadout = dynamic_cast<larg4::AuxDetReadout*>(sd);
961 
962  MF_LOG_DEBUG("LArG4") << "now put the AuxDetSimTracks in the event";
963 
964  const sim::AuxDetSimChannel adsc = auxDetReadout->GetAuxDetSimChannel();
965  adCol->push_back(adsc);
966  auxDetReadout->clear();
967  }
968  } // Loop over AuxDets
969 
970  if (partCol) {
971  mf::LogInfo("LArG4") << "Geant4 simulated " << nGeneratedParticles
972  << " MC particles, we keep " << partCol->size() << " .";
973  }
974 
975  if (fdumpSimChannels) {
976  mf::LogVerbatim("DumpSimChannels")
977  << "Event " << evt.id() << ": " << scCol->size() << " channels with signal";
978  unsigned int nChannels = 0;
979  for (const sim::SimChannel& sc : *scCol) {
980  mf::LogVerbatim out("DumpSimChannels");
981  out << " #" << nChannels << ": ";
982  // dump indenting with " ", but not on the first line
983  sc.Dump(out, " ");
984  ++nChannels;
985  } // for
986  } // if dump SimChannels
987 
988  if (!lgp->NoElectronPropagation()) evt.put(std::move(scCol));
989 
990  evt.put(std::move(adCol));
991  if (partCol) evt.put(std::move(partCol));
992  if (droppedPartCol) {
993  std::cout << "LArG4 dropped particles length = " << droppedPartCol->size() << std::endl;
994  evt.put(std::move(droppedPartCol));
995  }
996  if (tpassn) evt.put(std::move(tpassn));
997  if (!lgp->NoPhotonPropagation()) {
998  if (!fUseLitePhotons) {
999  evt.put(std::move(PhotonCol));
1000  if (fStoreReflected) evt.put(std::move(PhotonColRefl), "Reflected");
1001  }
1002  else {
1003  evt.put(std::move(LitePhotonCol));
1004  evt.put(std::move(cOpDetBacktrackerRecordCol));
1005  if (fStoreReflected) {
1006  evt.put(std::move(LitePhotonColRefl), "Reflected");
1007  evt.put(std::move(cOpDetBacktrackerRecordColRefl), "Reflected");
1008  }
1009  }
1010  }
1011 
1012  if (lgp->FillSimEnergyDeposits()) {
1013  evt.put(std::move(edepCol_TPCActive), "TPCActive");
1014  evt.put(std::move(edepCol_Other), "Other");
1015  }
1016  return;
1017  } // LArG4::produce()
std::vector< std::string > fInputLabels
std::unique_ptr< g4b::G4Helper > fG4Help
G4 interface object.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< sim::OpDetBacktrackerRecord > YieldReflectedOpDetBacktrackerRecords()
bool fStoreDroppedMCParticles
Whether to keep a sim::MCParticleLite list of dropped particles.
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:136
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
int Mother() const
Definition: MCParticle.h:214
void Dump(Stream &&out, std::string indent, std::string first_indent) const
Dumps the full content of the SimChannel into a stream.
Definition: SimChannel.h:332
bool fMakeMCParticles
Whether to keep a sim::MCParticle list.
int StatusCode() const
Definition: MCParticle.h:212
std::unordered_map< std::string, std::vector< sim::SimEnergyDeposit > > YieldSimEnergyDeposits()
Yields the map of energy deposits by volume name, and resets the internal one.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Definition: GeometryCore.h:430
CryostatGeo const & Cryostat(CryostatID const &cryoid=cryostat_zero) const
Returns the specified cryostat.
int TrackId() const
Definition: MCParticle.h:211
std::map< int, int > DetectedPhotons
Number of photons detected at each given time: time tick -> photons.
Definition: SimPhotons.h:109
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: Event.h:77
bool fSparsifyTrajectories
Sparsify MCParticle Trajectories.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
Collection of particles crossing one auxiliary detector cell.
bool fdumpSimChannels
Whether each event&#39;s sim::Channel will be displayed.
std::vector< sim::SimPhotons > & GetPhotons(bool Reflected=false)
larg4::ParticleListAction * fparticleListAction
Geant4 user action to particle information.
sim::ParticleList && YieldList()
std::map< unsigned int, sim::SimChannel > ChannelMap_t
Type of map channel -> sim::SimChannel.
static bool isDropped(simb::MCParticle const *p)
returns whether the specified particle has been marked as dropped
Provenance const * provenance() const
Definition: Handle.h:217
virtual void clear()
void DumpMCTruth(Stream &&out, simb::MCTruth const &truth, unsigned int pointsPerLine, std::string indent, std::string firstIndent)
Dumps the content of the specified MC truth in the output stream.
Definition: MCDumpers.h:338
int OpChannel
Optical detector channel associated to this data.
Definition: SimPhotons.h:106
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:175
size_t NSensitiveVolume() const
Definition: AuxDetGeo.h:144
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).
bool fdumpParticleList
Whether each event&#39;s sim::ParticleList will be displayed.
AuxDetGeo const & AuxDet(unsigned int const ad=0) const
Returns the specified auxiliary detector.
unsigned int NOpDets() const
Number of OpDets in the whole detector.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
raw::ChannelID_t Channel() const
Returns the readout channel this object describes.
Definition: SimChannel.h:323
static OpDetPhotonTable * Instance(bool LitePhotons=false)
Compact representation of photons on a channel.
Definition: SimPhotons.h:98
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
bool fUseLitePhotons
std::vector< sim::OpDetBacktrackerRecord > YieldOpDetBacktrackerRecords()
Float_t sc
Definition: plot.C:23
Contains information about a generated particle.
#define MF_LOG_DEBUG(id)
TDCIDEs_t const & TDCIDEMap() const
Returns all the deposited energy information as stored.
Definition: SimChannel.h:319
bool fStoreReflected
std::map< int, std::map< int, int > > GetLitePhotons(bool Reflected=false)
void SparsifyTrajectory(double margin=0.1, bool keep_second_to_last=false)
Definition: MCParticle.h:266
size_type size() const
Definition: ParticleList.h:313
void ClearTable(size_t nch=0)
EventID id() const
Definition: Event.cc:23
sim::AuxDetSimChannel const GetAuxDetSimChannel() const
Definition: AuxDetReadout.h:70
void DumpMCParticle(Stream &&out, simb::MCParticle const &particle, std::string indent, std::string firstIndent)
Dumps the content of the specified particle in the output stream.
Definition: MCDumpers.h:226
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
LArVoxelReadoutGeometry * fVoxelReadoutGeometry
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.
The data type to uniquely identify a cryostat.
Definition: geo_types.h:192
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
void art::Modifier::registerProducts ( ProductDescriptions productsToRegister)
inherited

Definition at line 16 of file Modifier.cc.

References art::ModuleBase::moduleDescription(), and art::ProductRegistryHelper::registerProducts().

17  {
18  ProductRegistryHelper::registerProducts(productsToRegister,
20  }
void registerProducts(ProductDescriptions &productsToRegister, ModuleDescription const &md)
ModuleDescription const & moduleDescription() const
Definition: ModuleBase.cc:13
void art::ModuleBase::setModuleDescription ( ModuleDescription const &  md)
inherited

Definition at line 31 of file ModuleBase.cc.

References art::ModuleBase::md_.

32  {
33  md_ = md;
34  }
std::optional< ModuleDescription > md_
Definition: ModuleBase.h:55
void art::ModuleBase::sortConsumables ( std::string const &  current_process_name)
inherited

Definition at line 49 of file ModuleBase.cc.

References art::ModuleBase::collector_, and art::ConsumesCollector::sortConsumables().

50  {
51  // Now that we know we have seen all the consumes declarations,
52  // sort the results for fast lookup later.
53  collector_.sortConsumables(current_process_name);
54  }
ConsumesCollector collector_
Definition: ModuleBase.h:56
void sortConsumables(std::string const &current_process_name)

Member Data Documentation

AllPhysicsLists larg4::LArG4::fAllPhysicsLists
private

Definition at line 355 of file LArG4_module.cc.

Referenced by LArG4().

bool larg4::LArG4::fCheckOverlaps
private

Whether to use the G4 overlap checker.

Definition at line 334 of file LArG4_module.cc.

Referenced by beginJob(), and LArG4().

detinfo::DetectorPropertiesData larg4::LArG4::fDetProp
private

Must outlive fAllPhysicsLists!

Definition at line 354 of file LArG4_module.cc.

Referenced by LArG4().

bool larg4::LArG4::fdumpParticleList
private

Whether each event's sim::ParticleList will be displayed.

Definition at line 338 of file LArG4_module.cc.

Referenced by LArG4(), and produce().

bool larg4::LArG4::fdumpSimChannels
private

Whether each event's sim::Channel will be displayed.

Definition at line 339 of file LArG4_module.cc.

Referenced by LArG4(), and produce().

CLHEP::HepRandomEngine& larg4::LArG4::fEngine
private

Random-number engine for IonizationAndScintillation initialization

Definition at line 351 of file LArG4_module.cc.

Referenced by beginJob(), and LArG4().

std::unique_ptr<g4b::G4Helper> larg4::LArG4::fG4Help {nullptr}
private

G4 interface object.

Definition at line 327 of file LArG4_module.cc.

Referenced by beginJob(), and produce().

std::string larg4::LArG4::fG4MacroPath
private

directory path for Geant4 macro file to be executed before main MC processing.

Definition at line 332 of file LArG4_module.cc.

Referenced by beginJob(), and LArG4().

std::string larg4::LArG4::fG4PhysListName
private

predefined physics list to use if not making a custom one

Definition at line 331 of file LArG4_module.cc.

Referenced by beginJob(), and LArG4().

std::vector<std::string> larg4::LArG4::fInputLabels
private

Definition at line 345 of file LArG4_module.cc.

Referenced by LArG4(), and produce().

std::vector<std::string> larg4::LArG4::fKeepParticlesInVolumes
private

Only write particles that have trajectories through these volumes.

Definition at line 347 of file LArG4_module.cc.

Referenced by beginRun(), and LArG4().

bool larg4::LArG4::fMakeMCParticles
private

Whether to keep a sim::MCParticle list.

Definition at line 335 of file LArG4_module.cc.

Referenced by beginJob(), LArG4(), and produce().

double larg4::LArG4::fOffPlaneMargin = 0.
private

Off-plane charge recovery margin dictate how tracks are put on stack.

Definition at line 343 of file LArG4_module.cc.

Referenced by beginJob(), and LArG4().

larg4::ParticleListAction* larg4::LArG4::fparticleListAction
private
Initial value:
{
nullptr}

Geant4 user action to particle information.

Definition at line 328 of file LArG4_module.cc.

Referenced by beginJob(), beginRun(), and produce().

int larg4::LArG4::fSmartStacking
private

Whether to instantiate and use class to.

Definition at line 342 of file LArG4_module.cc.

Referenced by beginJob(), and LArG4().

bool larg4::LArG4::fSparsifyTrajectories
private

Sparsify MCParticle Trajectories.

Definition at line 349 of file LArG4_module.cc.

Referenced by LArG4(), and produce().

bool larg4::LArG4::fStoreDroppedMCParticles
private

Whether to keep a sim::MCParticleLite list of dropped particles.

Definition at line 337 of file LArG4_module.cc.

Referenced by beginJob(), LArG4(), and produce().

bool larg4::LArG4::fStoreReflected {false}
private

Definition at line 341 of file LArG4_module.cc.

Referenced by LArG4(), and produce().

bool larg4::LArG4::fUseLitePhotons
private

Definition at line 340 of file LArG4_module.cc.

Referenced by beginJob(), LArG4(), and produce().

LArVoxelReadoutGeometry* larg4::LArG4::fVoxelReadoutGeometry
private
Initial value:
{
nullptr}

Definition at line 356 of file LArG4_module.cc.

Referenced by beginJob(), and produce().


The documentation for this class was generated from the following file: