22 #define LARG4_LARG4_H 1 48 #include "cetlib_except/exception.h" 49 #include "cetlib/search_path.h" 85 #include "Geant4/G4RunManager.hh" 86 #include "Geant4/G4UImanager.hh" 87 #include "Geant4/G4VUserDetectorConstruction.hh" 88 #include "Geant4/G4VUserPrimaryGeneratorAction.hh" 89 #include "Geant4/G4VUserPhysicsList.hh" 90 #include "Geant4/G4UserRunAction.hh" 91 #include "Geant4/G4UserEventAction.hh" 92 #include "Geant4/G4UserTrackingAction.hh" 93 #include "Geant4/G4UserSteppingAction.hh" 94 #include "Geant4/G4UserStackingAction.hh" 95 #include "Geant4/G4VisExecutive.hh" 96 #include "Geant4/G4VUserPhysicsList.hh" 97 #include "Geant4/G4SDManager.hh" 98 #include "Geant4/G4LogicalVolumeStore.hh" 99 #include "Geant4/Randomize.hh" 100 #include "Geant4/G4SDManager.hh" 101 #include "Geant4/G4VSensitiveDetector.hh" 102 #include "Geant4/globals.hh" 105 #include "TGeoManager.h" 114 class G4VisExecutive;
116 #if defined __clang__ 117 #pragma clang diagnostic push 118 #pragma clang diagnostic ignored "-Wunused-private-field" 125 class LArVoxelListAction;
126 class ParticleListAction;
334 (std::set<std::string>
const& vol_names)
const;
361 if (pset.has_key(
"Seed")) {
363 <<
"The configuration of LArG4 module has the discontinued 'Seed' parameter.\n" 364 "Seeds are now controlled by two parameters: 'GEANTSeed' and 'PropagationSeed'.";
371 ->
createEngine(*
this,
"G4Engine",
"GEANT", pset,
"GEANTSeed");
374 ->
createEngine(*
this,
"HepJamesRandom",
"propagation", pset,
"PropagationSeed");
378 bool useInputLabels = pset.get_if_present< std::vector<std::string> >(
"InputLabels",
fInputLabels);
397 produces< std::vector<sim::SimPhotons> >();
399 produces< std::vector<sim::SimPhotons> >(
"Reflected");
403 produces< std::vector<sim::SimPhotonsLite> >();
404 produces< std::vector<sim::OpDetBacktrackerRecord> >();
406 produces< std::vector<sim::SimPhotonsLite> >(
"Reflected");
407 produces< std::vector<sim::OpDetBacktrackerRecord> >(
"Reflected");
413 produces < std::vector<sim::SimEnergyDeposit> >(
"TPCActive");
414 produces < std::vector<sim::SimEnergyDeposit> >(
"Other");
417 produces< std::vector<simb::MCParticle> >();
419 produces< std::vector<sim::AuxDetSimChannel> >();
420 produces< art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo> >();
423 cet::search_path sp(
"FW_SEARCH_PATH");
425 sp.find_file(pset.get< std::string >(
"GeantCommandFile"),
fG4MacroPath);
458 std::vector<G4VUserParallelWorld*> pworlds;
470 readoutGeomSetupData.readoutSetup.propGen
471 = &(
rng->getEngine(
"propagation"));
473 (
"LArVoxelReadoutGeometry", readoutGeomSetupData)
535 (std::set<std::string>
const& vol_names)
const 539 if (vol_names.empty())
return {};
543 std::vector<std::vector<TGeoNode const*>> node_paths
544 = geom.FindAllVolumePaths(vol_names);
548 GeoVolumePairs.reserve(node_paths.size());
552 for (
size_t iVolume = 0; iVolume < node_paths.size(); ++iVolume) {
553 std::vector<TGeoNode const*> path = node_paths[iVolume];
555 TGeoTranslation* pTransl =
new TGeoTranslation(0.,0.,0.);
556 TGeoRotation* pRot =
new TGeoRotation();
557 for (TGeoNode
const* node: path) {
558 TGeoTranslation thistranslate(*node->GetMatrix());
559 TGeoRotation thisrotate(*node->GetMatrix());
560 pTransl->Add(&thistranslate);
561 *pRot=*pRot * thisrotate;
566 TGeoTranslation* pTransl2 =
new TGeoTranslation(pTransl->GetTranslation()[0],
567 pTransl->GetTranslation()[1],
568 pTransl->GetTranslation()[2]);
569 double phi=0.,theta=0.,psi=0.;
570 pRot->GetAngles(phi,theta,psi);
571 TGeoRotation* pRot2 =
new TGeoRotation();
572 pRot2->SetAngles(phi,theta,psi);
574 TGeoCombiTrans* pTransf =
new TGeoCombiTrans(*pTransl2,*pRot2);
576 GeoVolumePairs.emplace_back(node_paths[iVolume].back()->GetVolume(), pTransf);
580 return std::make_unique<util::PositionInVolumeFilter>(std::move(GeoVolumePairs));
590 std::unique_ptr< std::vector<sim::SimChannel> > scCol (
new std::vector<sim::SimChannel>);
591 std::unique_ptr< std::vector< sim::AuxDetSimChannel > > adCol (
new std::vector<sim::AuxDetSimChannel> );
592 auto tpassn = std::make_unique<art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo>>();
593 std::unique_ptr< std::vector<simb::MCParticle> > partCol (
new std::vector<simb::MCParticle >);
594 std::unique_ptr< std::vector<sim::SimPhotons> > PhotonCol (
new std::vector<sim::SimPhotons>);
595 std::unique_ptr< std::vector<sim::SimPhotons> > PhotonColRefl (
new std::vector<sim::SimPhotons>);
596 std::unique_ptr< std::vector<sim::SimPhotonsLite> > LitePhotonCol (
new std::vector<sim::SimPhotonsLite>);
597 std::unique_ptr< std::vector<sim::SimPhotonsLite> > LitePhotonColRefl (
new std::vector<sim::SimPhotonsLite>);
598 std::unique_ptr< std::vector< sim::OpDetBacktrackerRecord > > cOpDetBacktrackerRecordCol (
new std::vector<sim::OpDetBacktrackerRecord>);
599 std::unique_ptr< std::vector< sim::OpDetBacktrackerRecord > > cOpDetBacktrackerRecordColRefl (
new std::vector<sim::OpDetBacktrackerRecord>);
605 std::unique_ptr< std::vector<sim::SimEnergyDeposit> > edepCol_TPCActive (
new std::vector<sim::SimEnergyDeposit>);
606 std::unique_ptr< std::vector<sim::SimEnergyDeposit> > edepCol_Other (
new std::vector<sim::SimEnergyDeposit>);
622 std::vector< art::Handle< std::vector<simb::MCTruth> > > mclists;
631 unsigned int nGeneratedParticles = 0;
634 for(
size_t mcl = 0; mcl < mclists.size(); ++mcl){
638 for(
size_t m = 0; m < mclistHandle->size(); ++m){
649 for(
auto const& partPair: particleList) {
651 ++nGeneratedParticles;
661 if (!truthInfo.hasGeneratedParticleIndex() && (p.
Mother() == 0)) {
664 error <<
"Failed to match primary particle:\n";
666 error <<
"\nwith particles from the truth record '" 667 << mclistHandle.
provenance()->inputTag() <<
"':\n";
675 partCol->push_back(std::move(p));
677 tpassn->addSingle(mct, makeMCPartPtr(partCol->size() - 1), truthInfo);
684 mf::LogInfo(
"LArG4") <<
"Dump sim::ParticleList; size()=" 685 << particleList.size() <<
"\n" 695 G4SDManager* sdManager = G4SDManager::GetSDMpointer();
706 for (
int Reflected = 0; Reflected <= 1; Reflected++) {
711 LOG_DEBUG(
"Optical") <<
"Storing OpDet Hit Collection in Event";
713 if (Reflected) PhotonColRefl->reserve(ThePhotons.size());
714 else PhotonCol->reserve(ThePhotons.size());
715 for(
auto& it : ThePhotons) {
716 if (Reflected) PhotonColRefl->push_back(std::move(it));
717 else PhotonCol->push_back(std::move(it));
721 LOG_DEBUG(
"Optical") <<
"Storing OpDet Hit Collection in Event";
725 if(ThePhotons.size() > 0){
726 LitePhotonCol->reserve(ThePhotons.size());
727 for(
auto const& it : ThePhotons){
731 if (Reflected) LitePhotonColRefl->push_back(ph);
732 else LitePhotonCol->push_back(ph);
746 for(
auto const& edepCol : edepMap){
747 if(boost::contains(edepCol.first,
"TPCActive"))
748 edepCol_TPCActive->insert(edepCol_TPCActive->end(),
749 edepCol.second.begin(),edepCol.second.end());
751 edepCol_Other->insert(edepCol_Other->end(),
752 edepCol.second.begin(),edepCol.second.end());
764 std::set<LArVoxelReadout*> ReadoutList;
766 for(
unsigned int c = 0; c < geom->
Ncryostats(); ++c){
772 std::map<unsigned int, unsigned int> channelToscCol;
775 for(
unsigned int t = 0; t < ntpcs; ++t){
776 std::string name(
"LArVoxelSD");
777 std::ostringstream sstr;
778 sstr << name <<
"_Cryostat" << c <<
"_TPC" << t;
782 G4VSensitiveDetector* sd
783 = sdManager->FindSensitiveDetector(sstr.str(),
false);
785 if (!sd) sd = sdManager->FindSensitiveDetector(name,
false);
789 throw cet::exception(
"LArG4") <<
"Sensitive detector for cryostat " 790 << c <<
" TPC " << t <<
" not found (neither '" 791 << sstr.str() <<
"' nor '" << name <<
"' exist)\n";
799 if ( !larVoxelReadout ){
802 <<
"' is not a LArVoxelReadout object\n";
806 if (!channels.empty()) {
807 LOG_DEBUG(
"LArG4") <<
"now put " << channels.size() <<
" SimChannels" 808 " from C=" << c <<
" T=" << t <<
" into the event";
811 for(
auto ch_pair: channels){
818 unsigned int ichan = sc.
Channel();
820 if (itertest == channelToscCol.end()) {
821 channelToscCol[ichan] = scCol->size();
822 scCol->emplace_back(std::move(sc));
825 unsigned int idtest = itertest->second;
827 for(
auto const& tdcide : tdcideMap){
828 for(
auto const& ide : tdcide.second){
829 double xyz[3] = {ide.x, ide.y, ide.z};
830 scCol->at(idtest).AddIonizationElectrons(ide.trackID,
840 scCol->emplace_back(std::move(sc));
846 ReadoutList.insert(const_cast<LArVoxelReadout*>(larVoxelReadout));
852 larVoxelReadout->ClearSimChannels();
860 for(
unsigned int a = 0; a < geom->
NAuxDets(); ++a){
869 std::stringstream name;
870 name <<
"AuxDetSD_AuxDet" << a <<
"_" << sv;
871 G4VSensitiveDetector* sd = sdManager->FindSensitiveDetector(name.str().c_str());
875 <<
"' does not exist\n";
881 LOG_DEBUG(
"LArG4") <<
"now put the AuxDetSimTracks in the event";
884 adCol->push_back(adsc);
885 auxDetReadout->
clear();
891 <<
"Geant4 simulated " << nGeneratedParticles <<
" MC particles, we keep " 892 << partCol->size() <<
" .";
896 <<
"Event " << evt.
id()
897 <<
": " << scCol->size() <<
" channels with signal";
898 unsigned int nChannels = 0;
901 out <<
" #" << nChannels <<
": ";
910 evt.
put(std::move(adCol));
911 evt.
put(std::move(partCol));
914 evt.
put(std::move(PhotonCol));
916 evt.
put(std::move(PhotonColRefl),
"Reflected");
919 evt.
put(std::move(LitePhotonCol));
920 evt.
put(std::move(cOpDetBacktrackerRecordCol));
922 evt.
put(std::move(LitePhotonColRefl),
"Reflected");
923 evt.
put(std::move(cOpDetBacktrackerRecordColRefl),
"Reflected");
927 evt.
put(std::move(tpassn));
930 evt.
put(std::move(edepCol_TPCActive),
"TPCActive");
931 evt.
put(std::move(edepCol_Other),
"Other");
943 #if defined __clang__ 944 #pragma clang diagnostic pop 947 #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
std::vector< sim::OpDetBacktrackerRecord > YieldReflectedOpDetBacktrackerRecords()
bool KeepEMShowerDaughters() const
void SparsifyTrajectory()
void produce(art::Event &evt)
Energy deposited on a readout channel by simulated tracks.
Stores material properties and sends them to GEANT4 geometry.
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.
std::vector< VolumeInfo_t > AllVolumeInfo_t
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.
bool StoreReflected() const
std::string GDMLFile() const
Returns the full directory path to the GDML file source.
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 ...
std::vector< sim::SimPhotons > & GetPhotons(bool Reflected=false)
Use Geant4's user "hooks" to maintain a list of particles generated by Geant4.
base_engine_t & createEngine(seed_t seed)
std::unordered_map< std::string, std::vector< sim::SimEnergyDeposit > > const & GetSimEnergyDeposits() const
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.
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
void ParticleFilter(std::unique_ptr< util::PositionInVolumeFilter > &&filter)
Grabs a particle filter.
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 ...
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)
std::unique_ptr< util::PositionInVolumeFilter > CreateParticleVolumeFilter(std::set< std::string > const &vol_names) const
Configures and returns 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.
std::map< int, std::map< int, int > > GetLitePhotons(bool Reflected=false)
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.