32 #include "nug4/G4Base/PrimaryParticleInformation.h" 33 #include "nug4/ParticleNavigation/ParticleList.h" 42 #include "cetlib_except/exception.h" 44 #include "Geant4/G4DynamicParticle.hh" 45 #include "Geant4/G4Event.hh" 46 #include "Geant4/G4ParticleDefinition.hh" 47 #include "Geant4/G4PrimaryParticle.hh" 48 #include "Geant4/G4Step.hh" 49 #include "Geant4/G4StepPoint.hh" 50 #include "Geant4/G4String.hh" 51 #include "Geant4/G4ThreeVector.hh" 52 #include "Geant4/G4Track.hh" 53 #include "Geant4/G4VProcess.hh" 54 #include "Geant4/G4VUserPrimaryParticleInformation.hh" 56 #include "TLorentzVector.h" 58 #include "range/v3/view.hpp" 69 : artg4tk::EventActionBase(
"PLASEventActionBase")
70 , artg4tk::TrackingActionBase(
"PLASTrackingActionBase")
71 , artg4tk::SteppingActionBase(
"PLASSteppingActionBase")
72 , fenergyCut(p.
get<double>(
"EnergyCut", 0.0 *
CLHEP::
GeV))
73 , fstoreTrajectories(p.
get<
bool>(
"storeTrajectories", true))
103 std::stringstream sstored;
104 sstored <<
"The full tracking information will not be stored for particles" 105 <<
" resulting from the following processes: \n{ ";
107 sstored <<
"\"" << i <<
"\" ";
110 mf::LogInfo(
"ParticleListActionService") << sstored.str() <<
"}\n";
114 <<
"Storing full tracking information for all processes. \n";
118 <<
"NotStoredPhysics provided, but will be ignored." 119 <<
" To use NotStoredPhysics, set keepEMShowerDaughters to false";
126 <<
"Trajectory sparsification enabled with SparsifyMargin : " <<
fSparsifyMargin <<
"\n";
152 mf::LogDebug(
"beginOfEventAction::Generator") <<
"Trajectory points will not be stored.";
154 else if (!customKeepTraj) {
156 <<
"keepGenTrajectories list is empty. Will" 157 <<
" store trajectory points for all generators";
163 for (
size_t mcti = 0; mcti <
fMCLists->size(); ++mcti) {
165 std::stringstream sskeepgen;
166 sskeepgen <<
"MCTruth object summary :";
167 sskeepgen <<
"\n\tPrimary MCTIndex : " << mcti;
170 auto const& mclistHandle = (*fMCLists)[mcti];
171 generator_name = mclistHandle.provenance()->inputTag().label();
172 sskeepgen <<
"\n\tProvenance/Generator : " << generator_name;
174 G4bool keepGen =
false;
177 if (!customKeepTraj) {
183 if (generator_name == keepableGen) {
192 sskeepgen <<
"\n\tTrajectory points storable : " << (keepGen ?
"true" :
"false") <<
"\n";
193 mf::LogDebug(
"beginOfEventAction::Generator") << sskeepgen.str();
198 <<
"storeTrajectories" 199 <<
" set to true and a non-empty keepGenTrajectories list provided in configuration file, " 201 <<
" none of the generators in this list are present in the event! Double check list or " 203 <<
" provide keepGenTrajectories in the configuration to keep all trajectories from all" 204 <<
" generator labels. This may be expected for generators that have a nonzero probability " 206 <<
" producing no particles (e.g. some radiologicals)";
227 parentid = (*itr).second;
240 G4ParticleDefinition* particleDefinition = track->GetDefinition();
241 G4int pdgCode = particleDefinition->GetPDGEncoding();
255 bool isFromMCTProcessPrimary =
false;
259 const G4DynamicParticle* dynamicParticle = track->GetDynamicParticle();
260 const G4PrimaryParticle* primaryParticle = dynamicParticle->GetPrimaryParticle();
262 size_t primarymctIndex = 0;
263 if (primaryParticle !=
nullptr) {
264 const G4VUserPrimaryParticleInformation* gppi = primaryParticle->GetUserInformation();
265 const g4b::PrimaryParticleInformation* ppi =
266 dynamic_cast<const g4b::PrimaryParticleInformation*
>(gppi);
267 if (ppi !=
nullptr) {
268 primaryIndex = ppi->MCParticleIndex();
269 primarymctIndex = ppi->MCTruthIndex();
271 mct_primary_process = ppi->GetMCParticle()->Process();
285 if (mct_primary_process.compare(
"primary") == 0) {
286 process_name =
"primary";
287 isFromMCTProcessPrimary =
true;
289 else if (mct_primary_process.find(
"primary") == 0) {
290 process_name = mct_primary_process;
291 isFromMCTProcessPrimary =
false;
292 mf::LogDebug(
"PrimaryParticle") <<
"MCTruth primary process name contains \"primary\" " 293 <<
" but is not solely \"primary\" : " << process_name
294 <<
".\nWill not store full set of trajectory points.";
297 process_name =
"primary";
298 isFromMCTProcessPrimary =
true;
300 <<
"MCTruth primary process does not beging with string" 301 <<
" literal \"primary\" : " << process_name <<
"\nOVERRIDING it to \"primary\"";
320 process_name = track->GetCreatorProcess()->GetProcessName();
322 bool notstore =
false;
324 if (process_name.find(
p) != std::string::npos) {
326 mf::LogDebug(
"NotStoredPhysics") <<
"Found process : " << process_name;
362 G4double
energy = track->GetKineticEnergy();
388 <<
"can't find parent id: " << parentID <<
" in the particle list, or fParentIDMap." 389 <<
" Make " << parentID <<
" the mother ID for" 390 <<
" track ID " <<
fCurrentTrackID <<
" in the hope that it will aid debugging.";
399 primarymctIndex = it->second;
403 <<
"Could not locate MCT Index for parent trackID of " << parentID;
411 double mass = dynamicParticle->GetMass() /
CLHEP::GeV;
431 (isFromMCTProcessPrimary) ?
436 const G4ThreeVector& polarization = track->GetPolarization();
438 TVector3{polarization.x(), polarization.y(), polarization.z()});
454 const G4StepPoint* postStepPoint = aTrack->GetStep()->GetPostStepPoint();
455 if (!postStepPoint->GetProcessDefinedStep()) {
470 G4String
process = postStepPoint->GetProcessDefinedStep()->GetProcessName();
478 const G4ThreeVector
position = postStepPoint->GetPosition();
479 G4double
time = postStepPoint->GetGlobalTime();
482 TLorentzVector fourPos(position.x() /
CLHEP::cm,
487 const G4ThreeVector
momentum = postStepPoint->GetMomentum();
488 const G4double
energy = postStepPoint->GetTotalEnergy();
489 TLorentzVector fourMom(momentum.x() /
CLHEP::GeV,
524 double const globalTime = step->GetTrack()->GetGlobalTime();
525 double const velocity_G4 = step->GetTrack()->GetVelocity();
526 double const velocity_step = step->GetStepLength() / step->GetDeltaTime();
527 if ((step->GetTrack()->GetDefinition()->GetPDGEncoding() == 0) &&
528 fabs(velocity_G4 - velocity_step) > 0.0001) {
531 step->GetPostStepPoint()->SetGlobalTime(globalTime - step->GetDeltaTime() +
543 const G4StepPoint* preStepPoint = step->GetPreStepPoint();
545 const G4ThreeVector
position = preStepPoint->GetPosition();
546 G4double
time = preStepPoint->GetGlobalTime();
549 TLorentzVector fourPos(position.x() /
CLHEP::cm,
554 const G4ThreeVector
momentum = preStepPoint->GetMomentum();
555 const G4double
energy = preStepPoint->GetTotalEnergy();
556 TLorentzVector fourMom(momentum.x() /
CLHEP::GeV,
571 G4String
process = step->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName();
572 G4bool ignoreProcess = process.contains(
"LArVoxel") || process.contains(
"OpDetReadout");
591 const G4StepPoint* postStepPoint = step->GetPostStepPoint();
593 const G4ThreeVector
position = postStepPoint->GetPosition();
594 G4double
time = postStepPoint->GetGlobalTime();
597 TLorentzVector fourPos(position.x() /
CLHEP::cm,
602 const G4ThreeVector
momentum = postStepPoint->GetMomentum();
603 const G4double
energy = postStepPoint->GetTotalEnergy();
604 TLorentzVector fourMom(momentum.x() /
CLHEP::GeV,
621 operator()(sim::ParticleList::value_type& particleListEntry)
const 624 int particleID = particleListEntry.first;
629 int parentID = particleList->GetMotherOf(particleID);
632 if (parentID <= 0)
return;
640 if (parentEntry == particleList->end()) {
648 if (!parentEntry->second)
return;
677 if ((*pn).first > highestID) highestID = (*pn).first;
683 <<
"highestID = " << highestID <<
"\nfTrackIDOffset= " <<
fTrackIDOffset;
692 TLorentzVector
const& mom,
706 std::stringstream sscounter;
707 sscounter <<
"Not Stored Process summary:";
711 mf::LogInfo(
"ParticleListActionService") << sscounter.str();
714 partCol_ = std::make_unique<std::vector<simb::MCParticle>>();
716 std::make_unique<art::Assns<simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo>>();
727 unsigned int nGeneratedParticles = 0;
728 unsigned int nMCTruths = 0;
729 sim::ParticleList particleList =
YieldList();
731 for (
size_t mcl = 0; mcl <
fMCLists->size(); ++mcl) {
732 auto const& mclistHandle = (*fMCLists)[mcl];
733 MF_LOG_INFO(
"endOfEventAction") <<
"mclistHandle Size: " << mclistHandle->size();
735 for (
size_t m = 0;
m < mclistHandle->size(); ++
m) {
742 if (gen_index != nMCTruths)
continue;
743 assert(
p->NumberTrajectoryPoints() != 0ull);
745 ++nGeneratedParticles;
747 if (!truthInfo.hasGeneratedParticleIndex() &&
p->Mother() == 0) {
748 MF_LOG_WARNING(
"endOfEventAction") <<
"No GeneratedParticleIndex()!";
751 <<
"Failed to match primary particle:\n" 752 <<
"\nwith particles from the truth record '" << mclistHandle.provenance()->inputTag()
758 tpassn_->addSingle(mct, mcp_ptr, truthInfo);
760 mf::LogDebug(
"Offset") <<
"nGeneratedParticles = " << nGeneratedParticles;
static constexpr double cm
unsigned int NumberTrajectoryPoints() const
simb::MCParticle * particle
simple structure representing particle
void AddDaughter(const int trackID)
void userSteppingAction(const G4Step *) override
ParticleListActionService(fhicl::ParameterSet const &)
void beginOfEventAction(const G4Event *) override
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
void preUserTrackingAction(const G4Track *) override
sim::ParticleList && YieldList()
bool fKeepEMShowerDaughters
whether to keep EM shower secondaries, tertiaries, etc
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
bool fKeepSecondToLast
tell whether or not to force keeping the second to last point
bool keepFullTrajectory
if there was decision to keep
std::unique_ptr< art::Assns< simb::MCTruth, simb::MCParticle, sim::GeneratedParticleInfo > > tpassn_
int GetParentage(int trackid) const
double fSparsifyMargin
set the sparsification margin
void AddPointToCurrentParticle(TLorentzVector const &pos, TLorentzVector const &mom, std::string const &process)
Adds a trajectory point to the current particle, and runs the filter.
void postUserTrackingAction(const G4Track *) override
simb::GeneratedParticleIndex_t GetPrimaryTruthIndex(int trackId) const
Returns the index of primary truth (sim::NoGeneratorIndex if none).
bool fKeepTransportation
tell whether or not to keep the transportation process
std::unique_ptr< std::vector< simb::MCParticle > > partCol_
std::map< int, size_t > fMCTIndexMap
Map: particle track ID -> index of primary parent in std::vector<simb::MCTruth> object.
constexpr GeneratedParticleIndex_t NoGeneratedParticleIndex
Constant representing the absence of generator truth information.
bool fSparsifyTrajectories
help reduce the number of trajectory points.
void SetPolarization(const TVector3 &p)
static constexpr double GeV
static const int NoParticleId
Use Geant4's user "hooks" to maintain a list of particles generated by Geant4.
std::map< size_t, std::pair< std::string, G4bool > > fMCTIndexToGeneratorMap
Map: MCTruthIndex -> generator, input label of generator and keepGenerator decision.
std::unordered_map< std::string, int > fNotStoredCounterUMap
Map: not stored process and counter.
void endOfEventAction(const G4Event *) override
#define MF_LOG_INFO(category)
bool isPrimary() const
Returns whether there is a particle.
void SetWeight(double wt)
void SetEndProcess(std::string s)
std::vector< std::string > fNotStoredPhysics
Physics processes that will not be stored.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
#define DEFINE_ART_SERVICE(svc)
std::map< int, int > fParentIDMap
key is current track ID, value is parent ID
simb::GeneratedParticleIndex_t truthInfoIndex() const
Returns the index of the particle in the generator truth record.
art::EDProductGetter const * productGetter_
Contains data associated to particles from detector simulation.
void clear()
Resets the information (does not release memory it does not own)
std::vector< std::string > fkeepGenTrajectories
std::map< int, bool > fMCTPrimProcessKeepMap
Map: particle trakc ID -> boolean decision to keep or not full trajectory points. ...
simb::GeneratedParticleIndex_t truthIndex
Index of the particle in the original generator truth record.
sim::ParticleList fParticleList
bool hasParticle() const
Returns whether there is a particle.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
Contains information about a generated particle.
G4bool fstoreTrajectories
Whether to store particle trajectories with each particle.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
bool fkeepOnlyPrimaryFullTraj
std::map< int, simb::GeneratedParticleIndex_t > fPrimaryTruthMap
Map: particle track ID -> index of primary information in MC truth.
ParticleInfo_t fCurrentParticle
Tools and modules for checking out the basics of the Monte Carlo.
auto const & get(AssnsNode< L, R, D > const &r)
#define MF_LOG_WARNING(category)
def momentum(x1, x2, x3, scale=1.)
second_as<> second
Type of time stored in seconds, in double precision.
void SparsifyTrajectory(double margin=0.1, bool keep_second_to_last=false)
std::vector< art::Handle< std::vector< simb::MCTruth > > > const * fMCLists
MCTruthCollection input lists.
def parent(G, child, parent_type)
std::size_t GeneratedParticleIndex_t
Type of particle index in the generator truth record (simb::MCTruth).