22 #define LARG4_LARG4_H 1 48 #include "cetlib_except/exception.h" 49 #include "cetlib/search_path.h" 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" 104 #include "TGeoManager.h" 113 class G4VisExecutive;
115 #if defined __clang__ 116 #pragma clang diagnostic push 117 #pragma clang diagnostic ignored "-Wunused-private-field" 124 class LArVoxelListAction;
125 class ParticleListAction;
332 (std::set<std::string>
const& vol_names)
const;
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'.";
369 ->
createEngine(*
this,
"G4Engine",
"GEANT", pset,
"GEANTSeed");
372 ->
createEngine(*
this,
"HepJamesRandom",
"propagation", pset,
"PropagationSeed");
376 bool useInputLabels = pset.get_if_present< std::vector<std::string> >(
"InputLabels",
fInputLabels);
385 produces< std::vector<sim::SimPhotonsLite> >();
386 produces< std::vector<sim::OpDetBacktrackerRecord> >();
391 produces < std::vector<sim::SimEnergyDeposit> >(
"TPCActive");
392 produces < std::vector<sim::SimEnergyDeposit> >(
"Other");
395 produces< std::vector<simb::MCParticle> >();
397 produces< std::vector<sim::AuxDetSimChannel> >();
398 produces< art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo> >();
401 cet::search_path sp(
"FW_SEARCH_PATH");
403 sp.find_file(pset.get< std::string >(
"GeantCommandFile"),
fG4MacroPath);
436 std::vector<G4VUserParallelWorld*> pworlds;
448 readoutGeomSetupData.readoutSetup.propGen
449 = &(
rng->getEngine(
"propagation"));
451 (
"LArVoxelReadoutGeometry", readoutGeomSetupData)
513 (std::set<std::string>
const& vol_names)
const 517 if (vol_names.empty())
return {};
521 std::vector<std::vector<TGeoNode const*>> node_paths
522 = geom.FindAllVolumePaths(vol_names);
526 GeoVolumePairs.reserve(node_paths.size());
530 for (
size_t iVolume = 0; iVolume < node_paths.size(); ++iVolume) {
531 std::vector<TGeoNode const*> path = node_paths[iVolume];
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;
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);
552 TGeoCombiTrans* pTransf =
new TGeoCombiTrans(*pTransl2,*pRot2);
554 GeoVolumePairs.emplace_back(node_paths[iVolume].back()->GetVolume(), pTransf);
558 return std::make_unique<PositionInVolumeFilter>(std::move(GeoVolumePairs));
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>);
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>);
596 std::vector< art::Handle< std::vector<simb::MCTruth> > > mclists;
605 unsigned int nGeneratedParticles = 0;
608 for(
size_t mcl = 0; mcl < mclists.size(); ++mcl){
612 for(
size_t m = 0; m < mclistHandle->size(); ++m){
623 for(
auto const& partPair: particleList) {
625 ++nGeneratedParticles;
635 if (!truthInfo.hasGeneratedParticleIndex() && (p.
Mother() == 0)) {
638 error <<
"Failed to match primary particle:\n";
640 error <<
"\nwith particles from the truth record '" 641 << mclistHandle.
provenance()->inputTag() <<
"':\n";
649 partCol->push_back(std::move(p));
651 tpassn->addSingle(mct, makeMCPartPtr(partCol->size() - 1), truthInfo);
658 mf::LogInfo(
"LArG4") <<
"Dump sim::ParticleList; size()=" 659 << particleList.size() <<
"\n" 669 G4SDManager* sdManager = G4SDManager::GetSDMpointer();
681 LOG_DEBUG(
"Optical") <<
"Storing OpDet Hit Collection in Event";
683 PhotonCol->reserve(ThePhotons.size());
684 for(
auto& it : ThePhotons)
685 PhotonCol->push_back(std::move(it));
688 LOG_DEBUG(
"Optical") <<
"Storing OpDet Hit Collection in Event";
692 if(ThePhotons.size() > 0){
693 LitePhotonCol->reserve(ThePhotons.size());
694 for(
auto const& it : ThePhotons){
698 LitePhotonCol->push_back(ph);
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());
713 edepCol_Other->insert(edepCol_Other->end(),
714 edepCol.second.begin(),edepCol.second.end());
726 std::set<LArVoxelReadout*> ReadoutList;
728 for(
unsigned int c = 0; c < geom->
Ncryostats(); ++c){
734 std::map<unsigned int, unsigned int> channelToscCol;
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;
744 G4VSensitiveDetector* sd
745 = sdManager->FindSensitiveDetector(sstr.str(),
false);
747 if (!sd) sd = sdManager->FindSensitiveDetector(name,
false);
751 throw cet::exception(
"LArG4") <<
"Sensitive detector for cryostat " 752 << c <<
" TPC " << t <<
" not found (neither '" 753 << sstr.str() <<
"' nor '" << name <<
"' exist)\n";
761 if ( !larVoxelReadout ){
764 <<
"' is not a LArVoxelReadout object\n";
768 if (!channels.empty()) {
769 LOG_DEBUG(
"LArG4") <<
"now put " << channels.size() <<
" SimChannels" 770 " from C=" << c <<
" T=" << t <<
" into the event";
773 for(
auto ch_pair: channels){
780 unsigned int ichan = sc.
Channel();
782 if (itertest == channelToscCol.end()) {
783 channelToscCol[ichan] = scCol->size();
784 scCol->emplace_back(std::move(sc));
787 unsigned int idtest = itertest->second;
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,
802 scCol->emplace_back(std::move(sc));
808 ReadoutList.insert(const_cast<LArVoxelReadout*>(larVoxelReadout));
814 larVoxelReadout->ClearSimChannels();
822 for(
unsigned int a = 0; a < geom->
NAuxDets(); ++a){
831 std::stringstream name;
832 name <<
"AuxDetSD_AuxDet" << a <<
"_" << sv;
833 G4VSensitiveDetector* sd = sdManager->FindSensitiveDetector(name.str().c_str());
837 <<
"' does not exist\n";
843 LOG_DEBUG(
"LArG4") <<
"now put the AuxDetSimTracks in the event";
846 adCol->push_back(adsc);
847 auxDetReadout->
clear();
853 <<
"Geant4 simulated " << nGeneratedParticles <<
" MC particles, we keep " 854 << partCol->size() <<
" .";
858 <<
"Event " << evt.
id()
859 <<
": " << scCol->size() <<
" channels with signal";
860 unsigned int nChannels = 0;
863 out <<
" #" << nChannels <<
": ";
872 evt.
put(std::move(adCol));
873 evt.
put(std::move(partCol));
877 evt.
put(std::move(LitePhotonCol));
878 evt.
put(std::move(cOpDetBacktrackerRecordCol));
881 evt.
put(std::move(tpassn));
884 evt.
put(std::move(edepCol_TPCActive),
"TPCActive");
885 evt.
put(std::move(edepCol_Other),
"Other");
897 #if defined __clang__ 898 #pragma clang diagnostic pop 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()
std::vector< VolumeInfo_t > AllVolumeInfo_t
void produce(art::Event &evt)
Energy deposited on a readout channel by simulated tracks.
Stores material properties and sends them to GEANT4 geometry.
std::vector< sim::SimPhotons > & GetPhotons()
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
bool G4Run(std::vector< const simb::MCTruth * > &primaries)
std::string OpDetGeoName(unsigned int c=0) const
Returns gdml string which gives sensitive opdet name.
void SetUserAction()
Initialization for the Geant4 Monte Carlo.
void ConstructDetector(std::string const &gdmlFile)
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)
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()
bool StoreTrajectories() const
std::map< int, int > DetectedPhotons
void InitPhysics()
Initialization for the Geant4 Monte Carlo.
Define the "parallel" geometry that's seen by the LAr Voxels.
bool fSparsifyTrajectories
Sparsify MCParticle Trajectories.
ProductID put(std::unique_ptr< PROD > &&product)
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.
bool fdumpSimChannels
Whether each event's sim::Channel will be displayed.
larg4::ParticleListAction * fparticleListAction
Geant4 user action to particle information.
contains objects relating to OpDet hits
sim::ParticleList && YieldList()
void ResetTrackIDOffset()
std::map< unsigned int, sim::SimChannel > ChannelMap_t
Type of map channel -> sim::SimChannel.
void SetOverlapCheck(bool check)
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Use Geant4'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)
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
LArG4(fhicl::ParameterSet const &pset)
Standard constructor and destructor for an FMWK module.
std::unordered_map< std::string, std::vector< sim::SimEnergyDeposit > > & GetSimEnergyDeposits()
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.
bool FillSimEnergyDeposits() const
static IonizationAndScintillation * CreateInstance(CLHEP::HepRandomEngine &engine)
void getManyByType(std::vector< Handle< PROD >> &results) const
unsigned int NTPC() const
Number of TPCs in this cryostat.
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
Convert MCTruth to G4Event; Geant4 event generator.
size_t NSensitiveVolume() const
GeneratedParticleIndex_t GetPrimaryTruthIndex(int trackId) const
Returns the index of primary truth (sim::NoGeneratorIndex if none).
bool fdumpParticleList
Whether each event'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
double ParticleKineticEnergyCut() const
raw::ChannelID_t Channel() const
Returns the readout channel this object describes.
static OpDetPhotonTable * Instance(bool LitePhotons=false)
A Geant4 sensitive detector that accumulates voxel information.
Define the "parallel" geometry that's seen by the AuxDet.
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
double offPlaneMargin
Margin for charge recovery (see LArVoxelReadout).
void beginRun(art::Run &run)
void ParticleFilter(std::unique_ptr< PositionInVolumeFilter > &&filter)
Grabs a particle filter.
static UserActionManager * Instance()
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
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
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.
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.
sim::AuxDetSimChannel const GetAuxDetSimChannel() const
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.
cet::coded_exception< error, detail::translate > exception
bool UseLitePhotons() const
void ClearEnergyDeposits()
unsigned int NAuxDets() const
Returns the number of auxiliary detectors.