Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
LArPandoraExternalEventBuilding_module.cc
Go to the documentation of this file.
1
7#include "art/Framework/Core/EDProducer.h"
8#include "art/Framework/Core/ModuleMacros.h"
9#include "art/Framework/Principal/Event.h"
10#include "art/Utilities/make_tool.h"
11
12#include "canvas/Utilities/InputTag.h"
13
14#include "fhiclcpp/ParameterSet.h"
15
16#include "lardata/Utilities/AssociationUtil.h"
17
19
23
24#include "lardataobj/RecoBase/PFParticle.h"
25#include "lardataobj/RecoBase/PFParticleMetadata.h"
26
27#include "TTree.h"
28
29namespace lar_pandora {
30
31 class LArPandoraExternalEventBuilding : public art::EDProducer {
32 public:
33 explicit LArPandoraExternalEventBuilding(fhicl::ParameterSet const& pset);
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
113 float GetMetadataValue(const art::Ptr<larpandoraobj::PFParticleMetadata>& metadata,
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
135 art::InputTag m_pandoraTag;
136 std::unique_ptr<SliceIdBaseTool> m_sliceIdTool;
138 std::string m_targetKey;
139 std::string m_scoreKey;
140 };
141
142 DEFINE_ART_MODULE(LArPandoraExternalEventBuilding)
143
144} // namespace lar_pandora
145
146//------------------------------------------------------------------------------------------------------------------------------------------
147// implementation follows
148
149#include "Pandora/PdgTable.h"
150
151namespace 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"))
160 , m_pandoraTag(art::InputTag(m_inputProducerLabel))
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
211 SliceVector slices;
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 {
234 art::Handle<std::vector<recob::PFParticle>> pfParticleHandle;
235 evt.getByLabel(m_pandoraTag, pfParticleHandle);
236
237 art::FindManyP<larpandoraobj::PFParticleMetadata> pfParticleMetadataAssoc(
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
383 const art::Ptr<larpandoraobj::PFParticleMetadata>& metadata,
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
A description of all outputs from an instance of pandora with functionality to filter and merge multi...
helper function for LArPandoraInterface producer module
header for the lar pandora slice class
header for the lar pandora slice ID base tool
Class to handle the required producer labels.
LArPandoraEvent class.
void WriteToEvent() const
Write (put) the collections in this LArPandoraEvent to the art::Event.
bool m_shouldProduceT0s
If we should produce T0s (relevant when stitching over multiple drift volumes)
void CollectPFParticles(const art::Event &evt, PFParticleToMetadata &particlesToMetadata, PFParticleVector &particles) const
Collect PFParticles from the ART event and their mapping to metadata objects.
void CollectSlices(const PFParticleVector &allParticles, const PFParticleToMetadata &particlesToMetadata, const PFParticleMap &particleMap, SliceVector &slices) const
Collect slices.
bool IsTarget(const art::Ptr< larpandoraobj::PFParticleMetadata > &metadata) const
Query a metadata object to see if it is a target particle.
std::unique_ptr< SliceIdBaseTool > m_sliceIdTool
The slice id tool.
std::string m_trackProducerLabel
Label for the track producer using the Pandora instance that produced the collections we want to cons...
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.
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.
art::InputTag m_pandoraTag
The input tag for the pandora producer.
std::string m_targetKey
The metadata key for a PFParticle to determine if it is the target.
LArPandoraExternalEventBuilding & operator=(LArPandoraExternalEventBuilding &&)=delete
LArPandoraExternalEventBuilding & operator=(LArPandoraExternalEventBuilding const &)=delete
std::string m_inputProducerLabel
Label for the Pandora instance that produced the collections we want to consolidated.
std::map< art::Ptr< recob::PFParticle >, art::Ptr< larpandoraobj::PFParticleMetadata > > PFParticleToMetadata
void BuildPFParticleMap(const PFParticleToMetadata &particlesToMetadata, PFParticleMap &particleMap) const
Build mapping from ID to PFParticle for fast navigation through the hierarchy.
bool m_useTestBeamMode
If we should expect a test-beam (instead of a neutrino) slice.
std::string m_scoreKey
The metadata key for the score of the target slice from Pandora.
std::string m_showerProducerLabel
Label for the shower producer using the Pandora instance that produced the collections we want to con...
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.
LArPandoraExternalEventBuilding(LArPandoraExternalEventBuilding &&)=delete
LArPandoraExternalEventBuilding(LArPandoraExternalEventBuilding const &)=delete
std::string m_hitProducerLabel
Label for the hit producer that was used as input to the Pandora instance specified.
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.
Abstract base class for a slice ID tool.
std::map< int, art::Ptr< recob::PFParticle > > PFParticleMap
std::vector< Slice > SliceVector
Definition Slice.h:70
std::vector< art::Ptr< recob::PFParticle > > PFParticleVector