Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
LArPandoraOutput.cxx
Go to the documentation of this file.
1
8
9#include "art/Framework/Principal/Event.h"
10#include "cetlib_except/exception.h"
11#include "messagefacility/MessageLogger/MessageLogger.h"
12
13#include "lardata/Utilities/AssociationUtil.h"
14#include "lardata/Utilities/GeometryUtilities.h"
15#include "larreco/ClusterFinder/ClusterCreator.h"
16#include "larreco/RecoAlg/ClusterParamsImportWrapper.h"
17#include "larreco/RecoAlg/ClusterRecoUtil/StandardClusterParamsAlg.h"
18
19#include "larcore/Geometry/Geometry.h"
20#include "lardata/DetectorInfoServices/DetectorClocksService.h"
21#include "lardata/DetectorInfoServices/DetectorPropertiesService.h"
22#include "lardataobj/RecoBase/Hit.h"
23
24#include "Objects/CaloHit.h"
25#include "Objects/Cluster.h"
27#include "Objects/Vertex.h"
28
32
33#include <algorithm>
34#include <iostream>
35#include <iterator>
36#include <limits>
37#include <numeric> // std::iota()
38
39namespace lar_pandora {
40
42 const IdToHitMap& idToHitMap,
43 art::Event& evt)
44 {
45 settings.Validate();
46 const std::string instanceLabel(
48 const std::string testBeamInteractionVertexInstanceLabel(
49 instanceLabel + settings.m_testBeamInteractionVerticesInstanceLabel);
50
51 // Set up mandatory output collections
52 PFParticleCollection outputParticles(new std::vector<recob::PFParticle>);
53 VertexCollection outputVertices(new std::vector<recob::Vertex>);
54 ClusterCollection outputClusters(new std::vector<recob::Cluster>);
55 SpacePointCollection outputSpacePoints(new std::vector<recob::SpacePoint>);
56 PFParticleMetadataCollection outputParticleMetadata(
57 new std::vector<larpandoraobj::PFParticleMetadata>);
58
59 // Set up optional output collections
60 VertexCollection outputTestBeamInteractionVertices(
61 settings.m_shouldProduceTestBeamInteractionVertices ? new std::vector<recob::Vertex> :
62 nullptr);
63 T0Collection outputT0s(settings.m_shouldRunStitching ? new std::vector<anab::T0> : nullptr);
64 SliceCollection outputSlices(settings.m_shouldProduceSlices ? new std::vector<recob::Slice> :
65 nullptr);
66
67 // Set up mandatory output associations
68 PFParticleToMetadataCollection outputParticlesToMetadata(
69 new art::Assns<recob::PFParticle, larpandoraobj::PFParticleMetadata>);
70 PFParticleToSpacePointCollection outputParticlesToSpacePoints(
71 new art::Assns<recob::PFParticle, recob::SpacePoint>);
72 PFParticleToClusterCollection outputParticlesToClusters(
73 new art::Assns<recob::PFParticle, recob::Cluster>);
74 PFParticleToVertexCollection outputParticlesToVertices(
75 new art::Assns<recob::PFParticle, recob::Vertex>);
76 ClusterToHitCollection outputClustersToHits(new art::Assns<recob::Cluster, recob::Hit>);
77 SpacePointToHitCollection outputSpacePointsToHits(
78 new art::Assns<recob::SpacePoint, recob::Hit>);
79 SliceToHitCollection outputSlicesToHits(new art::Assns<recob::Slice, recob::Hit>);
80
81 // Set up optional output associations
82 PFParticleToVertexCollection outputParticlesToTestBeamInteractionVertices(
84 new art::Assns<recob::PFParticle, recob::Vertex> :
85 nullptr);
86 PFParticleToT0Collection outputParticlesToT0s(
87 settings.m_shouldRunStitching ? new art::Assns<recob::PFParticle, anab::T0> : nullptr);
88 PFParticleToSliceCollection outputParticlesToSlices(
89 settings.m_shouldProduceSlices ? new art::Assns<recob::PFParticle, recob::Slice> : nullptr);
90
91 // Collect immutable lists of pandora collections that we should convert to ART format
92 const pandora::PfoVector pfoVector(
96
97 IdToIdVectorMap pfoToVerticesMap, pfoToTestBeamInteractionVerticesMap;
99 pfoVector, pfoToVerticesMap, lar_content::LArPfoHelper::GetVertex));
100 const pandora::VertexVector testBeamInteractionVertexVector(
103 pfoToTestBeamInteractionVerticesMap,
106
107 IdToIdVectorMap pfoToClustersMap;
108 const pandora::ClusterList clusterList(
109 LArPandoraOutput::CollectClusters(pfoVector, pfoToClustersMap));
110
111 IdToIdVectorMap pfoToThreeDHitsMap;
112 const pandora::CaloHitList threeDHitList(
113 LArPandoraOutput::Collect3DHits(pfoVector, pfoToThreeDHitsMap));
114
115 // Get mapping from pandora hits to art hits
116 CaloHitToArtHitMap pandoraHitToArtHitMap;
118 clusterList, threeDHitList, idToHitMap, pandoraHitToArtHitMap);
119
120 // Build the ART outputs from the pandora objects
121 LArPandoraOutput::BuildVertices(vertexVector, outputVertices);
122
124 LArPandoraOutput::BuildVertices(testBeamInteractionVertexVector,
125 outputTestBeamInteractionVertices);
126
128 instanceLabel,
129 threeDHitList,
130 pandoraHitToArtHitMap,
131 outputSpacePoints,
132 outputSpacePointsToHits);
133
134 IdToIdVectorMap pfoToArtClustersMap;
136 instanceLabel,
137 clusterList,
138 pandoraHitToArtHitMap,
139 pfoToClustersMap,
140 outputClusters,
141 outputClustersToHits,
142 pfoToArtClustersMap);
143
145 instanceLabel,
146 pfoVector,
147 pfoToVerticesMap,
148 pfoToThreeDHitsMap,
149 pfoToArtClustersMap,
150 outputParticles,
151 outputParticlesToVertices,
152 outputParticlesToSpacePoints,
153 outputParticlesToClusters);
154
156 evt, instanceLabel, pfoVector, outputParticleMetadata, outputParticlesToMetadata);
157
158 if (settings.m_shouldProduceSlices)
160 settings.m_pPrimaryPandora,
161 evt,
162 instanceLabel,
163 pfoVector,
164 idToHitMap,
165 outputSlices,
166 outputParticlesToSlices,
167 outputSlicesToHits);
168
169 if (settings.m_shouldRunStitching)
170 LArPandoraOutput::BuildT0s(evt, instanceLabel, pfoVector, outputT0s, outputParticlesToT0s);
171
174 instanceLabel,
175 pfoVector,
176 pfoToTestBeamInteractionVerticesMap,
177 outputParticlesToTestBeamInteractionVertices);
178
179 // Add the outputs to the event
180 evt.put(std::move(outputParticles), instanceLabel);
181 evt.put(std::move(outputSpacePoints), instanceLabel);
182 evt.put(std::move(outputClusters), instanceLabel);
183 evt.put(std::move(outputVertices), instanceLabel);
184 evt.put(std::move(outputParticleMetadata), instanceLabel);
185
186 evt.put(std::move(outputParticlesToMetadata), instanceLabel);
187 evt.put(std::move(outputParticlesToSpacePoints), instanceLabel);
188 evt.put(std::move(outputParticlesToClusters), instanceLabel);
189 evt.put(std::move(outputParticlesToVertices), instanceLabel);
190 evt.put(std::move(outputParticlesToSlices), instanceLabel);
191 evt.put(std::move(outputSpacePointsToHits), instanceLabel);
192 evt.put(std::move(outputClustersToHits), instanceLabel);
193
195 evt.put(std::move(outputTestBeamInteractionVertices), testBeamInteractionVertexInstanceLabel);
196 evt.put(std::move(outputParticlesToTestBeamInteractionVertices),
197 testBeamInteractionVertexInstanceLabel);
198 }
199
200 if (settings.m_shouldRunStitching) {
201 evt.put(std::move(outputT0s), instanceLabel);
202 evt.put(std::move(outputParticlesToT0s), instanceLabel);
203 }
204
205 if (settings.m_shouldProduceSlices) {
206 evt.put(std::move(outputSlices), instanceLabel);
207 evt.put(std::move(outputSlicesToHits), instanceLabel);
208 }
209 }
210
211 //------------------------------------------------------------------------------------------------------------------------------------------
212
214 const std::string& name,
215 const pandora::Pandora*& pPandoraInstance)
216 {
217 if (!pPrimaryPandora)
218 throw cet::exception("LArPandora") << " LArPandoraOutput::GetPandoraInstance--- input "
219 "primary pandora instance address is invalid ";
220
221 if (pPandoraInstance)
222 throw cet::exception("LArPandora") << " LArPandoraOutput::GetPandoraInstance--- the input "
223 "pandora instance address is non-null ";
224
225 for (const pandora::Pandora* const pPandora :
227 if (pPandora->GetName() != name) continue;
228
229 if (pPandoraInstance)
230 throw cet::exception("LArPandora")
231 << " LArPandoraOutput::GetPandoraInstance--- found multiple pandora instances with name: "
232 << name;
233
234 pPandoraInstance = pPandora;
235 }
236
237 return static_cast<bool>(pPandoraInstance);
238 }
239
240 //------------------------------------------------------------------------------------------------------------------------------------------
241
242 void LArPandoraOutput::GetPandoraSlices(const pandora::Pandora* const pPrimaryPandora,
243 pandora::PfoVector& slicePfos)
244 {
245 if (!slicePfos.empty())
246 throw cet::exception("LArPandora")
247 << " LArPandoraOutput::GetPandoraSlices--- Input slicePfo vector is not empty ";
248
249 // Get the pandora slicing worker - if it exists
250 const pandora::Pandora* pSlicingWorker(nullptr);
251 if (!LArPandoraOutput::GetPandoraInstance(pPrimaryPandora, "SlicingWorker", pSlicingWorker))
252 return;
253
254 // Get the slice PFOs - one PFO per slice
255 const pandora::PfoList* pSlicePfoList(nullptr);
256 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS,
257 !=,
258 PandoraApi::GetCurrentPfoList(*pSlicingWorker, pSlicePfoList));
259
260 slicePfos.insert(slicePfos.end(), pSlicePfoList->begin(), pSlicePfoList->end());
261 }
262
263 //------------------------------------------------------------------------------------------------------------------------------------------
264
266 const pandora::Pandora* const pPrimaryPandora)
267 {
268 pandora::PfoList collectedPfos;
269
270 // Get the list of slice pfos - one per slice
271 pandora::PfoVector slicePfos;
272 LArPandoraOutput::GetPandoraSlices(pPrimaryPandora, slicePfos);
273
274 // Identify the pandora worker instances by their name
275 const pandora::Pandora* pSliceNuWorker(nullptr);
276 if (!LArPandoraOutput::GetPandoraInstance(pPrimaryPandora, "SliceNuWorker", pSliceNuWorker))
277 throw cet::exception("LArPandora")
278 << " LArPandoraOutput::CollectAllPfoOutcomes--- Can't find slice nu worker instance. ";
279
280 const pandora::Pandora* pSliceCRWorker(nullptr);
281 if (!LArPandoraOutput::GetPandoraInstance(pPrimaryPandora, "SliceCRWorker", pSliceCRWorker))
282 throw cet::exception("LArPandora")
283 << " LArPandoraOutput::CollectAllPfoOutcomes--- Can't find slice CR worker instance. ";
284
285 // Collect slices under both reconstruction hypotheses
286 for (unsigned int sliceIndex = 0; sliceIndex < slicePfos.size(); ++sliceIndex) {
287 const pandora::PfoList* pNuPfoList(nullptr);
288 if (pandora::STATUS_CODE_SUCCESS ==
290 *pSliceNuWorker, "NeutrinoParticles3D" + std::to_string(sliceIndex), pNuPfoList))
291 collectedPfos.insert(collectedPfos.end(), pNuPfoList->begin(), pNuPfoList->end());
292
293 const pandora::PfoList* pCRPfoList(nullptr);
294 if (pandora::STATUS_CODE_SUCCESS ==
296 *pSliceCRWorker, "MuonParticles3D" + std::to_string(sliceIndex), pCRPfoList))
297 collectedPfos.insert(collectedPfos.end(), pCRPfoList->begin(), pCRPfoList->end());
298 }
299
300 // Get the list of the parent pfos from the primary pandora instance
301 const pandora::PfoList* pParentPfoList(nullptr);
302 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS,
303 !=,
304 PandoraApi::GetCurrentPfoList(*pPrimaryPandora, pParentPfoList));
305
306 // Collect clear cosmic-rays
307 for (const pandora::ParticleFlowObject* const pPfo : *pParentPfoList) {
308 if (LArPandoraOutput::IsClearCosmic(pPfo)) collectedPfos.push_back(pPfo);
309 }
310
311 // Collect all pfos that are downstream of the parents we have collected
312 pandora::PfoVector pfoVector;
313 LArPandoraOutput::CollectPfos(collectedPfos, pfoVector);
314
315 return pfoVector;
316 }
317
318 //------------------------------------------------------------------------------------------------------------------------------------------
319
321 {
323
324 const auto& properties(pParent->GetPropertiesMap());
325 const auto it(properties.find("IsClearCosmic"));
326
327 if (it == properties.end()) return false;
328
329 return static_cast<bool>(std::round(it->second));
330 }
331
332 //------------------------------------------------------------------------------------------------------------------------------------------
333
335 {
337
338 const auto& properties(pParent->GetPropertiesMap());
339 return (properties.find("SliceIndex") != properties.end());
340 }
341
342 //------------------------------------------------------------------------------------------------------------------------------------------
343
345 {
347
348 const auto& properties(pParent->GetPropertiesMap());
349 const auto it(properties.find("SliceIndex"));
350
351 if (it == properties.end())
352 throw cet::exception("LArPandora")
353 << " LArPandoraOutput::GetSliceIndex--- Input PFO was not from a slice ";
354
355 return static_cast<unsigned int>(std::round(it->second));
356 }
357
358 //------------------------------------------------------------------------------------------------------------------------------------------
359
361 {
362 const pandora::PfoList* pParentPfoList(nullptr);
363 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS,
364 !=,
365 PandoraApi::GetCurrentPfoList(*pPrimaryPandora, pParentPfoList));
366
367 pandora::PfoVector pfoVector;
368 LArPandoraOutput::CollectPfos(*pParentPfoList, pfoVector);
369
370 return pfoVector;
371 }
372
373 //------------------------------------------------------------------------------------------------------------------------------------------
374
376 pandora::PfoVector& pfoVector)
377 {
378 if (!pfoVector.empty())
379 throw cet::exception("LArPandora")
380 << " LArPandoraOutput::CollectPfos--- trying to collect pfos into a non-empty list ";
381
382 pandora::PfoList pfoList;
384
385 pfoVector.insert(pfoVector.end(), pfoList.begin(), pfoList.end());
386 std::sort(pfoVector.begin(), pfoVector.end(), lar_content::LArPfoHelper::SortByNHits);
387 }
388
389 //------------------------------------------------------------------------------------------------------------------------------------------
390
392 const pandora::PfoVector& pfoVector,
393 IdToIdVectorMap& pfoToVerticesMap,
394 std::function<const pandora::Vertex* const(const pandora::ParticleFlowObject* const)> fCriteria)
395 {
396 pandora::VertexVector vertexVector;
397
398 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
399 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
400
401 if (pPfo->GetVertexList().empty()) continue;
402
403 try {
404 const pandora::Vertex* const pVertex(fCriteria(pPfo));
405
406 // Get the vertex ID and add it to the vertex list if required
407 const auto it(std::find(vertexVector.begin(), vertexVector.end(), pVertex));
408 const bool isInList(it != vertexVector.end());
409 const size_t vertexId(isInList ? std::distance(vertexVector.begin(), it) :
410 vertexVector.size());
411
412 if (!isInList) vertexVector.push_back(pVertex);
413
414 if (!pfoToVerticesMap.insert(IdToIdVectorMap::value_type(pfoId, {vertexId})).second)
415 throw cet::exception("LArPandora")
416 << " LArPandoraOutput::CollectVertices --- repeated pfos in input list ";
417 }
418 catch (const pandora::StatusCodeException&) {
419 continue;
420 }
421 }
422
423 return vertexVector;
424 }
425
426 //------------------------------------------------------------------------------------------------------------------------------------------
427
429 IdToIdVectorMap& pfoToClustersMap)
430 {
431 pandora::ClusterList clusterList;
432
433 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
434 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
435
436 // Get the sorted list of clusters from the pfo
437 pandora::ClusterList clusters;
440
441 // Get incrementing id's for each cluster
442 IdVector clusterIds(clusters.size());
443 std::iota(clusterIds.begin(), clusterIds.end(), clusterList.size());
444
445 clusterList.insert(clusterList.end(), clusters.begin(), clusters.end());
446
447 if (!pfoToClustersMap.insert(IdToIdVectorMap::value_type(pfoId, clusterIds)).second)
448 throw cet::exception("LArPandora")
449 << " LArPandoraOutput::CollectClusters --- repeated pfos in input list ";
450 }
451
452 return clusterList;
453 }
454
455 //------------------------------------------------------------------------------------------------------------------------------------------
456
458 IdToIdVectorMap& pfoToThreeDHitsMap)
459 {
460 pandora::CaloHitList caloHitList;
461
462 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
463 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
464
465 if (!pfoToThreeDHitsMap.insert(IdToIdVectorMap::value_type(pfoId, {})).second)
466 throw cet::exception("LArPandora")
467 << " LArPandoraOutput::Collect3DHits --- repeated pfos in input list ";
468
469 pandora::CaloHitVector sorted3DHits;
470 LArPandoraOutput::Collect3DHits(pPfo, sorted3DHits);
471
472 for (const pandora::CaloHit* const pCaloHit3D : sorted3DHits) {
473 if (pandora::TPC_3D !=
474 pCaloHit3D
475 ->GetHitType()) // TODO decide if this is required, or should I just insert them?
476 throw cet::exception("LArPandora")
477 << " LArPandoraOutput::Collect3DHits --- found a 2D hit in a 3D cluster";
478
479 pfoToThreeDHitsMap.at(pfoId).push_back(caloHitList.size());
480 caloHitList.push_back(pCaloHit3D);
481 }
482 }
483
484 return caloHitList;
485 }
486
487 //------------------------------------------------------------------------------------------------------------------------------------------
488
490 pandora::CaloHitVector& caloHits)
491 {
492 // Get the sorted list of 3D hits associated with the pfo
493 pandora::CaloHitList threeDHits;
495
496 caloHits.insert(caloHits.end(), threeDHits.begin(), threeDHits.end());
497 std::sort(caloHits.begin(), caloHits.end(), lar_content::LArClusterHelper::SortHitsByPosition);
498 }
499
500 //------------------------------------------------------------------------------------------------------------------------------------------
501
503 const pandora::CaloHitList& threeDHitList,
504 const IdToHitMap& idToHitMap,
505 CaloHitToArtHitMap& pandoraHitToArtHitMap)
506 {
507 // Collect 2D hits from clusters
508 for (const pandora::Cluster* const pCluster : clusterList) {
510 throw cet::exception("LArPandora")
511 << " LArPandoraOutput::GetPandoraToArtHitMap --- found a 3D input cluster ";
512
513 pandora::CaloHitVector sortedHits;
514 LArPandoraOutput::GetHitsInCluster(pCluster, sortedHits);
515
516 for (const pandora::CaloHit* const pCaloHit : sortedHits) {
517 if (!pandoraHitToArtHitMap
518 .insert(CaloHitToArtHitMap::value_type(
519 pCaloHit, LArPandoraOutput::GetHit(idToHitMap, pCaloHit)))
520 .second)
521 throw cet::exception("LArPandora")
522 << " LArPandoraOutput::GetPandoraToArtHitMap --- found repeated input hits ";
523 }
524 }
525
526 for (const pandora::CaloHit* const pCaloHit : threeDHitList) {
527 if (pCaloHit->GetHitType() != pandora::TPC_3D)
528 throw cet::exception("LArPandora")
529 << " LArPandoraOutput::GetPandoraToArtHitMap --- found a non-3D hit in the input list ";
530
531 // ATTN get the 2D calo hit from the 3D calo hit then find the art hit!
532 if (!pandoraHitToArtHitMap
533 .insert(CaloHitToArtHitMap::value_type(
534 pCaloHit,
536 idToHitMap, static_cast<const pandora::CaloHit*>(pCaloHit->GetParentAddress()))))
537 .second)
538 throw cet::exception("LArPandora")
539 << " LArPandoraOutput::GetPandoraToArtHitMap --- found repeated input hits ";
540 }
541 }
542
543 //------------------------------------------------------------------------------------------------------------------------------------------
544
545 art::Ptr<recob::Hit> LArPandoraOutput::GetHit(const IdToHitMap& idToHitMap,
546 const pandora::CaloHit* const pCaloHit)
547 {
548 // TODO make this less evil
549
550 // ATTN The CaloHit can come from the primary pandora instance (depth = 0) or one of its daughers (depth = 1).
551 // Here we keep trying to access the ART hit increasing the depth step-by-step
552 for (unsigned int depth = 0, maxDepth = 2; depth < maxDepth; ++depth) {
553 // Navigate to the hit address in the pandora master instance (assuming the depth is correct)
554 const pandora::CaloHit* pParentCaloHit = pCaloHit;
555 for (unsigned int i = 0; i < depth; ++i)
556 pParentCaloHit = static_cast<const pandora::CaloHit*>(pCaloHit->GetParentAddress());
557
558 // Attempt to find the mapping from the "parent" calo hit to the ART hit
559 const void* const pHitAddress(pParentCaloHit->GetParentAddress());
560 const intptr_t hitID_temp((intptr_t)(pHitAddress));
561 const int hitID((int)(hitID_temp));
562
563 IdToHitMap::const_iterator artIter = idToHitMap.find(hitID);
564
565 // If there is no such mapping from "parent" calo hit to the ART hit, then increase the depth and try again!
566 if (idToHitMap.end() == artIter) continue;
567
568 return artIter->second;
569 }
570
571 throw cet::exception("LArPandora")
572 << " LArPandoraOutput::GetHit --- found a Pandora hit without a parent ART hit ";
573 }
574
575 //------------------------------------------------------------------------------------------------------------------------------------------
576
578 VertexCollection& outputVertices)
579 {
580 for (size_t vertexId = 0; vertexId < vertexVector.size(); ++vertexId)
581 outputVertices->push_back(LArPandoraOutput::BuildVertex(vertexVector.at(vertexId), vertexId));
582 }
583
584 //------------------------------------------------------------------------------------------------------------------------------------------
585
586 void LArPandoraOutput::BuildSpacePoints(const art::Event& event,
587 const std::string& instanceLabel,
588 const pandora::CaloHitList& threeDHitList,
589 const CaloHitToArtHitMap& pandoraHitToArtHitMap,
590 SpacePointCollection& outputSpacePoints,
591 SpacePointToHitCollection& outputSpacePointsToHits)
592 {
593 pandora::CaloHitVector threeDHitVector;
594 threeDHitVector.insert(threeDHitVector.end(), threeDHitList.begin(), threeDHitList.end());
595
596 for (unsigned int hitId = 0; hitId < threeDHitVector.size(); hitId++) {
597 const pandora::CaloHit* const pCaloHit(threeDHitVector.at(hitId));
598
599 CaloHitToArtHitMap::const_iterator it(pandoraHitToArtHitMap.find(pCaloHit));
600 if (it == pandoraHitToArtHitMap.end())
601 throw cet::exception("LArPandora") << " LArPandoraOutput::BuildSpacePoints --- found a "
602 "pandora hit without a corresponding art hit ";
603
605 event, instanceLabel, hitId, {it->second}, outputSpacePointsToHits);
606 outputSpacePoints->push_back(LArPandoraOutput::BuildSpacePoint(pCaloHit, hitId));
607 }
608 }
609
610 //------------------------------------------------------------------------------------------------------------------------------------------
611
612 void LArPandoraOutput::BuildClusters(const art::Event& event,
613 const std::string& instanceLabel,
614 const pandora::ClusterList& clusterList,
615 const CaloHitToArtHitMap& pandoraHitToArtHitMap,
616 const IdToIdVectorMap& pfoToClustersMap,
617 ClusterCollection& outputClusters,
618 ClusterToHitCollection& outputClustersToHits,
619 IdToIdVectorMap& pfoToArtClustersMap)
620 {
621 cluster::StandardClusterParamsAlg clusterParamAlgo;
622
623 art::ServiceHandle<geo::Geometry const> geom{};
624 auto const clock_data =
625 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
626 auto const det_prop =
627 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(event, clock_data);
628 util::GeometryUtilities const gser{*geom, clock_data, det_prop};
629
630 // Produce the art clusters
631 size_t nextClusterId(0);
632 IdToIdVectorMap pandoraClusterToArtClustersMap;
633 for (const pandora::Cluster* const pCluster : clusterList) {
634 std::vector<HitVector> hitVectors;
635 const std::vector<recob::Cluster> clusters(
637 pCluster,
638 clusterList,
639 pandoraHitToArtHitMap,
640 pandoraClusterToArtClustersMap,
641 hitVectors,
642 nextClusterId,
643 clusterParamAlgo));
644
645 if (hitVectors.size() != clusters.size())
646 throw cet::exception("LArPandora")
647 << " LArPandoraOutput::BuildClusters --- invalid hit vectors for clusters produced ";
648
649 for (unsigned int i = 0; i < clusters.size(); ++i) {
651 event, instanceLabel, nextClusterId - 1, hitVectors.at(i), outputClustersToHits);
652 outputClusters->push_back(clusters.at(i));
653 }
654 }
655
656 // Get mapping from pfo id to art cluster id
657 for (IdToIdVectorMap::const_iterator it = pfoToClustersMap.begin();
658 it != pfoToClustersMap.end();
659 ++it) {
660 if (!pfoToArtClustersMap.insert(IdToIdVectorMap::value_type(it->first, {})).second)
661 throw cet::exception("LArPandora")
662 << " LArPandoraOutput::BuildClusters --- repeated pfo ids ";
663
664 for (const size_t pandoraClusterId : it->second) {
665 IdToIdVectorMap::const_iterator it2(pandoraClusterToArtClustersMap.find(pandoraClusterId));
666
667 if (it2 == pandoraClusterToArtClustersMap.end())
668 throw cet::exception("LArPandora") << " LArPandoraOutput::BuildClusters --- found a "
669 "pandora cluster with no associated recob cluster ";
670
671 for (const size_t recobClusterId : it2->second)
672 pfoToArtClustersMap.at(it->first).push_back(recobClusterId);
673 }
674 }
675 }
676
677 //------------------------------------------------------------------------------------------------------------------------------------------
678
680 const art::Event& event,
681 const std::string& instanceLabel,
682 const pandora::PfoVector& pfoVector,
683 const IdToIdVectorMap& pfoToVerticesMap,
684 const IdToIdVectorMap& pfoToThreeDHitsMap,
685 const IdToIdVectorMap& pfoToArtClustersMap,
686 PFParticleCollection& outputParticles,
687 PFParticleToVertexCollection& outputParticlesToVertices,
688 PFParticleToSpacePointCollection& outputParticlesToSpacePoints,
689 PFParticleToClusterCollection& outputParticlesToClusters)
690 {
691 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
692 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
693
694 outputParticles->push_back(LArPandoraOutput::BuildPFParticle(pPfo, pfoId, pfoVector));
695
696 // Associations from PFParticle
697 if (pfoToVerticesMap.find(pfoId) != pfoToVerticesMap.end())
699 event, instanceLabel, pfoId, pfoToVerticesMap, outputParticlesToVertices);
700
701 if (pfoToThreeDHitsMap.find(pfoId) != pfoToThreeDHitsMap.end())
703 event, instanceLabel, pfoId, pfoToThreeDHitsMap, outputParticlesToSpacePoints);
704
705 if (pfoToArtClustersMap.find(pfoId) != pfoToArtClustersMap.end())
707 event, instanceLabel, pfoId, pfoToArtClustersMap, outputParticlesToClusters);
708 }
709 }
710
711 //------------------------------------------------------------------------------------------------------------------------------------------
712
714 const art::Event& event,
715 const std::string& instanceLabel,
716 const pandora::PfoVector& pfoVector,
717 const IdToIdVectorMap& pfoToVerticesMap,
718 PFParticleToVertexCollection& outputParticlesToVertices)
719 {
720 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
721 if (pfoToVerticesMap.find(pfoId) != pfoToVerticesMap.end())
723 event, instanceLabel, pfoId, pfoToVerticesMap, outputParticlesToVertices);
724 }
725 }
726
727 //------------------------------------------------------------------------------------------------------------------------------------------
728
730 const art::Event& event,
731 const std::string& instanceLabel,
732 const pandora::PfoVector& pfoVector,
733 PFParticleMetadataCollection& outputParticleMetadata,
734 PFParticleToMetadataCollection& outputParticlesToMetadata)
735 {
736 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
737 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
738
740 event, instanceLabel, pfoId, outputParticleMetadata->size(), outputParticlesToMetadata);
741 larpandoraobj::PFParticleMetadata pPFParticleMetadata(
743 outputParticleMetadata->push_back(pPFParticleMetadata);
744 }
745 }
746
747 //------------------------------------------------------------------------------------------------------------------------------------------
748
750 const pandora::Pandora* const pPrimaryPandora,
751 const art::Event& event,
752 const std::string& instanceLabel,
753 const pandora::PfoVector& pfoVector,
754 const IdToHitMap& idToHitMap,
755 SliceCollection& outputSlices,
756 PFParticleToSliceCollection& outputParticlesToSlices,
757 SliceToHitCollection& outputSlicesToHits)
758 {
759 // Check for the special case in which there are no slices, and only the neutrino reconstruction was used on all hits
760 if (settings.m_isNeutrinoRecoOnlyNoSlicing) {
762 event,
763 instanceLabel,
764 pfoVector,
765 idToHitMap,
766 outputSlices,
767 outputParticlesToSlices,
768 outputSlicesToHits);
769 return;
770 }
771
772 // Collect the slice pfos - one per slice (if there is no slicing instance, this vector will be empty)
773 pandora::PfoVector slicePfos;
774 LArPandoraOutput::GetPandoraSlices(pPrimaryPandora, slicePfos);
775
776 // Make one slice per Pandora Slice pfo
777 for (const pandora::ParticleFlowObject* const pSlicePfo : slicePfos)
779 pSlicePfo, event, instanceLabel, idToHitMap, outputSlices, outputSlicesToHits);
780
781 // Make a slice for every remaining pfo hierarchy that wasn't already in a slice
782 std::unordered_map<const pandora::ParticleFlowObject*, unsigned int> parentPfoToSliceIndexMap;
783 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
784 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
785
786 // If this PFO is the parent of a hierarchy we have yet to use, then add a new slice
787 if (LArPandoraOutput::IsFromSlice(pPfo)) continue;
788
789 if (lar_content::LArPfoHelper::GetParentPfo(pPfo) != pPfo) continue;
790
791 if (!parentPfoToSliceIndexMap
792 .emplace(pPfo,
794 pPfo, event, instanceLabel, idToHitMap, outputSlices, outputSlicesToHits))
795 .second)
796 throw cet::exception("LArPandora")
797 << " LArPandoraOutput::BuildSlices --- found repeated primary particles ";
798 }
799
800 // Add the associations from PFOs to slices
801 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
802 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
803
804 // For PFOs that are from a Pandora slice, add the association and move on to the next PFO
807 instanceLabel,
808 pfoId,
810 outputParticlesToSlices);
811 continue;
812 }
813
814 // Get the parent of the particle
815 const pandora::ParticleFlowObject* const pParent(
817 if (parentPfoToSliceIndexMap.find(pParent) == parentPfoToSliceIndexMap.end())
818 throw cet::exception("LArPandora")
819 << " LArPandoraOutput::BuildSlices --- found pfo without a parent in the input list ";
820
821 // Add the association from the PFO to the slice
823 event, instanceLabel, pfoId, parentPfoToSliceIndexMap.at(pParent), outputParticlesToSlices);
824 }
825 }
826
827 //------------------------------------------------------------------------------------------------------------------------------------------
828
830 {
831 // Make a slice with dummy properties
832 const float bogusFloat(std::numeric_limits<float>::max());
833 const recob::tracking::Point_t bogusPoint(bogusFloat, bogusFloat, bogusFloat);
834 const recob::tracking::Vector_t bogusVector(bogusFloat, bogusFloat, bogusFloat);
835
836 const unsigned int sliceIndex(outputSlices->size());
837 outputSlices->emplace_back(
838 sliceIndex, bogusPoint, bogusVector, bogusPoint, bogusPoint, bogusFloat, bogusFloat);
839
840 return sliceIndex;
841 }
842
843 //------------------------------------------------------------------------------------------------------------------------------------------
844
846 const Settings& settings,
847 const art::Event& event,
848 const std::string& instanceLabel,
849 const pandora::PfoVector& pfoVector,
850 const IdToHitMap& idToHitMap,
851 SliceCollection& outputSlices,
852 PFParticleToSliceCollection& outputParticlesToSlices,
853 SliceToHitCollection& outputSlicesToHits)
854 {
855 const unsigned int sliceIndex(LArPandoraOutput::BuildDummySlice(outputSlices));
856
857 // Add all of the hits in the events to the slice
858 HitVector hits;
860 LArPandoraOutput::AddAssociation(event, instanceLabel, sliceIndex, hits, outputSlicesToHits);
861
862 mf::LogDebug("LArPandora") << "Finding hits with label: " << settings.m_hitfinderModuleLabel
863 << std::endl;
864 mf::LogDebug("LArPandora") << " - Found " << hits.size() << std::endl;
865 mf::LogDebug("LArPandora") << " - Making associations " << outputSlicesToHits->size()
866 << std::endl;
867
868 // Add all of the PFOs to the slice
869 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId)
871 event, instanceLabel, pfoId, sliceIndex, outputParticlesToSlices);
872 }
873
874 //------------------------------------------------------------------------------------------------------------------------------------------
875
876 unsigned int LArPandoraOutput::BuildSlice(const pandora::ParticleFlowObject* const pParentPfo,
877 const art::Event& event,
878 const std::string& instanceLabel,
879 const IdToHitMap& idToHitMap,
880 SliceCollection& outputSlices,
881 SliceToHitCollection& outputSlicesToHits)
882 {
883 const unsigned int sliceIndex(LArPandoraOutput::BuildDummySlice(outputSlices));
884
885 // Collect the pfos connected to the input primary pfos
886 pandora::PfoList pfosInSlice;
887 lar_content::LArPfoHelper::GetAllConnectedPfos(pParentPfo, pfosInSlice);
889
890 // Collect the hits from the pfos in all views
892 for (const pandora::ParticleFlowObject* const pPfo : pfosInSlice) {
893 for (const pandora::HitType& hitType :
895 lar_content::LArPfoHelper::GetCaloHits(pPfo, hitType, hits);
897 }
898 }
899
900 // Add the associations to the hits
901 for (const pandora::CaloHit* const pCaloHit : hits)
903 instanceLabel,
904 sliceIndex,
905 {LArPandoraOutput::GetHit(idToHitMap, pCaloHit)},
906 outputSlicesToHits);
907
908 return sliceIndex;
909 }
910
911 //------------------------------------------------------------------------------------------------------------------------------------------
912
913 void LArPandoraOutput::BuildT0s(const art::Event& event,
914 const std::string& instanceLabel,
915 const pandora::PfoVector& pfoVector,
916 T0Collection& outputT0s,
917 PFParticleToT0Collection& outputParticlesToT0s)
918 {
919 size_t nextT0Id(0);
920 for (unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
921 const pandora::ParticleFlowObject* const pPfo(pfoVector.at(pfoId));
922
923 anab::T0 t0;
924 if (!LArPandoraOutput::BuildT0(event, pPfo, pfoVector, nextT0Id, t0)) continue;
925
927 event, instanceLabel, pfoId, nextT0Id - 1, outputParticlesToT0s);
928 outputT0s->push_back(t0);
929 }
930 }
931
932 //------------------------------------------------------------------------------------------------------------------------------------------
933
935 const size_t pfoId,
936 const pandora::PfoVector& pfoVector)
937 {
938 // Get parent Pfo ID
939 const pandora::PfoList& parentList(pPfo->GetParentPfoList());
940 if (parentList.size() > 1)
941 throw cet::exception("LArPandora")
942 << " LArPandoraOutput::BuildPFParticle --- this pfo has multiple parent particles ";
943
944 const size_t parentId(parentList.empty() ?
945 recob::PFParticle::kPFParticlePrimary :
946 LArPandoraOutput::GetId(parentList.front(), pfoVector));
947
948 // Get daughters Pfo IDs
949 std::vector<size_t> daughterIds;
950 for (const pandora::ParticleFlowObject* const pDaughterPfo : pPfo->GetDaughterPfoList())
951 daughterIds.push_back(LArPandoraOutput::GetId(pDaughterPfo, pfoVector));
952
953 std::sort(daughterIds.begin(), daughterIds.end());
954
955 return recob::PFParticle(pPfo->GetParticleId(), pfoId, parentId, daughterIds);
956 }
957
958 //------------------------------------------------------------------------------------------------------------------------------------------
959
960 recob::Vertex LArPandoraOutput::BuildVertex(const pandora::Vertex* const pVertex,
961 const size_t vertexId)
962 {
963 double pos[3] = {
964 pVertex->GetPosition().GetX(), pVertex->GetPosition().GetY(), pVertex->GetPosition().GetZ()};
965 return recob::Vertex(pos, vertexId);
966 }
967
968 //------------------------------------------------------------------------------------------------------------------------------------------
969
971 pandora::CaloHitVector& sortedHits)
972 {
973 if (!sortedHits.empty())
974 throw cet::exception("LArPandora")
975 << " LArPandoraOutput::GetHitsInCluster --- vector to hold hits is not empty ";
976
977 pandora::CaloHitList hitList;
978 pCluster->GetOrderedCaloHitList().FillCaloHitList(hitList);
979 hitList.insert(hitList.end(),
980 pCluster->GetIsolatedCaloHitList().begin(),
981 pCluster->GetIsolatedCaloHitList().end());
982
983 sortedHits.insert(sortedHits.end(), hitList.begin(), hitList.end());
984 std::sort(
985 sortedHits.begin(), sortedHits.end(), lar_content::LArClusterHelper::SortHitsByPosition);
986 }
987
988 //------------------------------------------------------------------------------------------------------------------------------------------
989
990 std::vector<recob::Cluster> LArPandoraOutput::BuildClusters(
991 util::GeometryUtilities const& gser,
992 const pandora::Cluster* const pCluster,
993 const pandora::ClusterList& clusterList,
994 const CaloHitToArtHitMap& pandoraHitToArtHitMap,
995 IdToIdVectorMap& pandoraClusterToArtClustersMap,
996 std::vector<HitVector>& hitVectors,
997 size_t& nextId,
998 cluster::ClusterParamsAlgBase& algo)
999 {
1000 std::vector<recob::Cluster> clusters;
1001
1002 // Get the cluster ID and set up the map entry
1003 const size_t clusterId(LArPandoraOutput::GetId(pCluster, clusterList));
1004 if (!pandoraClusterToArtClustersMap.insert(IdToIdVectorMap::value_type(clusterId, {})).second)
1005 throw cet::exception("LArPandora")
1006 << " LArPandoraOutput::BuildClusters --- repeated clusters in input list ";
1007
1008 pandora::CaloHitVector sortedHits;
1009 LArPandoraOutput::GetHitsInCluster(pCluster, sortedHits);
1010
1011 HitArray hitArray; // hits organised by drift volume
1012 HitList isolatedHits;
1013
1014 for (const pandora::CaloHit* const pCaloHit2D : sortedHits) {
1015 CaloHitToArtHitMap::const_iterator it(pandoraHitToArtHitMap.find(pCaloHit2D));
1016 if (it == pandoraHitToArtHitMap.end())
1017 throw cet::exception("LArPandora")
1018 << " LArPandoraOutput::BuildClusters --- couldn't find art hit for input pandora hit ";
1019
1020 const art::Ptr<recob::Hit> hit(it->second);
1021
1022 const geo::WireID wireID(hit->WireID());
1023 const unsigned int volID(100000 * wireID.Cryostat + wireID.TPC);
1024 hitArray[volID].push_back(hit);
1025
1026 if (pCaloHit2D->IsIsolated()) isolatedHits.insert(hit);
1027 }
1028
1029 if (hitArray.empty())
1030 throw cet::exception("LArPandora")
1031 << " LArPandoraOutput::BuildClusters --- found a cluster with no hits ";
1032
1033 for (const HitArray::value_type& hitArrayEntry : hitArray) {
1034 const HitVector& clusterHits(hitArrayEntry.second);
1035
1036 clusters.push_back(
1037 LArPandoraOutput::BuildCluster(gser, nextId, clusterHits, isolatedHits, algo));
1038 hitVectors.push_back(clusterHits);
1039 pandoraClusterToArtClustersMap.at(clusterId).push_back(nextId);
1040
1041 nextId++;
1042 }
1043
1044 return clusters;
1045 }
1046
1047 //------------------------------------------------------------------------------------------------------------------------------------------
1048
1049 recob::Cluster LArPandoraOutput::BuildCluster(util::GeometryUtilities const& gser,
1050 const size_t id,
1051 const HitVector& hitVector,
1052 const HitList& isolatedHits,
1053 cluster::ClusterParamsAlgBase& algo)
1054 {
1055 if (hitVector.empty())
1056 throw cet::exception("LArPandora")
1057 << " LArPandoraOutput::BuildCluster --- No input hits were provided ";
1058
1059 // Fill list of cluster properties
1060 geo::View_t view(geo::kUnknown);
1061 geo::PlaneID planeID;
1062
1063 double startWire(+std::numeric_limits<float>::max()), sigmaStartWire(0.0);
1064 double startTime(+std::numeric_limits<float>::max()), sigmaStartTime(0.0);
1065 double endWire(-std::numeric_limits<float>::max()), sigmaEndWire(0.0);
1066 double endTime(-std::numeric_limits<float>::max()), sigmaEndTime(0.0);
1067
1068 std::vector<recob::Hit const*> hits_for_params;
1069 hits_for_params.reserve(hitVector.size());
1070
1071 for (const art::Ptr<recob::Hit>& hit : hitVector) {
1072 const double thisWire(hit->WireID().Wire);
1073 const double thisWireSigma(0.5);
1074 const double thisTime(hit->PeakTime());
1075 const double thisTimeSigma(double(2. * hit->RMS()));
1076 const geo::View_t thisView(hit->View());
1077 const geo::PlaneID thisPlaneID(hit->WireID().planeID());
1078
1079 if (geo::kUnknown == view) {
1080 view = thisView;
1081 planeID = thisPlaneID;
1082 }
1083
1084 if (!(thisView == view && thisPlaneID == planeID)) {
1085 throw cet::exception("LArPandora")
1086 << " LArPandoraOutput::BuildCluster --- Input hits have inconsistent plane IDs ";
1087 }
1088
1089 hits_for_params.push_back(&*hit);
1090
1091 if (isolatedHits.count(hit)) continue;
1092
1093 if (thisWire < startWire || (thisWire == startWire && thisTime < startTime)) {
1094 startWire = thisWire;
1095 sigmaStartWire = thisWireSigma;
1096 startTime = thisTime;
1097 sigmaStartTime = thisTimeSigma;
1098 }
1099
1100 if (thisWire > endWire || (thisWire == endWire && thisTime > endTime)) {
1101 endWire = thisWire;
1102 sigmaEndWire = thisWireSigma;
1103 endTime = thisTime;
1104 sigmaEndTime = thisTimeSigma;
1105 }
1106 }
1107
1108 // feed the algorithm with all the cluster hits
1109 algo.SetHits(gser, hits_for_params);
1110
1111 // create the recob::Cluster directly in the vector
1112 return cluster::ClusterCreator(gser,
1113 algo, // algo
1114 startWire, // start_wire
1115 sigmaStartWire, // sigma_start_wire
1116 startTime, // start_tick
1117 sigmaStartTime, // sigma_start_tick
1118 endWire, // end_wire
1119 sigmaEndWire, // sigma_end_wire
1120 endTime, // end_tick
1121 sigmaEndTime, // sigma_end_tick
1122 id, // ID
1123 view, // view
1124 planeID, // plane
1125 recob::Cluster::Sentry // sentry
1126 )
1127 .move();
1128 }
1129
1130 //------------------------------------------------------------------------------------------------------------------------------------------
1131
1132 recob::SpacePoint LArPandoraOutput::BuildSpacePoint(const pandora::CaloHit* const pCaloHit,
1133 const size_t spacePointId)
1134 {
1135 if (pandora::TPC_3D != pCaloHit->GetHitType())
1136 throw cet::exception("LArPandora")
1137 << " LArPandoraOutput::BuildSpacePoint --- trying to build a space point from a 2D hit";
1138
1139 const pandora::CartesianVector point(pCaloHit->GetPositionVector());
1140 double xyz[3] = {point.GetX(), point.GetY(), point.GetZ()};
1141
1142 // ATTN using dummy information
1143 double dxdydz[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // TODO: Fill in the error matrix
1144 double chi2(0.0);
1145
1146 return recob::SpacePoint(xyz, dxdydz, chi2, spacePointId);
1147 }
1148
1149 //------------------------------------------------------------------------------------------------------------------------------------------
1150
1151 bool LArPandoraOutput::BuildT0(const art::Event& e,
1152 const pandora::ParticleFlowObject* const pPfo,
1153 const pandora::PfoVector& pfoVector,
1154 size_t& nextId,
1155 anab::T0& t0)
1156 {
1158 const float x0(pParent->GetPropertiesMap().count("X0") ? pParent->GetPropertiesMap().at("X0") :
1159 0.f);
1160
1161 auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
1162 auto const det_prop =
1163 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e, clock_data);
1164 const double cm_per_tick(det_prop.GetXTicksCoefficient());
1165 const double ns_per_tick(sampling_rate(clock_data));
1166
1167 // ATTN: T0 values are currently calculated in nanoseconds relative to the trigger offset. Only non-zero values are outputted.
1168 const double T0(x0 * ns_per_tick / cm_per_tick);
1169
1170 if (std::fabs(T0) <= std::numeric_limits<double>::epsilon()) return false;
1171
1172 // Output T0 objects [arguments are: time (nanoseconds); trigger type (3 for TPC stitching!); pfparticle SelfID code; T0 ID code]
1173 t0 = anab::T0(T0, 3, LArPandoraOutput::GetId(pPfo, pfoVector), nextId++);
1174
1175 return true;
1176 }
1177
1178 //------------------------------------------------------------------------------------------------------------------------------------------
1179 //------------------------------------------------------------------------------------------------------------------------------------------
1180
1182 : m_pPrimaryPandora(nullptr)
1183 , m_shouldRunStitching(false)
1184 , m_shouldProduceAllOutcomes(false)
1185 , m_shouldProduceTestBeamInteractionVertices(false)
1186 , m_isNeutrinoRecoOnlyNoSlicing(false)
1187 {}
1188
1189 //------------------------------------------------------------------------------------------------------------------------------------------
1190
1192 {
1193 if (!m_pPrimaryPandora)
1194 throw cet::exception("LArPandora")
1195 << " LArPandoraOutput::Settings::Validate --- primary Pandora instance does not exist ";
1196
1197 if (!m_shouldProduceAllOutcomes) return;
1198
1199 if (m_allOutcomesInstanceLabel.empty())
1200 throw cet::exception("LArPandora")
1201 << " LArPandoraOutput::Settings::Validate --- all outcomes instance label not set ";
1202 }
1203
1204} // namespace lar_pandora
Header file for the calo hit class.
Header file for the cluster class.
Header file for the cluster helper class.
Helper functions for processing outputs from pandora.
Header file for the pfo helper class.
Header file for the MultiPandoraApi class.
Header file for the particle flow object class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
Header file for the vertex class.
static const PandoraInstanceList & GetDaughterPandoraInstanceList(const pandora::Pandora *const pPrimaryPandora)
Get the list of daughter pandora instances associated with a given primary pandora instance.
static pandora::StatusCode GetPfoList(const pandora::Pandora &pandora, const std::string &pfoListName, const pandora::PfoList *&pPfoList)
Get a named pfo list.
Definition PandoraApi.cc:92
static pandora::StatusCode GetCurrentPfoList(const pandora::Pandora &pandora, const pandora::PfoList *&pPfoList)
Get the current pfo list.
Definition PandoraApi.cc:84
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position,...
static void GetAllConnectedPfos(const pandora::PfoList &inputPfoList, pandora::PfoList &outputPfoList)
Get a flat list of all pfos, recursively including all daughters and parents associated with those pf...
static const pandora::ParticleFlowObject * GetParentPfo(const pandora::ParticleFlowObject *const pPfo)
Get the primary parent pfo.
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
static void GetIsolatedCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of isolated calo hits of a particular hit type from a list of pfos.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
static const pandora::Vertex * GetTestBeamInteractionVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo test beam interaction vertex.
static void GetCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of calo hits of a particular hit type from a list of pfos.
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
static void CollectHits(const art::Event &evt, const std::string &label, HitVector &hitVector)
Collect the reconstructed Hits from the ART event record.
static larpandoraobj::PFParticleMetadata GetPFParticleMetadata(const pandora::ParticleFlowObject *const pPfo)
Get metadata associated to a PFO.
void Validate() const
Check the parameters and throw an exception if they are not valid.
std::string m_testBeamInteractionVerticesInstanceLabel
The label for the test beam interaction vertices.
std::string m_allOutcomesInstanceLabel
The label for the instance producing all outcomes.
std::string m_hitfinderModuleLabel
The hit finder module label.
bool m_shouldProduceTestBeamInteractionVertices
Whether to write the test beam interaction vertices in a separate collection.
bool m_isNeutrinoRecoOnlyNoSlicing
If we are running the neutrino reconstruction only with no slicing.
bool m_shouldProduceAllOutcomes
If all outcomes should be produced in separate collections (choose false if you only require the cons...
const pandora::Pandora * m_pPrimaryPandora
bool m_shouldProduceSlices
Whether to produce output slices e.g. may not want to do this if only (re)processing single slices.
static pandora::VertexVector CollectVertices(const pandora::PfoVector &pfoVector, IdToIdVectorMap &pfoToVerticesMap, std::function< const pandora::Vertex *const(const pandora::ParticleFlowObject *const)> fCriteria)
Collect all vertices contained in the input pfo list Order is guaranteed provided pfoVector is ordere...
std::unique_ptr< art::Assns< recob::PFParticle, recob::Cluster > > PFParticleToClusterCollection
static void AssociateAdditionalVertices(const art::Event &event, const std::string &instanceLabel, const pandora::PfoVector &pfoVector, const IdToIdVectorMap &pfoToVerticesMap, PFParticleToVertexCollection &outputParticlesToVertices)
Convert Create the associations between pre-existing PFParticle and additional vertices.
static void AddAssociation(const art::Event &event, const std::string &instanceLabel, const size_t idA, const size_t idB, std::unique_ptr< art::Assns< A, B > > &association)
Add an association between objects with two given ids.
static bool IsClearCosmic(const pandora::ParticleFlowObject *const pPfo)
Check if the input pfo is an unambiguous cosmic ray.
std::unique_ptr< art::Assns< recob::PFParticle, recob::Vertex > > PFParticleToVertexCollection
static recob::Cluster BuildCluster(util::GeometryUtilities const &gser, const size_t id, const HitVector &hitVector, const HitList &isolatedHits, cluster::ClusterParamsAlgBase &algo)
Build an ART cluster from an input vector of ART hits.
static void ProduceArtOutput(const Settings &settings, const IdToHitMap &idToHitMap, art::Event &evt)
Convert the Pandora PFOs into ART clusters and write into ART event.
std::unique_ptr< art::Assns< recob::PFParticle, recob::SpacePoint > > PFParticleToSpacePointCollection
static void GetHitsInCluster(const pandora::Cluster *const pCluster, pandora::CaloHitVector &sortedHits)
Collect a sorted list of all 2D hits in a cluster.
std::unique_ptr< std::vector< recob::Cluster > > ClusterCollection
static art::Ptr< recob::Hit > GetHit(const IdToHitMap &idToHitMap, const pandora::CaloHit *const pCaloHit)
Look up ART hit from an input Pandora hit.
static void BuildT0s(const art::Event &event, const std::string &instanceLabel, const pandora::PfoVector &pfoVector, T0Collection &outputT0s, PFParticleToT0Collection &outputParticlesToT0s)
Calculate the T0 of each pfos and add them to the output vector Create the associations between PFPar...
std::unique_ptr< art::Assns< recob::Cluster, recob::Hit > > ClusterToHitCollection
std::unique_ptr< std::vector< larpandoraobj::PFParticleMetadata > > PFParticleMetadataCollection
std::unique_ptr< std::vector< recob::Slice > > SliceCollection
static void CopyAllHitsToSingleSlice(const Settings &settings, const art::Event &event, const std::string &instanceLabel, const pandora::PfoVector &pfoVector, const IdToHitMap &idToHitMap, SliceCollection &outputSlices, PFParticleToSliceCollection &outputParticlesToSlices, SliceToHitCollection &outputSlicesToHits)
Ouput a single slice containing all of the input hits.
static pandora::PfoVector CollectPfos(const pandora::Pandora *const pPrimaryPandora)
Collect the current pfos (including all downstream pfos) from the master pandora instance.
static pandora::ClusterList CollectClusters(const pandora::PfoVector &pfoVector, IdToIdVectorMap &pfoToClustersMap)
Collect a sorted list of all 2D clusters contained in the input pfo list Order is guaranteed provided...
static recob::PFParticle BuildPFParticle(const pandora::ParticleFlowObject *const pPfo, const size_t pfoId, const pandora::PfoVector &pfoVector)
Convert from a pfo to and ART PFParticle.
static void BuildSlices(const Settings &settings, const pandora::Pandora *const pPrimaryPandora, const art::Event &event, const std::string &instanceLabel, const pandora::PfoVector &pfoVector, const IdToHitMap &idToHitMap, SliceCollection &outputSlices, PFParticleToSliceCollection &outputParticlesToSlices, SliceToHitCollection &outputSlicesToHits)
Build slices - collections of hits which each describe a single particle hierarchy.
std::unique_ptr< std::vector< recob::PFParticle > > PFParticleCollection
static unsigned int BuildDummySlice(SliceCollection &outputSlices)
Build a new slice object with dummy information.
static bool GetPandoraInstance(const pandora::Pandora *const pPrimaryPandora, const std::string &name, const pandora::Pandora *&pPandoraInstance)
Get the address of a pandora instance with a given name.
static recob::SpacePoint BuildSpacePoint(const pandora::CaloHit *const pCaloHit, const size_t spacePointId)
Convert from a pandora 3D hit to an ART spacepoint.
std::map< size_t, IdVector > IdToIdVectorMap
static bool IsFromSlice(const pandora::ParticleFlowObject *const pPfo)
Check if the input pfo is from a slice.
static void Collect3DHits(const pandora::ParticleFlowObject *const pPfo, pandora::CaloHitVector &caloHits)
Collect a sorted vector of all 3D hits in the input pfo.
std::unique_ptr< std::vector< recob::SpacePoint > > SpacePointCollection
static void GetPandoraToArtHitMap(const pandora::ClusterList &clusterList, const pandora::CaloHitList &threeDHitList, const IdToHitMap &idToHitMap, CaloHitToArtHitMap &pandoraHitToArtHitMap)
Collect all 2D and 3D hits that were used / produced in the reconstruction and map them to their corr...
static void BuildPFParticles(const art::Event &event, const std::string &instanceLabel, const pandora::PfoVector &pfoVector, const IdToIdVectorMap &pfoToVerticesMap, const IdToIdVectorMap &pfoToThreeDHitsMap, const IdToIdVectorMap &pfoToArtClustersMap, PFParticleCollection &outputParticles, PFParticleToVertexCollection &outputParticlesToVertices, PFParticleToSpacePointCollection &outputParticlesToSpacePoints, PFParticleToClusterCollection &outputParticlesToClusters)
Convert between pfos and PFParticles and add them to the output vector Create the associations betwee...
static void BuildVertices(const pandora::VertexVector &vertexVector, VertexCollection &outputVertices)
Convert pandora vertices to ART vertices and add them to the output vector.
static void BuildSpacePoints(const art::Event &event, const std::string &instanceLabel, const pandora::CaloHitList &threeDHitList, const CaloHitToArtHitMap &pandoraHitToArtHitMap, SpacePointCollection &outputSpacePoints, SpacePointToHitCollection &outputSpacePointsToHits)
Convert pandora 3D hits to ART spacepoints and add them to the output vector Create the associations ...
std::unique_ptr< std::vector< recob::Vertex > > VertexCollection
static void GetPandoraSlices(const pandora::Pandora *const pPrimaryPandora, pandora::PfoVector &slicePfos)
Get the slice pfos - one pfo per slice.
std::unique_ptr< art::Assns< recob::PFParticle, recob::Slice > > PFParticleToSliceCollection
static unsigned int BuildSlice(const pandora::ParticleFlowObject *const pParentPfo, const art::Event &event, const std::string &instanceLabel, const IdToHitMap &idToHitMap, SliceCollection &outputSlices, SliceToHitCollection &outputSlicesToHits)
Build a new slice object from a PFO, this can be a top-level parent in a hierarchy or a "slice PFO" f...
static size_t GetId(const T *const pT, const std::list< const T * > &tList)
Find the index of an input object in an input list. Throw an exception if it doesn't exist.
std::vector< size_t > IdVector
std::unique_ptr< art::Assns< recob::Slice, recob::Hit > > SliceToHitCollection
static unsigned int GetSliceIndex(const pandora::ParticleFlowObject *const pPfo)
Get the index of the slice from which this pfo was produced.
static pandora::PfoVector CollectAllPfoOutcomes(const pandora::Pandora *const pPrimaryPandora)
Collect the pfos (including all downstream pfos) from the master and daughter pandora instances.
static recob::Vertex BuildVertex(const pandora::Vertex *const pVertex, const size_t vertexId)
Convert from a pandora vertex to an ART vertex.
static void BuildParticleMetadata(const art::Event &event, const std::string &instanceLabel, const pandora::PfoVector &pfoVector, PFParticleMetadataCollection &outputParticleMetadata, PFParticleToMetadataCollection &outputParticlesToMetadata)
Build metadata objects from a list of input pfos.
std::unique_ptr< std::vector< anab::T0 > > T0Collection
std::unique_ptr< art::Assns< recob::PFParticle, larpandoraobj::PFParticleMetadata > > PFParticleToMetadataCollection
static void BuildClusters(const art::Event &event, const std::string &instanceLabel, const pandora::ClusterList &clusterList, const CaloHitToArtHitMap &pandoraHitToArtHitMap, const IdToIdVectorMap &pfoToClustersMap, ClusterCollection &outputClusters, ClusterToHitCollection &outputClustersToHits, IdToIdVectorMap &pfoToArtClustersMap)
Convert pandora 2D clusters to ART clusters and add them to the output vector Create the associations...
std::unique_ptr< art::Assns< recob::SpacePoint, recob::Hit > > SpacePointToHitCollection
std::unique_ptr< art::Assns< recob::PFParticle, anab::T0 > > PFParticleToT0Collection
static bool BuildT0(const art::Event &event, const pandora::ParticleFlowObject *const pPfo, const pandora::PfoVector &pfoVector, size_t &nextId, anab::T0 &t0)
If required, build a T0 for the input pfo.
std::map< const pandora::CaloHit *, art::Ptr< recob::Hit > > CaloHitToArtHitMap
CaloHit class.
Definition CaloHit.h:26
HitType GetHitType() const
Get the calorimeter hit type.
Definition CaloHit.h:441
const CartesianVector & GetPositionVector() const
Get the position vector of center of calorimeter cell, units mm.
Definition CaloHit.h:350
const void * GetParentAddress() const
Get the address of the parent calo hit in the user framework.
Definition CaloHit.h:532
CartesianVector class.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetY() const
Get the cartesian y coordinate.
Cluster class.
Definition Cluster.h:31
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
Definition Cluster.h:470
const CaloHitList & GetIsolatedCaloHitList() const
Get the isolated calo hit list.
Definition Cluster.h:477
void FillCaloHitList(CaloHitList &caloHitList) const
Fill a provided calo hit list with all the calo hits in the ordered calo hit list.
Pandora class.
Definition Pandora.h:40
ParticleFlowObject class.
const PropertiesMap & GetPropertiesMap() const
Get the map from registered property name to floating point property value.
const PfoList & GetDaughterPfoList() const
Get the daughter pfo list.
const PfoList & GetParentPfoList() const
Get the parent pfo list.
const VertexList & GetVertexList() const
Get the vertex list.
int GetParticleId() const
Get the particle flow object id (PDG code)
StatusCodeException class.
Vertex class.
Definition Vertex.h:26
const CartesianVector & GetPosition() const
Get the vertex position.
Definition Vertex.h:103
std::vector< art::Ptr< recob::Hit > > HitVector
std::map< int, art::Ptr< recob::Hit > > IdToHitMap
Definition ILArPandora.h:24
std::set< art::Ptr< recob::Hit > > HitList
std::map< int, HitVector > HitArray
HitType
Calorimeter hit type enum.
std::vector< const CaloHit * > CaloHitVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< const ParticleFlowObject * > PfoVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList
std::vector< const Vertex * > VertexVector