LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
LArPandoraExternalEventBuilding_module.cc
Go to the documentation of this file.
1 
11 
13 
14 #include "fhiclcpp/ParameterSet.h"
15 
17 
19 
23 
26 
27 #include "TTree.h"
28 
29 namespace lar_pandora {
30 
32  public:
34 
39 
40  void produce(art::Event& evt) override;
41 
42  private:
43  typedef std::map<art::Ptr<recob::PFParticle>, art::Ptr<larpandoraobj::PFParticleMetadata>>
45 
53  void CollectPFParticles(const art::Event& evt,
54  PFParticleToMetadata& particlesToMetadata,
55  PFParticleVector& particles) const;
56 
63  void BuildPFParticleMap(const PFParticleToMetadata& particlesToMetadata,
64  PFParticleMap& particleMap) const;
65 
74  void CollectClearCosmicRays(const PFParticleVector& allParticles,
75  const PFParticleToMetadata& particlesToMetadata,
76  const PFParticleMap& particleMap,
77  PFParticleVector& clearCosmics) const;
78 
87  void CollectSlices(const PFParticleVector& allParticles,
88  const PFParticleToMetadata& particlesToMetadata,
89  const PFParticleMap& particleMap,
90  SliceVector& slices) const;
91 
100  void CollectConsolidatedParticles(const PFParticleVector& allParticles,
101  const PFParticleVector& clearCosmics,
102  const SliceVector& slices,
103  PFParticleVector& consolidatedParticles) const;
104 
114  const std::string& key) const;
115 
123  bool IsTarget(const art::Ptr<larpandoraobj::PFParticleMetadata>& metadata) const;
124 
125  std::string
127  std::string
129  std::string
131  std::string
133  bool
136  std::unique_ptr<SliceIdBaseTool> m_sliceIdTool;
138  std::string m_targetKey;
139  std::string m_scoreKey;
140  };
141 
143 
144 } // namespace lar_pandora
145 
146 //------------------------------------------------------------------------------------------------------------------------------------------
147 // implementation follows
148 
149 #include "Pandora/PdgTable.h"
150 
151 namespace lar_pandora {
152 
154  : EDProducer{pset}
155  , m_inputProducerLabel(pset.get<std::string>("InputProducerLabel"))
156  , m_trackProducerLabel(pset.get<std::string>("TrackProducerLabel"))
157  , m_showerProducerLabel(pset.get<std::string>("ShowerProducerLabel"))
158  , m_hitProducerLabel(pset.get<std::string>("HitProducerLabel"))
159  , m_shouldProduceT0s(pset.get<bool>("ShouldProduceT0s"))
161  , m_sliceIdTool(art::make_tool<SliceIdBaseTool>(pset.get<fhicl::ParameterSet>("SliceIdTool")))
162  , m_useTestBeamMode(pset.get<bool>("ShouldUseTestBeamMode", false))
163  , m_targetKey(m_useTestBeamMode ? "IsTestBeam" : "IsNeutrino")
164  , m_scoreKey(m_useTestBeamMode ? "TestBeamScore" : "NuScore")
165  {
166  produces<std::vector<recob::PFParticle>>();
167  produces<std::vector<recob::SpacePoint>>();
168  produces<std::vector<recob::Cluster>>();
169  produces<std::vector<recob::Vertex>>();
170  produces<std::vector<recob::Slice>>();
171  produces<std::vector<recob::Track>>();
172  produces<std::vector<recob::Shower>>();
173  produces<std::vector<recob::PCAxis>>();
174  produces<std::vector<larpandoraobj::PFParticleMetadata>>();
175 
176  produces<art::Assns<recob::PFParticle, recob::SpacePoint>>();
177  produces<art::Assns<recob::PFParticle, recob::Cluster>>();
178  produces<art::Assns<recob::PFParticle, recob::Vertex>>();
179  produces<art::Assns<recob::PFParticle, recob::Slice>>();
180  produces<art::Assns<recob::PFParticle, recob::Track>>();
181  produces<art::Assns<recob::PFParticle, recob::Shower>>();
182  produces<art::Assns<recob::PFParticle, recob::PCAxis>>();
183  produces<art::Assns<recob::PFParticle, larpandoraobj::PFParticleMetadata>>();
184  produces<art::Assns<recob::Track, recob::Hit, recob::TrackHitMeta>>();
185  produces<art::Assns<recob::Shower, recob::Hit>>();
186  produces<art::Assns<recob::Shower, recob::PCAxis>>();
187  produces<art::Assns<recob::SpacePoint, recob::Hit>>();
188  produces<art::Assns<recob::Cluster, recob::Hit>>();
189  produces<art::Assns<recob::Slice, recob::Hit>>();
190 
191  if (m_shouldProduceT0s) {
192  produces<std::vector<anab::T0>>();
193  produces<art::Assns<recob::PFParticle, anab::T0>>();
194  }
195  }
196 
197  //------------------------------------------------------------------------------------------------------------------------------------------
198 
200  {
201  PFParticleVector particles;
202  PFParticleToMetadata particlesToMetadata;
203  this->CollectPFParticles(evt, particlesToMetadata, particles);
204 
205  PFParticleMap particleMap;
206  this->BuildPFParticleMap(particlesToMetadata, particleMap);
207 
208  PFParticleVector clearCosmics;
209  this->CollectClearCosmicRays(particles, particlesToMetadata, particleMap, clearCosmics);
210 
212  this->CollectSlices(particles, particlesToMetadata, particleMap, slices);
213 
214  m_sliceIdTool->ClassifySlices(slices, evt);
215 
216  PFParticleVector consolidatedParticles;
217  this->CollectConsolidatedParticles(particles, clearCosmics, slices, consolidatedParticles);
218 
219  const LArPandoraEvent::Labels labels(
221  const LArPandoraEvent consolidatedEvent(LArPandoraEvent(this, &evt, labels, m_shouldProduceT0s),
222  consolidatedParticles);
223 
224  consolidatedEvent.WriteToEvent();
225  }
226 
227  //------------------------------------------------------------------------------------------------------------------------------------------
228 
230  const art::Event& evt,
231  PFParticleToMetadata& particlesToMetadata,
232  PFParticleVector& particles) const
233  {
235  evt.getByLabel(m_pandoraTag, pfParticleHandle);
236 
238  pfParticleHandle, evt, m_pandoraTag);
239 
240  for (unsigned int i = 0; i < pfParticleHandle->size(); ++i) {
241  const art::Ptr<recob::PFParticle> part(pfParticleHandle, i);
242  const auto& metadata(pfParticleMetadataAssoc.at(part.key()));
243 
244  particles.push_back(part);
245 
246  if (metadata.size() != 1)
247  throw cet::exception("LArPandora")
248  << " LArPandoraExternalEventBuilding::CollectPFParticles -- Found a PFParticle without "
249  "exactly 1 metadata associated."
250  << std::endl;
251 
252  if (!particlesToMetadata.insert(PFParticleToMetadata::value_type(part, metadata.front()))
253  .second)
254  throw cet::exception("LArPandoraExternalEventBuilding")
255  << "Repeated PFParticles" << std::endl;
256  }
257  }
258 
259  //------------------------------------------------------------------------------------------------------------------------------------------
260 
262  const PFParticleToMetadata& particlesToMetadata,
263  PFParticleMap& particleMap) const
264  {
265  for (const auto& entry : particlesToMetadata) {
266  if (!particleMap.insert(PFParticleMap::value_type(entry.first->Self(), entry.first)).second)
267  throw cet::exception("LArPandoraExternalEventBuilding")
268  << "Repeated PFParticles" << std::endl;
269  }
270  }
271 
272  //------------------------------------------------------------------------------------------------------------------------------------------
273 
275  const PFParticleVector& allParticles,
276  const PFParticleToMetadata& particlesToMetadata,
277  const PFParticleMap& particleMap,
278  PFParticleVector& clearCosmics) const
279  {
280  for (const auto& part : allParticles) {
281  // Get the parent of the particle
282  const auto parentIt(
283  particlesToMetadata.find(LArPandoraHelper::GetParentPFParticle(particleMap, part)));
284  if (parentIt == particlesToMetadata.end())
285  throw cet::exception("LArPandoraExternalEventBuilding")
286  << "Found PFParticle without metadata" << std::endl;
287 
288  // ATTN particles without the "IsClearCosmic" parameter are not clear cosmics
289  try {
290  if (static_cast<bool>(
291  std::round(this->GetMetadataValue(parentIt->second, "IsClearCosmic"))))
292  clearCosmics.push_back(part);
293  }
294  catch (const cet::exception&) {
295  }
296  }
297  }
298 
299  //------------------------------------------------------------------------------------------------------------------------------------------
300 
302  const PFParticleVector& allParticles,
303  const PFParticleToMetadata& particlesToMetadata,
304  const PFParticleMap& particleMap,
305  SliceVector& slices) const
306  {
307  std::map<unsigned int, float> targetScores;
308  std::map<unsigned int, PFParticleVector> crHypotheses;
309  std::map<unsigned int, PFParticleVector> targetHypotheses;
310  std::vector<unsigned int> usedSliceIds;
311 
312  // Collect the slice information
313  for (const auto& part : allParticles) {
314  // Find the parent PFParticle
315  const auto parentIt(
316  particlesToMetadata.find(LArPandoraHelper::GetParentPFParticle(particleMap, part)));
317  if (parentIt == particlesToMetadata.end())
318  throw cet::exception("LArPandoraExternalEventBuilding")
319  << "Found PFParticle without metadata" << std::endl;
320 
321  // Skip PFParticles that are clear cosmics
322  try {
323  if (static_cast<bool>(
324  std::round(this->GetMetadataValue(parentIt->second, "IsClearCosmic"))))
325  continue;
326  }
327  catch (const cet::exception&) {
328  }
329 
330  const unsigned int sliceId(static_cast<unsigned int>(
331  std::round(this->GetMetadataValue(parentIt->second, "SliceIndex"))));
332  const float targetScore(this->GetMetadataValue(parentIt->second, m_scoreKey));
333 
334  // Keep track of the slice IDs we have used, and their corresponding score
335  if (std::find(usedSliceIds.begin(), usedSliceIds.end(), sliceId) == usedSliceIds.end()) {
336  usedSliceIds.push_back(sliceId);
337 
338  // ATTN all PFParticles in the same slice will have the same targetScore
339  targetScores[sliceId] = targetScore;
340  }
341 
342  if (this->IsTarget(parentIt->second)) { targetHypotheses[sliceId].push_back(part); }
343  else {
344  crHypotheses[sliceId].push_back(part);
345  }
346  }
347 
348  // Sort the slice IDs to ensure reproducibility
349  std::sort(usedSliceIds.begin(), usedSliceIds.end());
350 
351  // ATTN: we need to ensure that for each slice there is a cosmic and neutrino hypothesis, even if the pass created no PFOs
352  // in such a case we add an empty vector of pfparticles
353  const PFParticleVector emptyPFParticleVector;
354 
355  // Produce the slices
356  for (const unsigned int sliceId : usedSliceIds) {
357  // Get the target score
358  const auto targetScoresIter(targetScores.find(sliceId));
359  if (targetScoresIter == targetScores.end())
360  throw cet::exception("LArPandoraExternalEventBuilding")
361  << "Scrambled slice information - can't find target score with id = " << sliceId
362  << std::endl;
363 
364  PFParticleVector targetPFParticleVector, crPFParticleVector;
365 
366  // Get the target hypothesis
367  const auto targetHypothesisIter(targetHypotheses.find(sliceId));
368  targetPFParticleVector =
369  ((targetHypothesisIter == targetHypotheses.end()) ? emptyPFParticleVector :
370  targetHypothesisIter->second);
371 
372  // Get the cosmic hypothesis
373  const auto crHypothesisIter(crHypotheses.find(sliceId));
374  crPFParticleVector = ((crHypothesisIter == crHypotheses.end()) ? emptyPFParticleVector :
375  crHypothesisIter->second);
376  slices.emplace_back(targetScoresIter->second, targetPFParticleVector, crPFParticleVector);
377  }
378  }
379 
380  //------------------------------------------------------------------------------------------------------------------------------------------
381 
384  const std::string& key) const
385  {
386  const auto& propertiesMap(metadata->GetPropertiesMap());
387  const auto& it(propertiesMap.find(key));
388 
389  if (it == propertiesMap.end())
390  throw cet::exception("LArPandoraExternalEventBuilding")
391  << "No key \"" << key << "\" found in metadata properties map" << std::endl;
392 
393  return it->second;
394  }
395 
396  //------------------------------------------------------------------------------------------------------------------------------------------
397 
399  const PFParticleVector& allParticles,
400  const PFParticleVector& clearCosmics,
401  const SliceVector& slices,
402  PFParticleVector& consolidatedParticles) const
403  {
404  PFParticleVector collectedParticles;
405  collectedParticles.insert(collectedParticles.end(), clearCosmics.begin(), clearCosmics.end());
406 
407  for (const auto& slice : slices) {
408  const PFParticleVector& particles(slice.IsTaggedAsTarget() ? slice.GetTargetHypothesis() :
409  slice.GetCosmicRayHypothesis());
410  collectedParticles.insert(collectedParticles.end(), particles.begin(), particles.end());
411  }
412 
413  // ATTN the collected particles are the ones we want to output, but here we loop over all particles to ensure that the consolidated
414  // particles have the same ordering.
415  for (const auto& part : allParticles) {
416  if (std::find(collectedParticles.begin(), collectedParticles.end(), part) !=
417  collectedParticles.end())
418  consolidatedParticles.push_back(part);
419  }
420  }
421 
422  //------------------------------------------------------------------------------------------------------------------------------------------
423 
425  const art::Ptr<larpandoraobj::PFParticleMetadata>& metadata) const
426  {
427  try {
428  return static_cast<bool>(std::round(this->GetMetadataValue(metadata, m_targetKey)));
429  }
430  catch (const cet::exception&) {
431  return false;
432  }
433  }
434 
435 } // namespace lar_pandora
void CollectSlices(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, SliceVector &slices) const
Collect slices.
void CollectPFParticles(const art::Event &evt, PFParticleToMetadata &particlesToMetadata, PFParticleVector &particles) const
Collect PFParticles from the ART event and their mapping to metadata objects.
std::unique_ptr< SliceIdBaseTool > m_sliceIdTool
The slice id tool.
std::map< art::Ptr< recob::PFParticle >, art::Ptr< larpandoraobj::PFParticleMetadata > > PFParticleToMetadata
LArPandoraEvent class.
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.cc:6
LArPandoraExternalEventBuilding & operator=(LArPandoraExternalEventBuilding const &)=delete
static art::Ptr< recob::PFParticle > GetParentPFParticle(const PFParticleMap &particleMap, const art::Ptr< recob::PFParticle > daughterParticle)
Return the top-level parent particle by navigating up the chain of parent/daughter associations...
std::map< int, art::Ptr< recob::PFParticle > > PFParticleMap
void CollectClearCosmicRays(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, PFParticleVector &clearCosmics) const
Collect PFParticles that have been identified as clear cosmic ray muons by pandora.
std::string m_trackProducerLabel
Label for the track producer using the Pandora instance that produced the collections we want to cons...
std::string m_showerProducerLabel
Label for the shower producer using the Pandora instance that produced the collections we want to con...
TString part[npart]
Definition: Style.C:32
std::string m_hitProducerLabel
Label for the hit producer that was used as input to the Pandora instance specified.
header for the lar pandora slice ID base tool
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
A description of all outputs from an instance of pandora with functionality to filter and merge multi...
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector
key_type key() const noexcept
Definition: Ptr.h:166
const PropertiesMap & GetPropertiesMap() const
std::string m_targetKey
The metadata key for a PFParticle to determine if it is the target.
std::string m_scoreKey
The metadata key for the score of the target slice from Pandora.
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
float GetMetadataValue(const art::Ptr< larpandoraobj::PFParticleMetadata > &metadata, const std::string &key) const
Query a metadata object for a given key and return the corresponding value.
std::vector< Slice > SliceVector
Definition: Slice.h:70
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Utility object to perform functions of association.
bool m_useTestBeamMode
If we should expect a test-beam (instead of a neutrino) slice.
header for the lar pandora slice class
bool m_shouldProduceT0s
If we should produce T0s (relevant when stitching over multiple drift volumes)
art::InputTag m_pandoraTag
The input tag for the pandora producer.
Class to handle the required producer labels.
std::string m_inputProducerLabel
Label for the Pandora instance that produced the collections we want to consolidated.
void BuildPFParticleMap(const PFParticleToMetadata &particlesToMetadata, PFParticleMap &particleMap) const
Build mapping from ID to PFParticle for fast navigation through the hierarchy.
void CollectConsolidatedParticles(const PFParticleVector &allParticles, const PFParticleVector &clearCosmics, const SliceVector &slices, PFParticleVector &consolidatedParticles) const
Get the consolidated collection of particles based on the slice ids.
bool IsTarget(const art::Ptr< larpandoraobj::PFParticleMetadata > &metadata) const
Query a metadata object to see if it is a target particle.
TCEvent evt
Definition: DataStructs.cxx:8
helper function for LArPandoraInterface producer module
Definition: fwd.h:26
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
void WriteToEvent() const
Write (put) the collections in this LArPandoraEvent to the art::Event.