14 #include "nusimdata/SimulationBase/MCTruth.h"
15 #include "nusimdata/SimulationBase/MCParticle.h"
18 #include "art/Framework/Core/EDAnalyzer.h"
19 #include "art/Framework/Core/ModuleMacros.h"
20 #include "art/Framework/Principal/Event.h"
21 #include "art/Framework/Principal/Handle.h"
22 #include "canvas/Persistency/Provenance/ProductID.h"
23 #include "canvas/Persistency/Common/FindOneP.h"
24 #include "canvas/Utilities/InputTag.h"
25 #include "fhiclcpp/types/Atom.h"
26 #include "fhiclcpp/types/OptionalAtom.h"
27 #include "messagefacility/MessageLogger/MessageLogger.h"
34 class DumpMCParticles;
38 using namespace fhicl;
43 using Comment = fhicl::Comment;
45 fhicl::Atom<art::InputTag> InputParticles {
46 Name(
"InputParticles"),
47 Comment(
"data product with the MC particles to be dumped")
50 fhicl::OptionalAtom<art::InputTag> ParticleTruthInfo {
51 Name(
"ParticleTruthInfo"),
53 (
"label of the association to MCTruth (default: as `InputParticles`)")
56 fhicl::Atom<std::string> OutputCategory {
57 Name(
"OutputCategory"),
58 Comment(
"name of the output stream (managed by the message facility)"),
62 fhicl::Atom<unsigned int> PointsPerLine {
63 Name(
"PointsPerLine"),
64 Comment(
"trajectory points printed per line (default: 2; 0 = skip them)"),
90 void analyze(art::Event
const& event)
override;
93 void endJob()
override;
115 template <
typename Stream>
117 Stream&& out, simb::MCParticle
const& particle,
119 std::string indent =
"",
bool bIndentFirst =
true
130 unsigned int fNEvents = 0U;
132 unsigned int fNMissingTruth = 0U;
134 unsigned int fNMissingTruthIndex = 0U;
146 class ProductNameCache {
149 ProductNameCache(art::Event
const& event): fEvent(event) {}
152 template <
typename T>
153 art::InputTag
const& operator[](art::Ptr<T>
const& ptr)
155 auto const iInfo = fNames.find(ptr.id());
156 return (iInfo == fNames.end())? fetch(ptr): iInfo->second;
160 art::Event
const& fEvent;
161 std::map<art::ProductID, art::InputTag> fNames;
163 template <
typename T>
164 art::InputTag fetchTag(art::Ptr<T>
const& ptr)
166 art::Handle<std::vector<T>> handle;
167 return fEvent.get(ptr.id(), handle)
168 ? handle.provenance()->inputTag()
173 template <
typename T>
174 art::InputTag
const& fetch(art::Ptr<T>
const& ptr)
176 art::InputTag
const tag = fetchTag(ptr);
177 return fNames.emplace(ptr.id(), tag).
first->second;
184 template <
typename Right,
typename Metadata,
typename Left>
185 std::unique_ptr<art::FindOneP<Right, Metadata>> makeFindOneP(
186 art::ValidHandle<std::vector<Left>>
const& handle,
187 art::Event
const& event,
188 art::InputTag
const& tag
191 art::Handle<art::Assns<Left, Right, Metadata>> assnsHandle;
192 if (!event.getByLabel(tag, assnsHandle))
return {};
194 return std::make_unique<art::FindOneP<Right, Metadata>>
195 (handle, event, tag);
208 , fInputParticles(config().InputParticles())
209 , fOutputCategory(config().OutputCategory())
210 , fPointsPerLine(config().PointsPerLine())
218 template <
typename Stream>
220 Stream&& out, simb::MCParticle
const& particle,
222 std::string indent ,
bool bIndentFirst
227 if (truthTag.label().empty()) out <<
"unknown truth record";
228 else out <<
"'" << truthTag.encode() <<
"'";
235 (std::forward<Stream>(out), particle, indent, bIndentFirst? indent:
"");
237 const unsigned int nPoints = particle.NumberTrajectoryPoints();
238 if ((nPoints > 0) && (fPointsPerLine > 0)) {
241 std::forward<Stream>(out), particle.Trajectory(),
242 fPointsPerLine, indent +
" "
254 ProductNameCache namesRegistry(event);
257 auto const& particleHandle
258 =
event.getValidHandle<std::vector<simb::MCParticle>>(fInputParticles);
259 auto const& Particles = *particleHandle;
264 auto particleToTruth = makeFindOneP<simb::MCTruth, sim::GeneratedParticleInfo>
265 (particleHandle, event, fParticleTruthInfo);
266 std::unique_ptr<art::FindOneP<simb::MCTruth>> particleToTruthLight;
267 if (!particleToTruth) {
268 ++fNMissingTruthIndex;
269 particleToTruthLight = makeFindOneP<simb::MCTruth, void>
270 (particleHandle, event, fParticleTruthInfo);
271 if (!particleToTruthLight) ++fNMissingTruth;
274 mf::LogVerbatim(fOutputCategory) <<
"Event " <<
event.id()
275 <<
": data product '" << fInputParticles.encode() <<
"' contains "
276 << Particles.size() <<
" MCParticle's";
278 unsigned int iParticle = 0;
279 for (simb::MCParticle
const& particle: Particles) {
282 mf::LogVerbatim log(fOutputCategory);
285 art::Ptr<simb::MCTruth>
const& truth = particleToTruth
286 ? particleToTruth->at(iParticle)
287 : particleToTruthLight
288 ? particleToTruthLight->at(iParticle)
289 : art::Ptr<simb::MCTruth>{}
291 art::InputTag
const& truthTag
292 = truth? namesRegistry[truth]: art::InputTag{};
296 ? particleToTruth->data(iParticle).ref()
301 log <<
"\n[#" << (iParticle++) <<
"] ";
305 mf::LogVerbatim(fOutputCategory) <<
"\n";
313 if (fNMissingTruth > 0) {
314 mf::LogProblem(fOutputCategory)
315 <<
"Warning: " << fNMissingTruth <<
"/" << fNEvents
316 <<
" events lacked event generator information for '"
317 << fParticleTruthInfo <<
"'.";
319 else if (fNMissingTruthIndex > 0) {
320 mf::LogProblem(fOutputCategory)
321 <<
"Warning: " << fNMissingTruthIndex <<
"/" << fNEvents
322 <<
" events lacked information of which particles of '"
323 << fParticleTruthInfo <<
"' are generator particles.";
process_name opflashCryo1 flashfilter analyze
static constexpr GeneratedParticleIndex_t NoGeneratedParticleIndex
Constant representing the absence of generator truth information.
bool hasGeneratedParticleIndex() const
Returns whether the specified one is an acceptable generator index.
std::string fOutputCategory
name of the stream for output
void DumpMCParticleTrajectory(Stream &&out, simb::MCTrajectory const &trajectory, unsigned int pointsPerLine, std::string indent)
Dumps the specified particle trajectory into the output stream.
Contains data associated to particles from detector simulation.
Utility functions to print MC truth information.
void DumpMCParticle(Stream &&out, simb::MCParticle const &particle, art::InputTag const &truthTag, sim::GeneratedParticleInfo const &truthInfo, std::string indent="", bool bIndentFirst=true) const
Dumps the content of the specified particle in the output stream.
BEGIN_PROLOG vertical distance to the surface Name
art::EDAnalyzer::Table< Config > Parameters
Contains information about a generated particle.
unsigned int fPointsPerLine
trajectory points per output line
art::InputTag fParticleTruthInfo
name of MCParticle assns data product
void endJob() override
May print some warnings.
void analyze(art::Event const &event) override
art::InputTag fInputParticles
name of MCParticle's data product
GeneratedParticleIndex_t generatedParticleIndex() const
Returns the generated particle index.
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.
DumpMCParticles(Parameters const &config)
Configuration-checking constructor.