9 #include "art/Framework/Principal/Event.h"
10 #include "cetlib_except/exception.h"
11 #include "messagefacility/MessageLogger/MessageLogger.h"
24 #include "Objects/CaloHit.h"
25 #include "Objects/Cluster.h"
26 #include "Objects/ParticleFlowObject.h"
27 #include "Objects/Vertex.h"
39 namespace lar_pandora {
47 const std::string instanceLabel(
49 const std::string testBeamInteractionVertexInstanceLabel(
58 new std::vector<larpandoraobj::PFParticleMetadata>);
70 new art::Assns<recob::PFParticle, larpandoraobj::PFParticleMetadata>);
72 new art::Assns<recob::PFParticle, recob::SpacePoint>);
74 new art::Assns<recob::PFParticle, recob::Cluster>);
76 new art::Assns<recob::PFParticle, recob::Vertex>);
79 new art::Assns<recob::SpacePoint, recob::Hit>);
85 new art::Assns<recob::PFParticle, recob::Vertex> :
93 const pandora::PfoVector pfoVector(
104 pfoToTestBeamInteractionVerticesMap,
109 const pandora::ClusterList clusterList(
113 const pandora::CaloHitList threeDHitList(
119 clusterList, threeDHitList, idToHitMap, pandoraHitToArtHitMap);
126 outputTestBeamInteractionVertices);
131 pandoraHitToArtHitMap,
133 outputSpacePointsToHits);
139 pandoraHitToArtHitMap,
142 outputClustersToHits,
143 pfoToArtClustersMap);
152 outputParticlesToVertices,
153 outputParticlesToSpacePoints,
154 outputParticlesToClusters);
157 evt, instanceLabel, pfoVector, outputParticleMetadata, outputParticlesToMetadata);
167 outputParticlesToSlices,
177 pfoToTestBeamInteractionVerticesMap,
178 outputParticlesToTestBeamInteractionVertices);
181 evt.put(std::move(outputParticles), instanceLabel);
182 evt.put(std::move(outputSpacePoints), instanceLabel);
183 evt.put(std::move(outputClusters), instanceLabel);
184 evt.put(std::move(outputVertices), instanceLabel);
185 evt.put(std::move(outputParticleMetadata), instanceLabel);
187 evt.put(std::move(outputParticlesToMetadata), instanceLabel);
188 evt.put(std::move(outputParticlesToSpacePoints), instanceLabel);
189 evt.put(std::move(outputParticlesToClusters), instanceLabel);
190 evt.put(std::move(outputParticlesToVertices), instanceLabel);
191 evt.put(std::move(outputParticlesToSlices), instanceLabel);
192 evt.put(std::move(outputSpacePointsToHits), instanceLabel);
193 evt.put(std::move(outputClustersToHits), instanceLabel);
196 evt.put(std::move(outputTestBeamInteractionVertices), testBeamInteractionVertexInstanceLabel);
197 evt.put(std::move(outputParticlesToTestBeamInteractionVertices),
198 testBeamInteractionVertexInstanceLabel);
202 evt.put(std::move(outputT0s), instanceLabel);
203 evt.put(std::move(outputParticlesToT0s), instanceLabel);
207 evt.put(std::move(outputSlices), instanceLabel);
208 evt.put(std::move(outputSlicesToHits), instanceLabel);
216 const std::string&
name,
217 const pandora::Pandora*& pPandoraInstance)
219 if (!pPrimaryPandora)
220 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::GetPandoraInstance--- input "
221 "primary pandora instance address is invalid ";
223 if (pPandoraInstance)
224 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::GetPandoraInstance--- the input "
225 "pandora instance address is non-null ";
227 for (
const pandora::Pandora*
const pPandora :
229 if (pPandora->GetName() !=
name)
continue;
231 if (pPandoraInstance)
232 throw cet::exception(
"LArPandora")
233 <<
" LArPandoraOutput::GetPandoraInstance--- found multiple pandora instances with name: "
236 pPandoraInstance = pPandora;
239 return static_cast<bool>(pPandoraInstance);
246 pandora::PfoVector& slicePfos)
248 if (!slicePfos.empty())
249 throw cet::exception(
"LArPandora")
250 <<
" LArPandoraOutput::GetPandoraSlices--- Input slicePfo vector is not empty ";
253 const pandora::Pandora* pSlicingWorker(
nullptr);
258 const pandora::PfoList* pSlicePfoList(
nullptr);
259 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS,
261 PandoraApi::GetCurrentPfoList(*pSlicingWorker, pSlicePfoList));
263 slicePfos.insert(slicePfos.end(), pSlicePfoList->begin(), pSlicePfoList->end());
271 pandora::PfoList collectedPfos;
274 pandora::PfoVector slicePfos;
278 const pandora::Pandora* pSliceNuWorker(
nullptr);
280 throw cet::exception(
"LArPandora")
281 <<
" LArPandoraOutput::CollectAllPfoOutcomes--- Can't find slice nu worker instance. ";
283 const pandora::Pandora* pSliceCRWorker(
nullptr);
285 throw cet::exception(
"LArPandora")
286 <<
" LArPandoraOutput::CollectAllPfoOutcomes--- Can't find slice CR worker instance. ";
289 for (
unsigned int sliceIndex = 0; sliceIndex < slicePfos.size(); ++sliceIndex) {
290 const pandora::PfoList* pNuPfoList(
nullptr);
291 if (pandora::STATUS_CODE_SUCCESS ==
292 PandoraApi::GetPfoList(
293 *pSliceNuWorker,
"NeutrinoParticles3D" +
std::to_string(sliceIndex), pNuPfoList))
294 collectedPfos.insert(collectedPfos.end(), pNuPfoList->begin(), pNuPfoList->end());
296 const pandora::PfoList* pCRPfoList(
nullptr);
297 if (pandora::STATUS_CODE_SUCCESS ==
298 PandoraApi::GetPfoList(
299 *pSliceCRWorker,
"MuonParticles3D" +
std::to_string(sliceIndex), pCRPfoList))
300 collectedPfos.insert(collectedPfos.end(), pCRPfoList->begin(), pCRPfoList->end());
304 const pandora::PfoList* pParentPfoList(
nullptr);
305 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS,
307 PandoraApi::GetCurrentPfoList(*pPrimaryPandora, pParentPfoList));
310 for (
const pandora::ParticleFlowObject*
const pPfo : *pParentPfoList) {
315 pandora::PfoVector pfoVector;
328 const auto& properties(pParent->GetPropertiesMap());
329 const auto it(properties.find(
"IsClearCosmic"));
331 if (it == properties.end())
return false;
333 return static_cast<bool>(std::round(it->second));
343 const auto& properties(pParent->GetPropertiesMap());
344 return (properties.find(
"SliceIndex") != properties.end());
354 const auto& properties(pParent->GetPropertiesMap());
355 const auto it(properties.find(
"SliceIndex"));
357 if (it == properties.end())
358 throw cet::exception(
"LArPandora")
359 <<
" LArPandoraOutput::GetSliceIndex--- Input PFO was not from a slice ";
361 return static_cast<unsigned int>(std::round(it->second));
369 const pandora::PfoList* pParentPfoList(
nullptr);
370 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS,
372 PandoraApi::GetCurrentPfoList(*pPrimaryPandora, pParentPfoList));
374 pandora::PfoVector pfoVector;
384 pandora::PfoVector& pfoVector)
386 if (!pfoVector.empty())
387 throw cet::exception(
"LArPandora")
388 <<
" LArPandoraOutput::CollectPfos--- trying to collect pfos into a non-empty list ";
390 pandora::PfoList pfoList;
393 pfoVector.insert(pfoVector.end(), pfoList.begin(), pfoList.end());
401 const pandora::PfoVector& pfoVector,
403 std::function<
const pandora::Vertex*
const(
const pandora::ParticleFlowObject*
const)> fCriteria)
407 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
408 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
410 if (pPfo->GetVertexList().empty())
continue;
413 const pandora::Vertex*
const pVertex(fCriteria(pPfo));
416 const auto it(std::find(vertexVector.begin(), vertexVector.end(), pVertex));
417 const bool isInList(it != vertexVector.end());
418 const size_t vertexId(isInList ?
std::distance(vertexVector.begin(), it) :
419 vertexVector.size());
421 if (!isInList) vertexVector.push_back(pVertex);
423 if (!pfoToVerticesMap.insert(IdToIdVectorMap::value_type(pfoId, {vertexId})).second)
424 throw cet::exception(
"LArPandora")
425 <<
" LArPandoraOutput::CollectVertices --- repeated pfos in input list ";
427 catch (
const pandora::StatusCodeException&) {
438 LArPandoraOutput::CollectClusters(
const pandora::PfoVector& pfoVector,
441 pandora::ClusterList clusterList;
443 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
444 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
447 pandora::ClusterList clusters;
452 IdVector clusterIds(clusters.size());
453 std::iota(clusterIds.begin(), clusterIds.end(), clusterList.size());
455 clusterList.insert(clusterList.end(), clusters.begin(), clusters.end());
457 if (!pfoToClustersMap.insert(IdToIdVectorMap::value_type(pfoId, clusterIds)).second)
458 throw cet::exception(
"LArPandora")
459 <<
" LArPandoraOutput::CollectClusters --- repeated pfos in input list ";
468 LArPandoraOutput::Collect3DHits(
const pandora::PfoVector& pfoVector,
471 pandora::CaloHitList caloHitList;
473 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
474 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
476 if (!pfoToThreeDHitsMap.insert(IdToIdVectorMap::value_type(pfoId, {})).second)
477 throw cet::exception(
"LArPandora")
478 <<
" LArPandoraOutput::Collect3DHits --- repeated pfos in input list ";
480 pandora::CaloHitVector sorted3DHits;
481 LArPandoraOutput::Collect3DHits(pPfo, sorted3DHits);
483 for (
const pandora::CaloHit*
const pCaloHit3D : sorted3DHits) {
484 if (pandora::TPC_3D !=
487 throw cet::exception(
"LArPandora")
488 <<
" LArPandoraOutput::Collect3DHits --- found a 2D hit in a 3D cluster";
490 pfoToThreeDHitsMap.at(pfoId).push_back(caloHitList.size());
491 caloHitList.push_back(pCaloHit3D);
501 LArPandoraOutput::Collect3DHits(
const pandora::ParticleFlowObject*
const pPfo,
502 pandora::CaloHitVector& caloHits)
505 pandora::CaloHitList threeDHits;
508 caloHits.insert(caloHits.end(), threeDHits.begin(), threeDHits.end());
515 LArPandoraOutput::GetPandoraToArtHitMap(
const pandora::ClusterList& clusterList,
516 const pandora::CaloHitList& threeDHitList,
521 for (
const pandora::Cluster*
const pCluster : clusterList) {
523 throw cet::exception(
"LArPandora")
524 <<
" LArPandoraOutput::GetPandoraToArtHitMap --- found a 3D input cluster ";
526 pandora::CaloHitVector sortedHits;
527 LArPandoraOutput::GetHitsInCluster(pCluster, sortedHits);
529 for (
const pandora::CaloHit*
const pCaloHit : sortedHits) {
530 if (!pandoraHitToArtHitMap
531 .insert(CaloHitToArtHitMap::value_type(
532 pCaloHit, LArPandoraOutput::GetHit(idToHitMap, pCaloHit)))
534 throw cet::exception(
"LArPandora")
535 <<
" LArPandoraOutput::GetPandoraToArtHitMap --- found repeated input hits ";
539 for (
const pandora::CaloHit*
const pCaloHit : threeDHitList) {
540 if (pCaloHit->GetHitType() != pandora::TPC_3D)
541 throw cet::exception(
"LArPandora")
542 <<
" LArPandoraOutput::GetPandoraToArtHitMap --- found a non-3D hit in the input list ";
545 if (!pandoraHitToArtHitMap
546 .insert(CaloHitToArtHitMap::value_type(
548 LArPandoraOutput::GetHit(
549 idToHitMap, static_cast<const pandora::CaloHit*>(pCaloHit->GetParentAddress()))))
551 throw cet::exception(
"LArPandora")
552 <<
" LArPandoraOutput::GetPandoraToArtHitMap --- found repeated input hits ";
559 LArPandoraOutput::GetHit(
const IdToHitMap& idToHitMap,
const pandora::CaloHit*
const pCaloHit)
565 for (
unsigned int depth = 0, maxDepth = 2; depth < maxDepth; ++depth) {
567 const pandora::CaloHit* pParentCaloHit = pCaloHit;
568 for (
unsigned int i = 0; i < depth; ++i)
569 pParentCaloHit = static_cast<const pandora::CaloHit*>(pCaloHit->GetParentAddress());
572 const void*
const pHitAddress(pParentCaloHit->GetParentAddress());
573 const intptr_t hitID_temp((intptr_t)(pHitAddress));
574 const int hitID((
int)(hitID_temp));
576 IdToHitMap::const_iterator artIter = idToHitMap.find(hitID);
579 if (idToHitMap.end() == artIter)
continue;
581 return artIter->second;
584 throw cet::exception(
"LArPandora")
585 <<
" LArPandoraOutput::GetHit --- found a Pandora hit without a parent ART hit ";
594 for (
size_t vertexId = 0; vertexId < vertexVector.size(); ++vertexId)
595 outputVertices->push_back(LArPandoraOutput::BuildVertex(vertexVector.at(vertexId), vertexId));
601 LArPandoraOutput::BuildSpacePoints(
const art::Event& event,
602 const std::string& instanceLabel,
603 const pandora::CaloHitList& threeDHitList,
608 pandora::CaloHitVector threeDHitVector;
609 threeDHitVector.insert(threeDHitVector.end(), threeDHitList.begin(), threeDHitList.end());
611 for (
unsigned int hitId = 0; hitId < threeDHitVector.size(); hitId++) {
612 const pandora::CaloHit*
const pCaloHit(threeDHitVector.at(hitId));
614 CaloHitToArtHitMap::const_iterator it(pandoraHitToArtHitMap.find(pCaloHit));
615 if (it == pandoraHitToArtHitMap.end())
616 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::BuildSpacePoints --- found a "
617 "pandora hit without a corresponding art hit ";
619 LArPandoraOutput::AddAssociation(
620 event, instanceLabel, hitId, {it->second}, outputSpacePointsToHits);
621 outputSpacePoints->push_back(LArPandoraOutput::BuildSpacePoint(pCaloHit, hitId));
628 LArPandoraOutput::BuildClusters(
const art::Event& event,
629 const std::string& instanceLabel,
630 const pandora::ClusterList& clusterList,
639 art::ServiceHandle<geo::Geometry const> geom{};
640 auto const clock_data =
641 art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
642 auto const det_prop =
643 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(event, clock_data);
647 size_t nextClusterId(0);
649 for (
const pandora::Cluster*
const pCluster : clusterList) {
650 std::vector<HitVector> hitVectors;
651 const std::vector<recob::Cluster> clusters(
652 LArPandoraOutput::BuildClusters(gser,
655 pandoraHitToArtHitMap,
656 pandoraClusterToArtClustersMap,
661 if (hitVectors.size() != clusters.size())
662 throw cet::exception(
"LArPandora")
663 <<
" LArPandoraOutput::BuildClusters --- invalid hit vectors for clusters produced ";
665 for (
unsigned int i = 0; i < clusters.size(); ++i) {
666 LArPandoraOutput::AddAssociation(
667 event, instanceLabel, nextClusterId - 1, hitVectors.at(i), outputClustersToHits);
668 outputClusters->push_back(clusters.at(i));
673 for (IdToIdVectorMap::const_iterator it = pfoToClustersMap.begin();
674 it != pfoToClustersMap.end();
676 if (!pfoToArtClustersMap.insert(IdToIdVectorMap::value_type(it->first, {})).second)
677 throw cet::exception(
"LArPandora")
678 <<
" LArPandoraOutput::BuildClusters --- repeated pfo ids ";
680 for (
const size_t pandoraClusterId : it->second) {
681 IdToIdVectorMap::const_iterator it2(pandoraClusterToArtClustersMap.find(pandoraClusterId));
683 if (it2 == pandoraClusterToArtClustersMap.end())
684 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::BuildClusters --- found a "
685 "pandora cluster with no associated recob cluster ";
687 for (
const size_t recobClusterId : it2->second)
688 pfoToArtClustersMap.at(it->first).push_back(recobClusterId);
696 LArPandoraOutput::BuildPFParticles(
const art::Event& event,
697 const std::string& instanceLabel,
698 const pandora::PfoVector& pfoVector,
707 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
708 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
710 outputParticles->push_back(LArPandoraOutput::BuildPFParticle(pPfo, pfoId, pfoVector));
713 if (pfoToVerticesMap.find(pfoId) != pfoToVerticesMap.end())
714 LArPandoraOutput::AddAssociation(
715 event, instanceLabel, pfoId, pfoToVerticesMap, outputParticlesToVertices);
717 if (pfoToThreeDHitsMap.find(pfoId) != pfoToThreeDHitsMap.end())
718 LArPandoraOutput::AddAssociation(
719 event, instanceLabel, pfoId, pfoToThreeDHitsMap, outputParticlesToSpacePoints);
721 if (pfoToArtClustersMap.find(pfoId) != pfoToArtClustersMap.end())
722 LArPandoraOutput::AddAssociation(
723 event, instanceLabel, pfoId, pfoToArtClustersMap, outputParticlesToClusters);
730 LArPandoraOutput::AssociateAdditionalVertices(
731 const art::Event& event,
732 const std::string& instanceLabel,
733 const pandora::PfoVector& pfoVector,
737 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
738 if (pfoToVerticesMap.find(pfoId) != pfoToVerticesMap.end())
739 LArPandoraOutput::AddAssociation(
740 event, instanceLabel, pfoId, pfoToVerticesMap, outputParticlesToVertices);
747 LArPandoraOutput::BuildParticleMetadata(
const art::Event& event,
748 const std::string& instanceLabel,
749 const pandora::PfoVector& pfoVector,
753 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
754 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
756 LArPandoraOutput::AddAssociation(event,
759 outputParticleMetadata->size(),
760 outputParticlesToMetadata);
762 LArPandoraHelper::GetPFParticleMetadata(pPfo));
763 outputParticleMetadata->push_back(pPFParticleMetadata);
770 LArPandoraOutput::BuildSlices(
const Settings& settings,
771 const pandora::Pandora*
const pPrimaryPandora,
772 const art::Event& event,
773 const std::string& instanceLabel,
774 const pandora::PfoVector& pfoVector,
782 LArPandoraOutput::CopyAllHitsToSingleSlice(settings,
788 outputParticlesToSlices,
794 pandora::PfoVector slicePfos;
795 LArPandoraOutput::GetPandoraSlices(pPrimaryPandora, slicePfos);
798 for (
const pandora::ParticleFlowObject*
const pSlicePfo : slicePfos)
799 LArPandoraOutput::BuildSlice(
800 pSlicePfo, event, instanceLabel, idToHitMap, outputSlices, outputSlicesToHits);
803 std::unordered_map<const pandora::ParticleFlowObject*, unsigned int> parentPfoToSliceIndexMap;
804 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
805 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
808 if (LArPandoraOutput::IsFromSlice(pPfo))
continue;
812 if (!parentPfoToSliceIndexMap
814 LArPandoraOutput::BuildSlice(
815 pPfo, event, instanceLabel, idToHitMap, outputSlices, outputSlicesToHits))
817 throw cet::exception(
"LArPandora")
818 <<
" LArPandoraOutput::BuildSlices --- found repeated primary particles ";
822 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
823 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
826 if (LArPandoraOutput::IsFromSlice(pPfo)) {
827 LArPandoraOutput::AddAssociation(event,
831 outputParticlesToSlices);
836 const pandora::ParticleFlowObject*
const pParent(
838 if (parentPfoToSliceIndexMap.find(pParent) == parentPfoToSliceIndexMap.end())
839 throw cet::exception(
"LArPandora")
840 <<
" LArPandoraOutput::BuildSlices --- found pfo without a parent in the input list ";
843 LArPandoraOutput::AddAssociation(
844 event, instanceLabel, pfoId, parentPfoToSliceIndexMap.at(pParent), outputParticlesToSlices);
854 const float bogusFloat(std::numeric_limits<float>::max());
858 const unsigned int sliceIndex(outputSlices->size());
859 outputSlices->emplace_back(
860 sliceIndex, bogusPoint, bogusVector, bogusPoint, bogusPoint, bogusFloat, bogusFloat);
868 LArPandoraOutput::CopyAllHitsToSingleSlice(
const Settings& settings,
869 const art::Event& event,
870 const std::string& instanceLabel,
871 const pandora::PfoVector& pfoVector,
877 const unsigned int sliceIndex(LArPandoraOutput::BuildDummySlice(outputSlices));
882 LArPandoraOutput::AddAssociation(event, instanceLabel, sliceIndex, hits, outputSlicesToHits);
886 mf::LogDebug(
"LArPandora") <<
" - Found " << hits.size() << std::endl;
887 mf::LogDebug(
"LArPandora") <<
" - Making associations " << outputSlicesToHits->size()
891 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId)
892 LArPandoraOutput::AddAssociation(
893 event, instanceLabel, pfoId, sliceIndex, outputParticlesToSlices);
899 LArPandoraOutput::BuildSlice(
const pandora::ParticleFlowObject*
const pParentPfo,
900 const art::Event& event,
901 const std::string& instanceLabel,
906 const unsigned int sliceIndex(LArPandoraOutput::BuildDummySlice(outputSlices));
909 pandora::PfoList pfosInSlice;
914 pandora::CaloHitList hits;
915 for (
const pandora::ParticleFlowObject*
const pPfo : pfosInSlice) {
916 for (
const pandora::HitType& hitType :
917 {pandora::TPC_VIEW_U, pandora::TPC_VIEW_V, pandora::TPC_VIEW_W}) {
924 for (
const pandora::CaloHit*
const pCaloHit : hits)
925 LArPandoraOutput::AddAssociation(event,
928 {LArPandoraOutput::GetHit(idToHitMap, pCaloHit)},
937 LArPandoraOutput::BuildT0s(
const art::Event& event,
938 const std::string& instanceLabel,
939 const pandora::PfoVector& pfoVector,
944 for (
unsigned int pfoId = 0; pfoId < pfoVector.size(); ++pfoId) {
945 const pandora::ParticleFlowObject*
const pPfo(pfoVector.at(pfoId));
948 if (!LArPandoraOutput::BuildT0(event, pPfo, pfoVector, nextT0Id, t0))
continue;
950 LArPandoraOutput::AddAssociation(
951 event, instanceLabel, pfoId, nextT0Id - 1, outputParticlesToT0s);
952 outputT0s->push_back(t0);
959 LArPandoraOutput::BuildPFParticle(
const pandora::ParticleFlowObject*
const pPfo,
961 const pandora::PfoVector& pfoVector)
964 const pandora::PfoList& parentList(pPfo->GetParentPfoList());
965 if (parentList.size() > 1)
966 throw cet::exception(
"LArPandora")
967 <<
" LArPandoraOutput::BuildPFParticle --- this pfo has multiple parent particles ";
969 const size_t parentId(parentList.empty() ?
971 LArPandoraOutput::GetId(parentList.front(), pfoVector));
974 std::vector<size_t> daughterIds;
975 for (
const pandora::ParticleFlowObject*
const pDaughterPfo : pPfo->GetDaughterPfoList())
976 daughterIds.push_back(LArPandoraOutput::GetId(pDaughterPfo, pfoVector));
978 std::sort(daughterIds.begin(), daughterIds.end());
986 LArPandoraOutput::BuildVertex(
const pandora::Vertex*
const pVertex,
const size_t vertexId)
989 pVertex->GetPosition().GetX(), pVertex->GetPosition().GetY(), pVertex->GetPosition().GetZ()};
996 LArPandoraOutput::GetHitsInCluster(
const pandora::Cluster*
const pCluster,
997 pandora::CaloHitVector& sortedHits)
999 if (!sortedHits.empty())
1000 throw cet::exception(
"LArPandora")
1001 <<
" LArPandoraOutput::GetHitsInCluster --- vector to hold hits is not empty ";
1003 pandora::CaloHitList hitList;
1004 pCluster->GetOrderedCaloHitList().FillCaloHitList(hitList);
1005 hitList.insert(hitList.end(),
1006 pCluster->GetIsolatedCaloHitList().begin(),
1007 pCluster->GetIsolatedCaloHitList().end());
1009 sortedHits.insert(sortedHits.end(), hitList.begin(), hitList.end());
1016 std::vector<recob::Cluster>
1018 const pandora::Cluster*
const pCluster,
1019 const pandora::ClusterList& clusterList,
1022 std::vector<HitVector>& hitVectors,
1026 std::vector<recob::Cluster> clusters;
1029 const size_t clusterId(LArPandoraOutput::GetId(pCluster, clusterList));
1030 if (!pandoraClusterToArtClustersMap.insert(IdToIdVectorMap::value_type(clusterId, {})).second)
1031 throw cet::exception(
"LArPandora")
1032 <<
" LArPandoraOutput::BuildClusters --- repeated clusters in input list ";
1034 pandora::CaloHitVector sortedHits;
1035 LArPandoraOutput::GetHitsInCluster(pCluster, sortedHits);
1040 for (
const pandora::CaloHit*
const pCaloHit2D : sortedHits) {
1041 CaloHitToArtHitMap::const_iterator it(pandoraHitToArtHitMap.find(pCaloHit2D));
1042 if (it == pandoraHitToArtHitMap.end())
1043 throw cet::exception(
"LArPandora")
1044 <<
" LArPandoraOutput::BuildClusters --- couldn't find art hit for input pandora hit ";
1046 const art::Ptr<recob::Hit>
hit(it->second);
1049 const unsigned int volID(100000 * wireID.Cryostat + wireID.TPC);
1050 hitArray[volID].push_back(
hit);
1052 if (pCaloHit2D->IsIsolated()) isolatedHits.insert(
hit);
1055 if (hitArray.empty())
1056 throw cet::exception(
"LArPandora")
1057 <<
" LArPandoraOutput::BuildClusters --- found a cluster with no hits ";
1059 for (
const HitArray::value_type& hitArrayEntry : hitArray) {
1060 const HitVector& clusterHits(hitArrayEntry.second);
1063 LArPandoraOutput::BuildCluster(gser, nextId, clusterHits, isolatedHits, algo));
1064 hitVectors.push_back(clusterHits);
1065 pandoraClusterToArtClustersMap.at(clusterId).push_back(nextId);
1082 if (hitVector.empty())
1083 throw cet::exception(
"LArPandora")
1084 <<
" LArPandoraOutput::BuildCluster --- No input hits were provided ";
1090 double startWire(+std::numeric_limits<float>::max()), sigmaStartWire(0.0);
1091 double startTime(+std::numeric_limits<float>::max()), sigmaStartTime(0.0);
1092 double endWire(-std::numeric_limits<float>::max()), sigmaEndWire(0.0);
1093 double endTime(-std::numeric_limits<float>::max()), sigmaEndTime(0.0);
1095 std::vector<recob::Hit const*> hits_for_params;
1096 hits_for_params.reserve(hitVector.size());
1098 for (
const art::Ptr<recob::Hit>&
hit : hitVector) {
1099 const double thisWire(
hit->WireID().Wire);
1100 const double thisWireSigma(0.5);
1101 const double thisTime(
hit->PeakTime());
1102 const double thisTimeSigma(
double(2. *
hit->RMS()));
1108 planeID = thisPlaneID;
1111 if (!(thisView == view && thisPlaneID == planeID)) {
1112 throw cet::exception(
"LArPandora")
1113 <<
" LArPandoraOutput::BuildCluster --- Input hits have inconsistent plane IDs ";
1116 hits_for_params.push_back(&*
hit);
1118 if (isolatedHits.count(
hit))
continue;
1120 if (thisWire < startWire || (thisWire == startWire && thisTime < startTime)) {
1121 startWire = thisWire;
1122 sigmaStartWire = thisWireSigma;
1123 startTime = thisTime;
1124 sigmaStartTime = thisTimeSigma;
1127 if (thisWire > endWire || (thisWire == endWire && thisTime > endTime)) {
1129 sigmaEndWire = thisWireSigma;
1131 sigmaEndTime = thisTimeSigma;
1136 algo.
SetHits(gser, hits_for_params);
1160 LArPandoraOutput::BuildSpacePoint(
const pandora::CaloHit*
const pCaloHit,
1161 const size_t spacePointId)
1163 if (pandora::TPC_3D != pCaloHit->GetHitType())
1164 throw cet::exception(
"LArPandora")
1165 <<
" LArPandoraOutput::BuildSpacePoint --- trying to build a space point from a 2D hit";
1167 const pandora::CartesianVector point(pCaloHit->GetPositionVector());
1168 double xyz[3] = {point.GetX(), point.GetY(), point.GetZ()};
1171 double dxdydz[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1180 LArPandoraOutput::BuildT0(
const art::Event&
e,
1181 const pandora::ParticleFlowObject*
const pPfo,
1182 const pandora::PfoVector& pfoVector,
1187 const float x0(pParent->GetPropertiesMap().count(
"X0") ? pParent->GetPropertiesMap().at(
"X0") :
1190 auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(e);
1191 auto const det_prop =
1192 art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(e, clock_data);
1193 const double cm_per_tick(det_prop.GetXTicksCoefficient());
1197 const double T0(x0 * ns_per_tick / cm_per_tick);
1199 if (std::fabs(T0) <= std::numeric_limits<double>::epsilon())
return false;
1202 t0 =
anab::T0(T0, 3, LArPandoraOutput::GetId(pPfo, pfoVector), nextId++);
1210 LArPandoraOutput::Settings::Settings()
1211 : m_pPrimaryPandora(nullptr)
1212 , m_shouldRunStitching(
false)
1213 , m_shouldProduceAllOutcomes(
false)
1214 , m_shouldProduceTestBeamInteractionVertices(
false)
1215 , m_isNeutrinoRecoOnlyNoSlicing(
false)
1223 if (!m_pPrimaryPandora)
1224 throw cet::exception(
"LArPandora")
1225 <<
" LArPandoraOutput::Settings::Validate --- primary Pandora instance does not exist ";
1227 if (!m_shouldProduceAllOutcomes)
return;
1229 if (m_allOutcomesInstanceLabel.empty())
1230 throw cet::exception(
"LArPandora")
1231 <<
" LArPandoraOutput::Settings::Validate --- all outcomes instance label not set ";
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, then pulse-height.
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...
void Validate() const
Check the parameters and throw an exception if they are not valid.
static void GetPandoraSlices(const pandora::Pandora *const pPrimaryPandora, pandora::PfoVector &slicePfos)
Get the slice pfos - one pfo per slice.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
Header file for the pfo helper class.
Class managing the creation of a new recob::Cluster object.
const pandora::Pandora * m_pPrimaryPandora
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.
std::unique_ptr< std::vector< larpandoraobj::PFParticleMetadata > > PFParticleMetadataCollection
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 constexpr size_t kPFParticlePrimary
Define index to signify primary particle.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
std::map< int, HitVector > HitArray
static void GetTwoDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 2D clusters from an input pfo.
std::unique_ptr< art::Assns< recob::PFParticle, recob::Slice > > PFParticleToSliceCollection
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...
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 ...
Declaration of signal hit object.
std::unique_ptr< std::vector< recob::Slice > > SliceCollection
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
std::unique_ptr< std::vector< recob::PFParticle > > PFParticleCollection
The data type to uniquely identify a Plane.
std::string m_testBeamInteractionVerticesInstanceLabel
The label for the test beam interaction vertices.
std::unique_ptr< std::vector< recob::Vertex > > VertexCollection
static const pandora::Vertex * GetTestBeamInteractionVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo test beam interaction vertex.
std::string m_allOutcomesInstanceLabel
The label for the instance producing all outcomes.
std::map< size_t, IdVector > IdToIdVectorMap
Algorithm collection class computing cluster parameters.
Set of hits with a 2D structure.
std::unique_ptr< art::Assns< recob::PFParticle, larpandoraobj::PFParticleMetadata > > PFParticleToMetadataCollection
std::map< int, art::Ptr< recob::Hit > > IdToHitMap
bool m_isNeutrinoRecoOnlyNoSlicing
If we are running the neutrino reconstruction only with no slicing.
Helper functions for processing outputs from pandora.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool IsFromSlice(const pandora::ParticleFlowObject *const pPfo)
Check if the input pfo is from a slice.
Definition of vertex object for LArSoft.
std::array< float, 2 > HitVector(const recob::Hit &hit, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
static const SentryArgument_t Sentry
An instance of the sentry object.
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.
std::string m_hitfinderModuleLabel
The hit finder module label.
Algorithm collection class computing cluster parameters.
std::unique_ptr< art::Assns< recob::Slice, recob::Hit > > SliceToHitCollection
std::vector< size_t > IdVector
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< Coord_t >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space. See recob::tracking::Coord_t for more details on the ...
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
Metadata associated to PFParticles.
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 const pandora::ParticleFlowObject * GetParentPfo(const pandora::ParticleFlowObject *const pPfo)
Get the primary parent pfo.
Header file for the cluster helper class.
static unsigned int GetSliceIndex(const pandora::ParticleFlowObject *const pPfo)
Get the index of the slice from which this pfo was produced.
std::unique_ptr< art::Assns< recob::PFParticle, anab::T0 > > PFParticleToT0Collection
Helper functions to create a cluster.
static void BuildVertices(const pandora::VertexVector &vertexVector, VertexCollection &outputVertices)
Convert pandora vertices to ART vertices and add them to the output vector.
std::vector< art::Ptr< recob::Hit > > CollectHits(const std::vector< art::Ptr< recob::Hit >> &hits, const sbn::VertexHit &vhit, const recob::Hit &vhit_hit, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
std::unique_ptr< art::Assns< recob::SpacePoint, recob::Hit > > SpacePointToHitCollection
static pandora::PfoVector CollectPfos(const pandora::Pandora *const pPrimaryPandora)
Collect the current pfos (including all downstream pfos) from the master pandora instance.
static bool IsClearCosmic(const pandora::ParticleFlowObject *const pPfo)
Check if the input pfo is an unambiguous cosmic ray.
Wrapper for ClusterParamsAlgBase objects to accept arbitrary input.
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< std::vector< recob::Cluster > > ClusterCollection
std::map< const pandora::CaloHit *, art::Ptr< recob::Hit > > CaloHitToArtHitMap
std::unique_ptr< art::Assns< recob::PFParticle, recob::Vertex > > PFParticleToVertexCollection
Header file for the MultiPandoraApi class.
virtual void SetHits(util::GeometryUtilities const &gser, std::vector< recob::Hit const * > const &hits)=0
Sets the list of input hits.
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::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 void Collect3DHits(const pandora::ParticleFlowObject *const pPfo, pandora::CaloHitVector &caloHits)
Collect a sorted vector of all 3D hits in the input pfo.
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...
bool m_shouldProduceTestBeamInteractionVertices
Whether to write the test beam interaction vertices in a separate collection.
std::unique_ptr< art::Assns< recob::PFParticle, recob::SpacePoint > > PFParticleToSpacePointCollection
std::vector< art::Ptr< recob::Hit > > HitVector
Hierarchical representation of particle flow.
bool m_shouldRunStitching
std::unique_ptr< std::vector< anab::T0 > > T0Collection
bool m_shouldProduceAllOutcomes
If all outcomes should be produced in separate collections (choose false if you only require the cons...
std::string to_string(WindowPattern const &pattern)
bool m_shouldProduceSlices
Whether to produce output slices e.g. may not want to do this if only (re)processing single slices...
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.
std::pair< unsigned short, unsigned short > GetSliceIndex(std::string typeName, int uID)
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.
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 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< recob::SpacePoint > > SpacePointCollection
Interface to class computing cluster parameters.
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...
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< Coord_t >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space. See recob::tracking::Coord_t for more detai...
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.
std::set< art::Ptr< recob::Hit > > HitList
recob::Cluster && move()
Prepares the constructed hit to be moved away.
static pandora::PfoVector CollectAllPfoOutcomes(const pandora::Pandora *const pPrimaryPandora)
Collect the pfos (including all downstream pfos) from the master and daughter pandora instances...
std::array< float, 2 > VertexVector(const recob::Vertex &vert, const geo::PlaneID &plane, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
std::unique_ptr< art::Assns< recob::Cluster, recob::Hit > > ClusterToHitCollection
art framework interface to geometry description
process_name opdaq physics producers generator physics producers generator physics producers generator physics producers generator physics producers generator physics producers generator physics producers generator physics producers generator T0