LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
LArG4_module.cc
Go to the documentation of this file.
1 
20 
21 #ifndef LARG4_LARG4_H
22 #define LARG4_LARG4_H 1
23 
26 
27 // C++ Includes
28 #include <sstream> // std::ostringstream
29 #include <vector> // std::ostringstream
30 #include <map> // std::ostringstream
31 #include <set> // std::ostringstream
32 #include <iostream>
33 #include <sys/stat.h>
34 
35 // Framework includes
39 #include "fhiclcpp/ParameterSet.h"
48 #include "cetlib_except/exception.h"
49 #include "cetlib/search_path.h"
50 
51 // art extensions
53 
54 // LArSoft Includes
68 #include "larsim/LArG4/ParticleFilters.h" // larg4::PositionInVolumeFilter
69 #include "larsim/MCDumpers/MCDumpers.h" // sim::dump namespace
82 
83 // G4 Includes
84 #include "Geant4/G4RunManager.hh"
85 #include "Geant4/G4UImanager.hh"
86 #include "Geant4/G4VUserDetectorConstruction.hh"
87 #include "Geant4/G4VUserPrimaryGeneratorAction.hh"
88 #include "Geant4/G4VUserPhysicsList.hh"
89 #include "Geant4/G4UserRunAction.hh"
90 #include "Geant4/G4UserEventAction.hh"
91 #include "Geant4/G4UserTrackingAction.hh"
92 #include "Geant4/G4UserSteppingAction.hh"
93 #include "Geant4/G4UserStackingAction.hh"
94 #include "Geant4/G4VisExecutive.hh"
95 #include "Geant4/G4VUserPhysicsList.hh"
96 #include "Geant4/G4SDManager.hh"
97 #include "Geant4/G4LogicalVolumeStore.hh"
98 #include "Geant4/Randomize.hh"
99 #include "Geant4/G4SDManager.hh"
100 #include "Geant4/G4VSensitiveDetector.hh"
101 #include "Geant4/globals.hh"
102 
103 // ROOT Includes
104 #include "TGeoManager.h"
105 
106 //For energy depositions
108 
109 
110 // Forward declarations
111 class G4RunManager;
112 class G4UImanager;
113 class G4VisExecutive;
114 
115 #if defined __clang__
116  #pragma clang diagnostic push
117  #pragma clang diagnostic ignored "-Wunused-private-field"
118 #endif
119 
121 namespace larg4 {
122 
123  // Forward declarations within namespace.
124  class LArVoxelListAction;
125  class ParticleListAction;
126 
296  class LArG4 : public art::EDProducer{
297  public:
298 
300  explicit LArG4(fhicl::ParameterSet const& pset);
301  virtual ~LArG4();
302 
306  void produce (art::Event& evt);
307  void beginJob();
308  void beginRun(art::Run& run);
309 
310  private:
312  larg4::LArVoxelListAction* flarVoxelListAction;
314 
315  std::string fG4PhysListName;
316  std::string fG4MacroPath;
317  bool fCheckOverlaps;
323  double fOffPlaneMargin = 0.;
324  std::vector<std::string> fInputLabels;
326  std::vector<std::string> fKeepParticlesInVolumes;
327 
329 
331  std::unique_ptr<PositionInVolumeFilter> CreateParticleVolumeFilter
332  (std::set<std::string> const& vol_names) const;
333 
334  };
335 
336 } // namespace LArG4
337 
338 namespace larg4 {
339 
340  //----------------------------------------------------------------------
341  // Constructor
343  : fG4Help (0)
344  , flarVoxelListAction (0)
345  , fparticleListAction (0)
346  , fG4PhysListName (pset.get< std::string >("G4PhysListName","larg4::PhysicsList"))
347  , fCheckOverlaps (pset.get< bool >("CheckOverlaps",false) )
348  , fdumpParticleList (pset.get< bool >("DumpParticleList",false) )
349  , fdumpSimChannels (pset.get< bool >("DumpSimChannels", false) )
350  , fSmartStacking (pset.get< int >("SmartStacking",0) )
351  , fOffPlaneMargin (pset.get< double >("ChargeRecoveryMargin",0.0) )
352  , fKeepParticlesInVolumes (pset.get< std::vector< std::string > >("KeepParticlesInVolumes",{}))
353  , fSparsifyTrajectories (pset.get< bool >("SparsifyTrajectories",false) )
354 
355  {
356  LOG_DEBUG("LArG4") << "Debug: LArG4()";
358 
359  if (pset.has_key("Seed")) {
361  << "The configuration of LArG4 module has the discontinued 'Seed' parameter.\n"
362  "Seeds are now controlled by two parameters: 'GEANTSeed' and 'PropagationSeed'.";
363  }
364  // setup the random number service for Geant4, the "G4Engine" label is a
365  // special tag setting up a global engine for use by Geant4/CLHEP;
366  // obtain the random seed from NuRandomService,
367  // unless overridden in configuration with key "Seed" or "GEANTSeed"
369  ->createEngine(*this, "G4Engine", "GEANT", pset, "GEANTSeed");
370  // same thing for the propagation engine:
372  ->createEngine(*this, "HepJamesRandom", "propagation", pset, "PropagationSeed");
373 
374  //get a list of generators to use, otherwise, we'll end up looking for anything that's
375  //made an MCTruth object
376  bool useInputLabels = pset.get_if_present< std::vector<std::string> >("InputLabels",fInputLabels);
377  if(!useInputLabels) fInputLabels.resize(0);
378 
380 
382  if(!lgp->NoPhotonPropagation()){
383  if(!fUseLitePhotons) produces< std::vector<sim::SimPhotons> >();
384  else{
385  produces< std::vector<sim::SimPhotonsLite> >();
386  produces< std::vector<sim::OpDetBacktrackerRecord> >();
387  }
388  }
389 
390  if(lgp->FillSimEnergyDeposits()){
391  produces < std::vector<sim::SimEnergyDeposit> >("TPCActive");
392  produces < std::vector<sim::SimEnergyDeposit> >("Other");
393  }
394 
395  produces< std::vector<simb::MCParticle> >();
396  if(!lgp->NoElectronPropagation()) produces< std::vector<sim::SimChannel> >();
397  produces< std::vector<sim::AuxDetSimChannel> >();
398  produces< art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo> >();
399 
400  // constructor decides if initialized value is a path or an environment variable
401  cet::search_path sp("FW_SEARCH_PATH");
402 
403  sp.find_file(pset.get< std::string >("GeantCommandFile"), fG4MacroPath);
404  struct stat sb;
405  if (fG4MacroPath.empty() || stat(fG4MacroPath.c_str(), &sb)!=0)
406  // failed to resolve the file name
407  throw cet::exception("NoG4Macro") << "G4 macro file "
408  << fG4MacroPath
409  << " not found!\n";
410 
411  }
412 
413  //----------------------------------------------------------------------
414  // Destructor
416  {
417  if(fG4Help) delete fG4Help;
418  }
419 
420  //----------------------------------------------------------------------
422  {
425 
429 
430  // Get the logical volume store and assign material properties
433  MPL->UpdateGeometry(G4LogicalVolumeStore::GetInstance());
434 
435  // Tell the detector about the parallel LAr voxel geometry.
436  std::vector<G4VUserParallelWorld*> pworlds;
437  // Intialize G4 physics and primary generator action
438  fG4Help->InitPhysics();
439 
440  // create the ionization and scintillation calculator;
441  // this is a singleton (!) so it does not make sense
442  // to create it in LArVoxelReadoutGeometry
443  IonizationAndScintillation::CreateInstance(rng->getEngine("propagation"));
444 
445  // make a parallel world for each TPC in the detector
446  LArVoxelReadoutGeometry::Setup_t readoutGeomSetupData;
447  readoutGeomSetupData.readoutSetup.offPlaneMargin = fOffPlaneMargin;
448  readoutGeomSetupData.readoutSetup.propGen
449  = &(rng->getEngine("propagation"));
450  pworlds.push_back(new LArVoxelReadoutGeometry
451  ("LArVoxelReadoutGeometry", readoutGeomSetupData)
452  );
453  pworlds.push_back( new OpDetReadoutGeometry( geom->OpDetGeoName() ));
454  pworlds.push_back( new AuxDetReadoutGeometry("AuxDetReadoutGeometry") );
455 
456  fG4Help->SetParallelWorlds(pworlds);
457 
458  // moved up
459  // Intialize G4 physics and primary generator action
460  fG4Help->InitPhysics();
461 
462  // Use the UserActionManager to handle all the Geant4 user hooks.
464 
465  // User-action class for accumulating LAr voxels.
467 
468  // UserAction for getting past a bug in v4.9.4.p02 of Geant4.
469  // This action will not be used once the bug has been fixed
470  // The techniques used in this UserAction are not to be repeated
471  // as in general they are a very bad idea, ie they take a const
472  // pointer and jump through hoops to change it
473  // 08-Apr-2014 WGS: It appears that with the shift to Geant 4.9.6 or
474  // above, there's no longer any need for the "Bad Idea Action" fix.
475  // larg4::G4BadIdeaAction *bia = new larg4::G4BadIdeaAction(fSmartStacking);
476  // uaManager->AddAndAdoptAction(bia);
477 
478  // remove IonizationAndScintillationAction for now as we are ensuring
479  // the Reset for each G4Step within the G4SensitiveVolumes
480  //larg4::IonizationAndScintillationAction *iasa = new larg4::IonizationAndScintillationAction();
481  //uaManager->AddAndAdoptAction(iasa);
482 
483  // User-action class for accumulating particles and trajectories
484  // produced in the detector.
486  lgp->StoreTrajectories(),
487  lgp->KeepEMShowerDaughters());
489 
490  // UserActionManager is now configured so continue G4 initialization
492 
493  // With an enormous detector with lots of rock ala LAr34 (nee LAr20)
494  // we need to be smarter about stacking.
495  if (fSmartStacking>0){
496  G4UserStackingAction* stacking_action = new LArStackingAction(fSmartStacking);
497  fG4Help->GetRunManager()->SetUserAction(stacking_action);
498  }
499 
500 
501 
502  }
503 
505  // prepare the filter object (null if no filtering)
506 
507  std::set<std::string> volnameset(fKeepParticlesInVolumes.begin(), fKeepParticlesInVolumes.end());
509 
510  }
511 
512  std::unique_ptr<PositionInVolumeFilter> LArG4::CreateParticleVolumeFilter
513  (std::set<std::string> const& vol_names) const
514  {
515 
516  // if we don't have favourite volumes, don't even bother creating a filter
517  if (vol_names.empty()) return {};
518 
519  auto const& geom = *art::ServiceHandle<geo::Geometry>();
520 
521  std::vector<std::vector<TGeoNode const*>> node_paths
522  = geom.FindAllVolumePaths(vol_names);
523 
524  // collection of interesting volumes
526  GeoVolumePairs.reserve(node_paths.size()); // because we are obsessed
527 
528  //for each interesting volume, follow the node path and collect
529  //total rotations and translations
530  for (size_t iVolume = 0; iVolume < node_paths.size(); ++iVolume) {
531  std::vector<TGeoNode const*> path = node_paths[iVolume];
532 
533  TGeoTranslation* pTransl = new TGeoTranslation(0.,0.,0.);
534  TGeoRotation* pRot = new TGeoRotation();
535  for (TGeoNode const* node: path) {
536  TGeoTranslation thistranslate(*node->GetMatrix());
537  TGeoRotation thisrotate(*node->GetMatrix());
538  pTransl->Add(&thistranslate);
539  *pRot=*pRot * thisrotate;
540  }
541 
542  //for some reason, pRot and pTransl don't have tr and rot bits set correctly
543  //make new translations and rotations so bits are set correctly
544  TGeoTranslation* pTransl2 = new TGeoTranslation(pTransl->GetTranslation()[0],
545  pTransl->GetTranslation()[1],
546  pTransl->GetTranslation()[2]);
547  double phi=0.,theta=0.,psi=0.;
548  pRot->GetAngles(phi,theta,psi);
549  TGeoRotation* pRot2 = new TGeoRotation();
550  pRot2->SetAngles(phi,theta,psi);
551 
552  TGeoCombiTrans* pTransf = new TGeoCombiTrans(*pTransl2,*pRot2);
553 
554  GeoVolumePairs.emplace_back(node_paths[iVolume].back()->GetVolume(), pTransf);
555 
556  }
557 
558  return std::make_unique<PositionInVolumeFilter>(std::move(GeoVolumePairs));
559 
560  } // CreateParticleVolumeFilter()
561 
562 
564  {
565  LOG_DEBUG("LArG4") << "produce()";
566 
567  // loop over the lists and put the particles and voxels into the event as collections
568  std::unique_ptr< std::vector<sim::SimChannel> > scCol (new std::vector<sim::SimChannel>);
569  std::unique_ptr< std::vector< sim::AuxDetSimChannel > > adCol (new std::vector<sim::AuxDetSimChannel> );
570  auto tpassn = std::make_unique<art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo>>();
571  std::unique_ptr< std::vector<simb::MCParticle> > partCol (new std::vector<simb::MCParticle >);
572  std::unique_ptr< std::vector<sim::SimPhotons> > PhotonCol (new std::vector<sim::SimPhotons>);
573  std::unique_ptr< std::vector<sim::SimPhotonsLite> > LitePhotonCol (new std::vector<sim::SimPhotonsLite>);
574  std::unique_ptr< std::vector< sim::OpDetBacktrackerRecord > > cOpDetBacktrackerRecordCol (new std::vector<sim::OpDetBacktrackerRecord>);
575 
576  art::PtrMaker<simb::MCParticle> makeMCPartPtr(evt, *this);
577 
578  //for energy deposits
579  std::unique_ptr< std::vector<sim::SimEnergyDeposit> > edepCol_TPCActive (new std::vector<sim::SimEnergyDeposit>);
580  std::unique_ptr< std::vector<sim::SimEnergyDeposit> > edepCol_Other (new std::vector<sim::SimEnergyDeposit>);
581 
582  // Fetch the lists of LAr voxels and particles.
585 
586  // Clear the detected photon table
588  if(lgp->FillSimEnergyDeposits())
590 
591  // reset the track ID offset as we have a new collection of interactions
593 
594  //look to see if there is any MCTruth information for this
595  //event
596  std::vector< art::Handle< std::vector<simb::MCTruth> > > mclists;
597  if(fInputLabels.size()==0)
598  evt.getManyByType(mclists);
599  else{
600  mclists.resize(fInputLabels.size());
601  for(size_t i=0; i<fInputLabels.size(); i++)
602  evt.getByLabel(fInputLabels[i],mclists[i]);
603  }
604 
605  unsigned int nGeneratedParticles = 0;
606 
607  // Need to process Geant4 simulation for each interaction separately.
608  for(size_t mcl = 0; mcl < mclists.size(); ++mcl){
609 
610  art::Handle< std::vector<simb::MCTruth> > mclistHandle = mclists[mcl];
611 
612  for(size_t m = 0; m < mclistHandle->size(); ++m){
613  art::Ptr<simb::MCTruth> mct(mclistHandle, m);
614 
615  LOG_DEBUG("LArG4") << *(mct.get());
616 
617  // The following tells Geant4 to track the particles in this interaction.
618  fG4Help->G4Run(mct);
619 
620  // receive the particle list
622 
623  for(auto const& partPair: particleList) {
624  simb::MCParticle& p = *(partPair.second);
625  ++nGeneratedParticles;
626 
627  // if the particle has been marked as dropped, we don't save it
628  // (as of LArSoft ~v5.6 this does not ever happen because
629  // ParticleListAction has already taken care of deleting them)
630  if (ParticleListAction::isDropped(&p)) continue;
631 
632  sim::GeneratedParticleInfo const truthInfo{
634  };
635  if (!truthInfo.hasGeneratedParticleIndex() && (p.Mother() == 0)) {
636  // this means it's primary but with no information; logic error!!
638  error << "Failed to match primary particle:\n";
639  sim::dump::DumpMCParticle(error, p, " ");
640  error << "\nwith particles from the truth record '"
641  << mclistHandle.provenance()->inputTag() << "':\n";
642  sim::dump::DumpMCTruth(error, *mct, 2U, " "); // 2 points per line
643  error << "\n";
644  throw error;
645  }
646 
648 
649  partCol->push_back(std::move(p));
650 
651  tpassn->addSingle(mct, makeMCPartPtr(partCol->size() - 1), truthInfo);
652 
653  } // for(particleList)
654 
655 
656  // Has the user request a detailed dump of the output objects?
657  if (fdumpParticleList){
658  mf::LogInfo("LArG4") << "Dump sim::ParticleList; size()="
659  << particleList.size() << "\n"
660  << particleList;
661  }
662 
663  }
664 
665  }// end loop over interactions
666 
667  // get the electrons from the LArVoxelReadout sensitive detector
668  // Get the sensitive-detector manager.
669  G4SDManager* sdManager = G4SDManager::GetSDMpointer();
670 
671  // Find the sensitive detector with the name "LArVoxelSD".
672  OpDetSensitiveDetector *theOpDetDet = dynamic_cast<OpDetSensitiveDetector*>(sdManager->FindSensitiveDetector("OpDetSensitiveDetector"));
673 
674  // Store the contents of the detected photon table
675  //
676  if(theOpDetDet){
677 
678  if(!lgp->NoPhotonPropagation()){
679 
680  if(!fUseLitePhotons){
681  LOG_DEBUG("Optical") << "Storing OpDet Hit Collection in Event";
682  std::vector<sim::SimPhotons>& ThePhotons = OpDetPhotonTable::Instance()->GetPhotons();
683  PhotonCol->reserve(ThePhotons.size());
684  for(auto& it : ThePhotons)
685  PhotonCol->push_back(std::move(it));
686  }
687  else{
688  LOG_DEBUG("Optical") << "Storing OpDet Hit Collection in Event";
689 
690  std::map<int, std::map<int, int> > ThePhotons = OpDetPhotonTable::Instance()->GetLitePhotons();
691 
692  if(ThePhotons.size() > 0){
693  LitePhotonCol->reserve(ThePhotons.size());
694  for(auto const& it : ThePhotons){
696  ph.OpChannel = it.first;
697  ph.DetectedPhotons = it.second;
698  LitePhotonCol->push_back(ph);
699  }
700  }
701  *cOpDetBacktrackerRecordCol = OpDetPhotonTable::Instance()->YieldOpDetBacktrackerRecords();
702  }
703  }//end if no photon propagation
704 
705  if(lgp->FillSimEnergyDeposits())
706  {
707  auto const& edepMap = OpDetPhotonTable::Instance()->GetSimEnergyDeposits();
708  for(auto const& edepCol : edepMap){
709  if(boost::contains(edepCol.first,"TPCActive"))
710  edepCol_TPCActive->insert(edepCol_TPCActive->end(),
711  edepCol.second.begin(),edepCol.second.end());
712  else
713  edepCol_Other->insert(edepCol_Other->end(),
714  edepCol.second.begin(),edepCol.second.end());
715  }
716  }
717  }//end if theOpDetDet
718 
719 
720  if(!lgp->NoElectronPropagation())
721  {
722 
723  // only put the sim::SimChannels into the event once, not once for every
724  // MCTruth in the event
725 
726  std::set<LArVoxelReadout*> ReadoutList; // to be cleared later on
727 
728  for(unsigned int c = 0; c < geom->Ncryostats(); ++c){
729 
730  // map to keep track of which channels we already have SimChannels for in scCol
731  // remake this map on each cryostat as channels ought not to be shared between
732  // cryostats, just between TPC's
733 
734  std::map<unsigned int, unsigned int> channelToscCol;
735 
736  unsigned int ntpcs = geom->Cryostat(c).NTPC();
737  for(unsigned int t = 0; t < ntpcs; ++t){
738  std::string name("LArVoxelSD");
739  std::ostringstream sstr;
740  sstr << name << "_Cryostat" << c << "_TPC" << t;
741 
742  // try first to find the sensitive detector specific for this TPC;
743  // do not bother writing on screen if there is none (yet)
744  G4VSensitiveDetector* sd
745  = sdManager->FindSensitiveDetector(sstr.str(), false);
746  // if there is none, catch the general one (called just "LArVoxelSD")
747  if (!sd) sd = sdManager->FindSensitiveDetector(name, false);
748  // If this didn't work, then a sensitive detector with
749  // the name "LArVoxelSD" does not exist.
750  if ( !sd ){
751  throw cet::exception("LArG4") << "Sensitive detector for cryostat "
752  << c << " TPC " << t << " not found (neither '"
753  << sstr.str() << "' nor '" << name << "' exist)\n";
754  }
755 
756  // Convert the G4VSensitiveDetector* to a LArVoxelReadout*.
757  LArVoxelReadout* larVoxelReadout = dynamic_cast<LArVoxelReadout*>(sd);
758 
759  // If this didn't work, there is a "LArVoxelSD" detector, but
760  // it's not a LArVoxelReadout object.
761  if ( !larVoxelReadout ){
762  throw cet::exception("LArG4") << "Sensitive detector '"
763  << sd->GetName()
764  << "' is not a LArVoxelReadout object\n";
765  }
766 
767  LArVoxelReadout::ChannelMap_t& channels = larVoxelReadout->GetSimChannelMap(c, t);
768  if (!channels.empty()) {
769  LOG_DEBUG("LArG4") << "now put " << channels.size() << " SimChannels"
770  " from C=" << c << " T=" << t << " into the event";
771  }
772 
773  for(auto ch_pair: channels){
774  sim::SimChannel& sc = ch_pair.second;
775 
776  // push sc onto scCol but only if we haven't already put something in scCol for this channel.
777  // if we have, then merge the ionization deposits. Skip the check if we only have one TPC
778 
779  if (ntpcs > 1) {
780  unsigned int ichan = sc.Channel();
781  std::map<unsigned int, unsigned int>::iterator itertest = channelToscCol.find(ichan);
782  if (itertest == channelToscCol.end()) {
783  channelToscCol[ichan] = scCol->size();
784  scCol->emplace_back(std::move(sc));
785  }
786  else {
787  unsigned int idtest = itertest->second;
788  auto const& tdcideMap = sc.TDCIDEMap();
789  for(auto const& tdcide : tdcideMap){
790  for(auto const& ide : tdcide.second){
791  double xyz[3] = {ide.x, ide.y, ide.z};
792  scCol->at(idtest).AddIonizationElectrons(ide.trackID,
793  tdcide.first,
794  ide.numElectrons,
795  xyz,
796  ide.energy);
797  } // end loop to add ionization electrons to scCol->at(idtest)
798  }// end loop over tdc to vector<sim::IDE> map
799  } // end if check to see if we've put SimChannels in for ichan yet or not
800  }
801  else {
802  scCol->emplace_back(std::move(sc));
803  } // end of check if we only have one TPC (skips check for multiple simchannels if we have just one TPC)
804  } // end loop over simchannels for this TPC
805 
806 
807  // mark it for clearing
808  ReadoutList.insert(const_cast<LArVoxelReadout*>(larVoxelReadout));
809 
810  } // end loop over tpcs
811  }// end loop over cryostats
812 
813  for (LArVoxelReadout* larVoxelReadout: ReadoutList){
814  larVoxelReadout->ClearSimChannels();
815  }
816  }//endif electron prop
817 
818  // only put the sim::AuxDetSimChannels into the event once, not once for every
819  // MCTruth in the event
820 
821  adCol->reserve(geom->NAuxDets());
822  for(unsigned int a = 0; a < geom->NAuxDets(); ++a){
823 
824  // there should always be at least one senstive volume because
825  // we make one for the full aux det if none are specified in the
826  // gdml file - see AuxDetGeo.cxx
827  for(size_t sv = 0; sv < geom->AuxDet(a).NSensitiveVolume(); ++sv){
828 
829  // N.B. this name convention is used when creating the
830  // AuxDetReadout SD in AuxDetReadoutGeometry
831  std::stringstream name;
832  name << "AuxDetSD_AuxDet" << a << "_" << sv;
833  G4VSensitiveDetector* sd = sdManager->FindSensitiveDetector(name.str().c_str());
834  if ( !sd ){
835  throw cet::exception("LArG4") << "Sensitive detector '"
836  << name.str()
837  << "' does not exist\n";
838  }
839 
840  // Convert the G4VSensitiveDetector* to a AuxDetReadout*.
841  larg4::AuxDetReadout *auxDetReadout = dynamic_cast<larg4::AuxDetReadout*>(sd);
842 
843  LOG_DEBUG("LArG4") << "now put the AuxDetSimTracks in the event";
844 
845  const sim::AuxDetSimChannel adsc = auxDetReadout->GetAuxDetSimChannel();
846  adCol->push_back(adsc);
847  auxDetReadout->clear();
848  }
849 
850  } // Loop over AuxDets
851 
852  mf::LogInfo("LArG4")
853  << "Geant4 simulated " << nGeneratedParticles << " MC particles, we keep "
854  << partCol->size() << " .";
855 
856  if (fdumpSimChannels) {
857  mf::LogVerbatim("DumpSimChannels")
858  << "Event " << evt.id()
859  << ": " << scCol->size() << " channels with signal";
860  unsigned int nChannels = 0;
861  for (const sim::SimChannel& sc: *scCol) {
862  mf::LogVerbatim out("DumpSimChannels");
863  out << " #" << nChannels << ": ";
864  // dump indenting with " ", but not on the first line
865  sc.Dump(out, " ");
866  ++nChannels;
867  } // for
868  } // if dump SimChannels
869 
870  if(!lgp->NoElectronPropagation()) evt.put(std::move(scCol));
871 
872  evt.put(std::move(adCol));
873  evt.put(std::move(partCol));
874  if(!lgp->NoPhotonPropagation()){
875  if(!fUseLitePhotons) evt.put(std::move(PhotonCol));
876  else{
877  evt.put(std::move(LitePhotonCol));
878  evt.put(std::move(cOpDetBacktrackerRecordCol));
879  }
880  }
881  evt.put(std::move(tpassn));
882 
883  if(lgp->FillSimEnergyDeposits()){
884  evt.put(std::move(edepCol_TPCActive),"TPCActive");
885  evt.put(std::move(edepCol_Other),"Other");
886  }
887  return;
888  } // LArG4::produce()
889 
890 } // namespace LArG4
891 
892 namespace larg4 {
893 
895 
896 } // namespace LArG4
897 #if defined __clang__
898  #pragma clang diagnostic pop
899 #endif
900 
901 #endif // LARG4_LARG4_H
std::vector< std::string > fInputLabels
Build Geant4 geometry from GDML.
Store parameters for running LArG4.
Create the physics lists to be used by Geant4.
Collection of all it takes to set up this object.
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
bool KeepEMShowerDaughters() const
void SparsifyTrajectory()
Definition: MCParticle.h:268
std::vector< VolumeInfo_t > AllVolumeInfo_t
std::string fG4MacroPath
void produce(art::Event &evt)
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:143
Stores material properties and sends them to GEANT4 geometry.
intermediate_table::iterator iterator
std::vector< sim::SimPhotons > & GetPhotons()
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
bool G4Run(std::vector< const simb::MCTruth * > &primaries)
Definition: G4Helper.cxx:503
int Mother() const
Definition: MCParticle.h:217
std::string OpDetGeoName(unsigned int c=0) const
Returns gdml string which gives sensitive opdet name.
virtual ~LArG4()
void SetUserAction()
Initialization for the Geant4 Monte Carlo.
Definition: G4Helper.cxx:432
void ConstructDetector(std::string const &gdmlFile)
Definition: G4Helper.cxx:368
const ChannelMap_t & GetSimChannelMap() const
Returns the accumulated channel -> SimChannel map for the single TPC.
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
larg4::LArVoxelListAction * flarVoxelListAction
Geant4 user action to accumulate LAr voxel information.
void SetParallelWorlds(std::vector< G4VUserParallelWorld * > pworlds)
Definition: G4Helper.cxx:357
Geant4 interface.
STL namespace.
Contains data associated to particles from detector simulation.
larg4::LArVoxelReadout::Setup_t readoutSetup
Set up data for LArVoxelReadout.
Runs Geant4 simulation and propagation of electrons and photons to readout.
bool NoPhotonPropagation() const
Use Geant4 to run the LArSoft detector simulation.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
this UserAction derived class is to implement catches to known bugs in Geant4 that require grabbing c...
std::vector< std::string > fKeepParticlesInVolumes
Only write particles that have trajectories through these volumes.
G4RunManager * GetRunManager()
Definition: G4Helper.h:100
Definition: Run.h:30
bool StoreTrajectories() const
int TrackId() const
Definition: MCParticle.h:214
std::map< int, int > DetectedPhotons
Definition: SimPhotons.h:65
void InitPhysics()
Initialization for the Geant4 Monte Carlo.
Definition: G4Helper.cxx:407
Define the "parallel" geometry that&#39;s seen by the LAr Voxels.
bool fSparsifyTrajectories
Sparsify MCParticle Trajectories.
ProductID put(std::unique_ptr< PROD > &&product)
Definition: Event.h:102
int fSmartStacking
Whether to instantiate and use class to.
Collection of particles crossing one auxiliary detector cell.
std::string GDMLFile() const
Returns the full directory path to the GDML file source.
std::unique_ptr< PositionInVolumeFilter > CreateParticleVolumeFilter(std::set< std::string > const &vol_names) const
Configures and returns a particle filter.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
bool fdumpSimChannels
Whether each event&#39;s sim::Channel will be displayed.
larg4::ParticleListAction * fparticleListAction
Geant4 user action to particle information.
contains objects relating to OpDet hits
sim::ParticleList && YieldList()
std::map< unsigned int, sim::SimChannel > ChannelMap_t
Type of map channel -> sim::SimChannel.
void SetOverlapCheck(bool check)
Definition: G4Helper.h:128
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Use Geant4&#39;s user "hooks" to maintain a list of particles generated by Geant4.
base_engine_t & createEngine(seed_t seed)
bool NoElectronPropagation() const
Utility functions to print MC truth information.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:42
g4b::G4Helper * fG4Help
G4 interface object.
static bool isDropped(simb::MCParticle const *p)
returns whether the specified particle has been marked as dropped
static void AddAndAdoptAction(UserAction *a)
Provenance const * provenance() const
Definition: Handle.h:204
LArG4(fhicl::ParameterSet const &pset)
Standard constructor and destructor for an FMWK module.
std::unordered_map< std::string, std::vector< sim::SimEnergyDeposit > > & GetSimEnergyDeposits()
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:346
bool FillSimEnergyDeposits() const
static IonizationAndScintillation * CreateInstance(CLHEP::HepRandomEngine &engine)
void getManyByType(std::vector< Handle< PROD >> &results) const
Definition: DataViewImpl.h:446
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:155
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
Convert MCTruth to G4Event; Geant4 event generator.
size_t NSensitiveVolume() const
Definition: AuxDetGeo.h:160
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.
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
std::map< int, std::map< int, int > > GetLitePhotons()
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.
void UpdateGeometry(G4LogicalVolumeStore *lvs)
Updates the material properties with the collected values.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
double ParticleKineticEnergyCut() const
raw::ChannelID_t Channel() const
Returns the readout channel this object describes.
Definition: SimChannel.h:332
static OpDetPhotonTable * Instance(bool LitePhotons=false)
A Geant4 sensitive detector that accumulates voxel information.
Define the "parallel" geometry that&#39;s seen by the AuxDet.
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
double offPlaneMargin
Margin for charge recovery (see LArVoxelReadout).
void beginRun(art::Run &run)
T const * get() const
Definition: Ptr.h:321
void ParticleFilter(std::unique_ptr< PositionInVolumeFilter > &&filter)
Grabs a particle filter.
static UserActionManager * Instance()
bool fUseLitePhotons
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
std::vector< sim::OpDetBacktrackerRecord > YieldOpDetBacktrackerRecords()
Contains information about a generated particle.
contains information for a single step in the detector simulation
object containing MC truth information necessary for making RawDigits and doing back tracking ...
std::string fG4PhysListName
predefined physics list to use if not making a custom one
#define LOG_DEBUG(id)
bool fCheckOverlaps
Whether to use the G4 overlap checker.
Transports energy depositions from GEANT4 to TPC channels.
TDCIDEs_t const & TDCIDEMap() const
Returns all the deposited energy information as stored.
Definition: SimChannel.h:331
this UserAction derived class is to provide a hook during G4 stepping in which to call the code that ...
Defines classes to filter particles based on their trajectory.
void GetPropertiesFromServices()
Imports properties from LArSoft services.
Particle list in DetSim contains Monte Carlo particle information.
double fOffPlaneMargin
dictate how tracks are put on stack.
void ClearTable(size_t nch=0)
Tools and modules for checking out the basics of the Monte Carlo.
A Geant4 sensitive detector that accumulates information.
EventID id() const
Definition: Event.h:56
sim::AuxDetSimChannel const GetAuxDetSimChannel() const
Definition: AuxDetReadout.h:73
art framework interface to geometry description
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:228
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool UseLitePhotons() const
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.