LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
DumpMCParticles_module.cc
Go to the documentation of this file.
1 
9 // LArSoft libraries
10 #include "larsim/MCDumpers/MCDumpers.h" // sim::dump namespace
12 
13 // nutools libraries
16 #include "nusimdata/SimulationBase/simb.h" // simb::NoGeneratedParticleIndex
17 
18 // framework libraries
26 #include "fhiclcpp/ParameterSet.h"
27 #include "fhiclcpp/types/Atom.h"
30 
31 // C/C++ standard libraries
32 #include <memory> // std::unique_ptr<>
33 #include <vector>
34 #include <string>
35 #include <cstddef> // std::size_t
36 
37 
38 namespace sim {
39  class DumpMCParticles;
40 } // namespace sim
41 
42 namespace {
43  using namespace fhicl;
44 
46  struct Config {
47  using Name = fhicl::Name;
48  using Comment = fhicl::Comment;
49 
50  fhicl::Atom<art::InputTag> InputParticles {
51  Name("InputParticles"),
52  Comment("data product with the MC particles to be dumped")
53  };
54 
55  fhicl::OptionalAtom<art::InputTag> ParticleTruthInfo {
56  Name("ParticleTruthInfo"),
57  Comment
58  ("label of the association to MCTruth (default: as `InputParticles`)")
59  };
60 
61  fhicl::Atom<std::string> OutputCategory {
62  Name("OutputCategory"),
63  Comment("name of the output stream (managed by the message facility)"),
64  "DumpMCParticles" /* default value */
65  };
66 
67  fhicl::Atom<unsigned int> PointsPerLine {
68  Name("PointsPerLine"),
69  Comment("trajectory points printed per line (default: 2; 0 = skip them)"),
70  2 /* default value */
71  };
72 
73  }; // struct Config
74 
75 
76 } // local namespace
77 
78 
80  public:
81  // type to enable module parameters description by art
83 
85  explicit DumpMCParticles(Parameters const& config);
86 
87  // Plugins should not be copied or assigned.
88  DumpMCParticles(DumpMCParticles const&) = delete;
89  DumpMCParticles(DumpMCParticles &&) = delete;
92 
93 
94  // Operates on the event
95  void analyze(art::Event const& event) override;
96 
98  void endJob() override;
99 
120  template <typename Stream>
121  void DumpMCParticle(
122  Stream&& out, simb::MCParticle const& particle,
123  art::InputTag const& truthTag, sim::GeneratedParticleInfo const& truthInfo,
124  std::string indent = "", bool bIndentFirst = true
125  ) const;
126 
127 
128  private:
129 
132  std::string fOutputCategory;
133  unsigned int fPointsPerLine;
134 
135  unsigned int fNEvents = 0U;
136  unsigned int fNMissingTruth = 0U;
139  unsigned int fNMissingTruthIndex = 0U;
140 
141 }; // class sim::DumpMCParticles
142 
143 
144 //------------------------------------------------------------------------------
145 //--- module implementation
146 //---
147 //------------------------------------------------------------------------------
148 namespace {
149 
150  //----------------------------------------------------------------------------
151  class ProductNameCache {
152 
153  public:
154  ProductNameCache(art::Event const& event): fEvent(event) {}
155 
157  template <typename T>
158  art::InputTag const& operator[](art::Ptr<T> const& ptr)
159  {
160  auto const iInfo = fNames.find(ptr.id());
161  return (iInfo == fNames.end())? fetch(ptr): iInfo->second;
162  }
163 
164  private:
165  art::Event const& fEvent;
166  std::map<art::ProductID, art::InputTag> fNames;
167 
168  template <typename T>
169  art::InputTag fetchTag(art::Ptr<T> const& ptr)
170  {
172  return fEvent.get(ptr.id(), handle)
173  ? handle.provenance()->inputTag()
174  : art::InputTag{}
175  ;
176  }
177 
178  template <typename T>
179  art::InputTag const& fetch(art::Ptr<T> const& ptr)
180  {
181  art::InputTag const tag = fetchTag(ptr);
182  return fNames.emplace(ptr.id(), tag).first->second;
183  }
184 
185  }; // class ProductNameCache
186 
187 
188  //----------------------------------------------------------------------------
189  template <typename Right, typename Metadata, typename Left>
190  std::unique_ptr<art::FindOneP<Right, Metadata>> makeFindOneP(
191  art::ValidHandle<std::vector<Left>> const& handle,
192  art::Event const& event,
193  art::InputTag const& tag
194  ) {
195 
197  if (!event.getByLabel(tag, assnsHandle)) return {};
198 
199  return std::make_unique<art::FindOneP<Right, Metadata>>
200  (handle, event, tag);
201 
202  } // makeFindOneP()
203 
204 
205  //----------------------------------------------------------------------------
206 
207 } // local namespace
208 
209 
210 //------------------------------------------------------------------------------
212  : EDAnalyzer(config)
213  , fInputParticles(config().InputParticles())
214  , fOutputCategory(config().OutputCategory())
215  , fPointsPerLine(config().PointsPerLine())
216 {
217  if (!config().ParticleTruthInfo(fParticleTruthInfo))
219 
220 }
221 
222 //------------------------------------------------------------------------------
223 template <typename Stream>
225  Stream&& out, simb::MCParticle const& particle,
226  art::InputTag const& truthTag, sim::GeneratedParticleInfo const& truthInfo,
227  std::string indent /* = "" */, bool bIndentFirst /* = true */
228 ) const {
229 
230  if (!truthTag.label().empty() || truthInfo.hasGeneratedParticleIndex()) {
231  out << "(from ";
232  if (truthTag.label().empty()) out << "unknown truth record";
233  else out << "'" << truthTag.encode() << "'";
234  if (truthInfo.hasGeneratedParticleIndex())
235  out << " particle #" << truthInfo.generatedParticleIndex();
236  out << ") ";
237  }
238 
240  (std::forward<Stream>(out), particle, indent, bIndentFirst? indent: "");
241 
242  const unsigned int nPoints = particle.NumberTrajectoryPoints();
243  if ((nPoints > 0) && (fPointsPerLine > 0)) {
244  out << ":";
246  std::forward<Stream>(out), particle.Trajectory(),
247  fPointsPerLine, indent + " "
248  );
249  } // if has points
250 
251 } // sim::DumpMCParticles::DumpMCParticle()
252 
253 
254 //------------------------------------------------------------------------------
256 
257  ++fNEvents;
258 
259  ProductNameCache namesRegistry(event);
260 
261  // get the particles from the event
262  auto const& particleHandle
263  = event.getValidHandle<std::vector<simb::MCParticle>>(fInputParticles);
264  auto const& Particles = *particleHandle;
265 
266  // get the association to MCTruth
267  // - try first the more complete one, with true particle indices
268  // - as a fallback, go without true particle indices
269  auto particleToTruth = makeFindOneP<simb::MCTruth, sim::GeneratedParticleInfo>
270  (particleHandle, event, fParticleTruthInfo);
271  std::unique_ptr<art::FindOneP<simb::MCTruth>> particleToTruthLight;
272  if (!particleToTruth) {
274  particleToTruthLight = makeFindOneP<simb::MCTruth, void>
275  (particleHandle, event, fParticleTruthInfo);
276  if (!particleToTruthLight) ++fNMissingTruth;
277  }
278 
279  mf::LogVerbatim(fOutputCategory) << "Event " << event.id()
280  << ": data product '" << fInputParticles.encode() << "' contains "
281  << Particles.size() << " MCParticle's";
282 
283  unsigned int iParticle = 0;
284  for (simb::MCParticle const& particle: Particles) {
285  // flush on every particle,
286  // since the output buffer might grow too large otherwise
288 
289  // fetch the input tag of the truth information (if any)
290  art::Ptr<simb::MCTruth> const& truth = particleToTruth
291  ? particleToTruth->at(iParticle)
292  : particleToTruthLight
293  ? particleToTruthLight->at(iParticle)
295  ;
296  art::InputTag const& truthTag
297  = truth? namesRegistry[truth]: art::InputTag{};
298 
299  // fetch the index of the true particle in the truth record (if any)
300  sim::GeneratedParticleInfo truthInfo = particleToTruth
301  ? particleToTruth->data(iParticle).ref()
303  ;
304 
305  // a bit of a header
306  log << "\n[#" << (iParticle++) << "] ";
307  DumpMCParticle(log, particle, truthTag, truthInfo, " ", false);
308  } // for
309 
311 
312 } // sim::DumpMCParticles::analyze()
313 
314 
315 //------------------------------------------------------------------------------
317 
318  if (fNMissingTruth > 0) {
320  << "Warning: " << fNMissingTruth << "/" << fNEvents
321  << " events lacked event generator information for '"
322  << fParticleTruthInfo << "'.";
323  }
324  else if (fNMissingTruthIndex > 0) {
326  << "Warning: " << fNMissingTruthIndex << "/" << fNEvents
327  << " events lacked information of which particles of '"
328  << fParticleTruthInfo << "' are generator particles.";
329  }
330 
331 } // sim::DumpMCParticles::endJob()
332 
333 
334 //------------------------------------------------------------------------------
336 
337 //------------------------------------------------------------------------------
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:222
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:257
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:289
bool get(SelectorBase const &, Handle< PROD > &result) const
Definition: DataViewImpl.h:307
Contains data associated to particles from detector simulation.
Particle class.
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:42
Provenance const * provenance() const
Definition: Handle.h:204
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 encode() const
Definition: InputTag.cc:36
std::string indent(std::size_t const i)
unsigned int fNMissingTruth
Count of events without truth association.
EDAnalyzer(Table< Config > const &config)
Definition: EDAnalyzer.h:100
ProductID id() const
Definition: Ptr.h:349
Monte Carlo Simulation.
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
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
std::string const & label() const noexcept
Definition: InputTag.h:55
Definition: fwd.h:25
Common type definitions for data products (and a bit beyond).
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:228
Event finding and building.
DumpMCParticles(Parameters const &config)
Configuration-checking constructor.