LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
DumpMCParticles_module.cc
Go to the documentation of this file.
1 
9 // LArSoft libraries
10 #include "lardataalg/MCDumpers/MCDumpers.h" // sim::dump namespace
12 
13 // nusimdata libraries
16 
17 // framework libraries
25 #include "fhiclcpp/types/Atom.h"
28 
29 // C/C++ standard libraries
30 #include <memory> // std::unique_ptr<>
31 #include <string>
32 
33 namespace sim {
34  class DumpMCParticles;
35 } // namespace sim
36 
37 namespace {
38  using namespace fhicl;
39 
41  struct Config {
42  using Name = fhicl::Name;
43  using Comment = fhicl::Comment;
44 
45  fhicl::Atom<art::InputTag> InputParticles{
46  Name("InputParticles"),
47  Comment("data product with the MC particles to be dumped")};
48 
49  fhicl::OptionalAtom<art::InputTag> ParticleTruthInfo{
50  Name("ParticleTruthInfo"),
51  Comment("label of the association to MCTruth (default: as `InputParticles`)")};
52 
53  fhicl::Atom<std::string> OutputCategory{
54  Name("OutputCategory"),
55  Comment("name of the output stream (managed by the message facility)"),
56  "DumpMCParticles" /* default value */
57  };
58 
59  fhicl::Atom<unsigned int> PointsPerLine{
60  Name("PointsPerLine"),
61  Comment("trajectory points printed per line (default: 2; 0 = skip them)"),
62  2 /* default value */
63  };
64 
65  }; // struct Config
66 
67 } // local namespace
68 
70 public:
71  // type to enable module parameters description by art
73 
75  explicit DumpMCParticles(Parameters const& config);
76 
77  // Plugins should not be copied or assigned.
78  DumpMCParticles(DumpMCParticles const&) = delete;
79  DumpMCParticles(DumpMCParticles&&) = delete;
80  DumpMCParticles& operator=(DumpMCParticles const&) = delete;
82 
83  // Operates on the event
84  void analyze(art::Event const& event) override;
85 
87  void endJob() override;
88 
109  template <typename Stream>
110  void DumpMCParticle(Stream&& out,
111  simb::MCParticle const& particle,
112  art::InputTag const& truthTag,
113  sim::GeneratedParticleInfo const& truthInfo,
114  std::string indent = "",
115  bool bIndentFirst = true) const;
116 
117 private:
120  std::string fOutputCategory;
121  unsigned int fPointsPerLine;
122 
123  unsigned int fNEvents = 0U;
124  unsigned int fNMissingTruth = 0U;
127  unsigned int fNMissingTruthIndex = 0U;
128 
129 }; // class sim::DumpMCParticles
130 
131 //------------------------------------------------------------------------------
132 //--- module implementation
133 //---
134 //------------------------------------------------------------------------------
135 namespace {
136 
137  //----------------------------------------------------------------------------
138  class ProductNameCache {
139 
140  public:
141  ProductNameCache(art::Event const& event) : fEvent(event) {}
142 
144  template <typename T>
145  art::InputTag const& operator[](art::Ptr<T> const& ptr)
146  {
147  auto const iInfo = fNames.find(ptr.id());
148  return (iInfo == fNames.end()) ? fetch(ptr) : iInfo->second;
149  }
150 
151  private:
152  art::Event const& fEvent;
153  std::map<art::ProductID, art::InputTag> fNames;
154 
155  template <typename T>
156  art::InputTag fetchTag(art::Ptr<T> const& ptr)
157  {
158  if (auto provenance = fEvent.getProductProvenance(ptr.id())) {
159  return provenance->inputTag();
160  }
161  return {};
162  }
163 
164  template <typename T>
165  art::InputTag const& fetch(art::Ptr<T> const& ptr)
166  {
167  art::InputTag const tag = fetchTag(ptr);
168  return fNames.try_emplace(ptr.id(), tag).first->second;
169  }
170 
171  }; // class ProductNameCache
172 
173  //----------------------------------------------------------------------------
174  template <typename Right, typename Metadata, typename Left>
175  std::unique_ptr<art::FindOneP<Right, Metadata>> makeFindOneP(
176  art::ValidHandle<std::vector<Left>> const& handle,
177  art::Event const& event,
178  art::InputTag const& tag)
179  {
180 
182  if (!event.getByLabel(tag, assnsHandle)) return {};
183 
184  return std::make_unique<art::FindOneP<Right, Metadata>>(handle, event, tag);
185 
186  } // makeFindOneP()
187 
188  //----------------------------------------------------------------------------
189 
190 } // local namespace
191 
192 //------------------------------------------------------------------------------
194  : EDAnalyzer(config)
195  , fInputParticles(config().InputParticles())
196  , fOutputCategory(config().OutputCategory())
197  , fPointsPerLine(config().PointsPerLine())
198 {
199  if (!config().ParticleTruthInfo(fParticleTruthInfo)) fParticleTruthInfo = fInputParticles;
200 }
201 
202 //------------------------------------------------------------------------------
203 template <typename Stream>
205  simb::MCParticle const& particle,
206  art::InputTag const& truthTag,
207  sim::GeneratedParticleInfo const& truthInfo,
208  std::string indent /* = "" */,
209  bool bIndentFirst /* = true */
210 ) const
211 {
212 
213  if (!truthTag.label().empty() || truthInfo.hasGeneratedParticleIndex()) {
214  out << "(from ";
215  if (truthTag.label().empty())
216  out << "unknown truth record";
217  else
218  out << "'" << truthTag.encode() << "'";
219  if (truthInfo.hasGeneratedParticleIndex())
220  out << " particle #" << truthInfo.generatedParticleIndex();
221  out << ") ";
222  }
223 
225  std::forward<Stream>(out), particle, indent, bIndentFirst ? indent : "");
226 
227  const unsigned int nPoints = particle.NumberTrajectoryPoints();
228  if ((nPoints > 0) && (fPointsPerLine > 0)) {
229  out << ":";
231  std::forward<Stream>(out), particle.Trajectory(), fPointsPerLine, indent + " ");
232  } // if has points
233 
234 } // sim::DumpMCParticles::DumpMCParticle()
235 
236 //------------------------------------------------------------------------------
238 {
239 
240  ++fNEvents;
241 
242  ProductNameCache namesRegistry(event);
243 
244  // get the particles from the event
245  auto const& particleHandle = event.getValidHandle<std::vector<simb::MCParticle>>(fInputParticles);
246  auto const& Particles = *particleHandle;
247 
248  // get the association to MCTruth
249  // - try first the more complete one, with true particle indices
250  // - as a fallback, go without true particle indices
251  auto particleToTruth = makeFindOneP<simb::MCTruth, sim::GeneratedParticleInfo>(
252  particleHandle, event, fParticleTruthInfo);
253  std::unique_ptr<art::FindOneP<simb::MCTruth>> particleToTruthLight;
254  if (!particleToTruth) {
256  particleToTruthLight =
257  makeFindOneP<simb::MCTruth, void>(particleHandle, event, fParticleTruthInfo);
258  if (!particleToTruthLight) ++fNMissingTruth;
259  }
260 
262  << "Event " << event.id() << ": data product '" << fInputParticles.encode() << "' contains "
263  << Particles.size() << " MCParticle's";
264 
265  unsigned int iParticle = 0;
266  for (simb::MCParticle const& particle : Particles) {
267  // flush on every particle,
268  // since the output buffer might grow too large otherwise
270 
271  // fetch the input tag of the truth information (if any)
272  art::Ptr<simb::MCTruth> const& truth = particleToTruth ? particleToTruth->at(iParticle) :
273  particleToTruthLight ?
274  particleToTruthLight->at(iParticle) :
276  art::InputTag const& truthTag = truth ? namesRegistry[truth] : art::InputTag{};
277 
278  // fetch the index of the true particle in the truth record (if any)
279  sim::GeneratedParticleInfo truthInfo = particleToTruth ?
280  particleToTruth->data(iParticle).ref() :
282 
283  // a bit of a header
284  log << "\n[#" << (iParticle++) << "] ";
285  DumpMCParticle(log, particle, truthTag, truthInfo, " ", false);
286  } // for
287 
289 
290 } // sim::DumpMCParticles::analyze()
291 
292 //------------------------------------------------------------------------------
294 {
295 
296  if (fNMissingTruth > 0) {
298  << "Warning: " << fNMissingTruth << "/" << fNEvents
299  << " events lacked event generator information for '" << fParticleTruthInfo << "'.";
300  }
301  else if (fNMissingTruthIndex > 0) {
302  mf::LogProblem(fOutputCategory) << "Warning: " << fNMissingTruthIndex << "/" << fNEvents
303  << " events lacked information of which particles of '"
304  << fParticleTruthInfo << "' are generator particles.";
305  }
306 
307 } // sim::DumpMCParticles::endJob()
308 
309 //------------------------------------------------------------------------------
311 
312 //------------------------------------------------------------------------------
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:219
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
const simb::MCTrajectory & Trajectory() const
Definition: MCParticle.h:254
void DumpMCParticleTrajectory(Stream &&out, simb::MCTrajectory const &trajectory, unsigned int pointsPerLine, std::string indent)
Dumps the specified particle trajectory into the output stream.
Definition: MCDumpers.h:288
Contains data associated to particles from detector simulation.
EDAnalyzer(fhicl::ParameterSet const &pset)
Definition: EDAnalyzer.cc:6
Particle class.
std::string encode() const
Definition: InputTag.cc:97
std::string const & label() const noexcept
Definition: InputTag.cc:79
MaybeLogger_< ELseverityLevel::ELsev_error, true > LogProblem
unsigned int fNMissingTruthIndex
Count of events without truth index.
Utility functions to print MC truth information.
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
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.
parameter set interface
std::string indent(std::size_t const i)
unsigned int fNMissingTruth
Count of events without truth association.
ProductID id() const noexcept
Definition: Ptr.h:160
Monte Carlo Simulation.
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
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&#39;s data product
GeneratedParticleIndex_t generatedParticleIndex() const
Returns the generated particle index.
DumpMCParticles & operator=(DumpMCParticles const &)=delete
Definition: fwd.h:26
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:226
Event finding and building.
std::optional< Provenance const > getProductProvenance(ProductID) const
DumpMCParticles(Parameters const &config)
Configuration-checking constructor.