Convert the Pandora PFOs into ART clusters and write into ART event.
50 mf::LogDebug(
"LArPandora") <<
" *** LArPandora::ProduceArtOutput() *** " << std::endl;
52 if (!settings.m_pPrimaryPandora)
53 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- primary Pandora instance does not exist ";
55 if (!settings.m_pProducer)
56 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- pointer to ART Producer module does not exist ";
59 const pandora::PfoList *pPfoList(
nullptr);
60 PANDORA_THROW_RESULT_IF(pandora::STATUS_CODE_SUCCESS, !=, PandoraApi::GetCurrentPfoList(*(settings.m_pPrimaryPandora), pPfoList));
62 if (pPfoList->empty())
63 mf::LogDebug(
"LArPandora") <<
" Warning: No reconstructed particles for this event " << std::endl;
65 pandora::PfoList connectedPfoList;
68 pandora::PfoVector pfoVector(connectedPfoList.begin(), connectedPfoList.end());
72 std::unique_ptr< std::vector<recob::PFParticle> > outputParticles(
new std::vector<recob::PFParticle> );
73 std::unique_ptr< std::vector<recob::SpacePoint> > outputSpacePoints(
new std::vector<recob::SpacePoint> );
74 std::unique_ptr< std::vector<recob::Cluster> > outputClusters(
new std::vector<recob::Cluster> );
75 std::unique_ptr< std::vector<recob::Vertex> > outputVertices(
new std::vector<recob::Vertex> );
76 std::unique_ptr< std::vector<anab::T0> > outputT0s(
new std::vector<anab::T0> );
77 std::unique_ptr< std::vector<larpandoraobj::PFParticleMetadata> > outputParticleMetadata(
new std::vector<larpandoraobj::PFParticleMetadata> );
92 size_t particleCounter(0), vertexCounter(0), spacePointCounter(0), clusterCounter(0), t0Counter(0);
98 for (
const pandora::ParticleFlowObject *
const pPfo : pfoVector)
100 particleMap.insert( std::pair<const pandora::ParticleFlowObject*, size_t>(pPfo, particleCounter++) );
102 if (!pPfo->GetVertexList().empty())
104 if(pPfo->GetVertexList().size() != 1)
105 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- this particle has multiple interaction vertices ";
107 const pandora::Vertex *
const pVertex(pPfo->GetVertexList().front());
109 if (vertexMap.end() != vertexMap.find(pVertex))
112 double pos[3] = {pVertex->GetPosition().GetX(), pVertex->GetPosition().GetY(), pVertex->GetPosition().GetZ()};
113 outputVertices->emplace_back(
recob::Vertex(pos, vertexCounter++));
114 vertexMap.insert(std::pair<const pandora::Vertex*, unsigned int>(pVertex, vertexCounter - 1));
119 for (
const pandora::ParticleFlowObject *
const pPfo : pfoVector)
123 if (particleMap.end() == iter)
124 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- found an unassociated particle";
126 const size_t pfoIdCode(iter->second);
130 const pandora::PfoList &parentList(pPfo->GetParentPfoList());
132 if (!parentList.empty())
134 if (parentList.size() != 1)
135 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- this particle has multiple parent particles ";
138 if (particleMap.end() == parentIdIter)
139 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- found an unassociated particle ";
141 parentIdCode = parentIdIter->second;
145 std::vector<size_t> daughterIdCodes;
146 pandora::PfoVector daughterPfoVector(pPfo->GetDaughterPfoList().begin(), pPfo->GetDaughterPfoList().end());
149 for (
const pandora::ParticleFlowObject *
const pDaughterPfo : daughterPfoVector)
152 if (particleMap.end() == daughterIdIter)
153 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- found an unassociated particle ";
155 const size_t daughterIdCode(daughterIdIter->second);
156 daughterIdCodes.push_back(daughterIdCode);
160 recob::PFParticle newParticle(pPfo->GetParticleId(), pfoIdCode, parentIdCode, daughterIdCodes);
161 outputParticles->push_back(newParticle);
167 util::CreateAssn(*(settings.m_pProducer), evt, *(outputParticles.get()), *(outputParticleMetadata.get()), *(outputParticlesToMetadata.get()), outputParticleMetadata->
size()-1, outputParticleMetadata->size());
170 if (!pPfo->GetVertexList().empty())
172 if (pPfo->GetVertexList().size() != 1)
173 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- this particle has multiple interaction vertices ";
175 const pandora::Vertex *
const pVertex = *(pPfo->GetVertexList().begin());
178 if (vertexMap.end() == iter)
179 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- found an unassociated vertex ";
181 const unsigned int vtxElement(iter->second);
182 util::CreateAssn(*(settings.m_pProducer), evt, *(outputParticles.get()), *(outputVertices.get()), *(outputParticlesToVertices.get()),
183 vtxElement, vtxElement + 1);
187 pandora::ClusterVector pandoraClusterVector(pPfo->GetClusterList().begin(), pPfo->GetClusterList().end());
190 for (
const pandora::Cluster *
const pCluster : pandoraClusterVector)
195 pandora::CaloHitList pandoraHitList2D;
196 pCluster->GetOrderedCaloHitList().FillCaloHitList(pandoraHitList2D);
197 pandoraHitList2D.insert(pandoraHitList2D.end(), pCluster->GetIsolatedCaloHitList().begin(), pCluster->GetIsolatedCaloHitList().end());
199 pandora::CaloHitVector pandoraHitVector2D(pandoraHitList2D.begin(), pandoraHitList2D.end());
205 for (
const pandora::CaloHit *
const pCaloHit2D : pandoraHitVector2D)
210 const unsigned int volID(100000 * wireID.Cryostat + wireID.TPC);
211 hitArray[volID].push_back(hit);
213 if (pCaloHit2D->IsIsolated())
214 isolatedHits.insert(hit);
217 if (hitArray.empty())
218 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- found a cluster with no hits ";
220 for (
const HitArray::value_type &hitArrayEntry : hitArray)
222 const HitVector &clusterHits(hitArrayEntry.second);
225 util::CreateAssn(*(settings.m_pProducer), evt, *(outputClusters.get()), clusterHits, *(outputClustersToHits.get()));
226 util::CreateAssn(*(settings.m_pProducer), evt, *(outputParticles.get()), *(outputClusters.get()), *(outputParticlesToClusters.get()),
227 outputClusters->
size() - 1, outputClusters->size());
229 LOG_DEBUG(
"LArPandora") <<
"Stored cluster ID=" << outputClusters->back().ID() <<
" (#" << (outputClusters->size() - 1)
230 <<
") with " << clusterHits.size() <<
" hits";
235 pandora::CaloHitList pandoraHitList3D;
238 pandora::CaloHitVector pandoraHitVector3D(pandoraHitList3D.begin(), pandoraHitList3D.end());
241 double sumT(0.), sumN(0.);
243 for (
const pandora::CaloHit *
const pCaloHit3D : pandoraHitVector3D)
245 if (pandora::TPC_3D != pCaloHit3D->GetHitType())
246 throw cet::exception(
"LArPandora") <<
" LArPandoraOutput::ProduceArtOutput --- found a 2D hit in a 3D cluster";
248 const pandora::CaloHit *
const pCaloHit2D =
static_cast<const pandora::CaloHit*
>(pCaloHit3D->GetParentAddress());
253 spacePointHits.push_back(hit);
261 util::CreateAssn(*(settings.m_pProducer), evt, *(outputSpacePoints.get()), spacePointHits, *(outputSpacePointsToHits.get()));
262 util::CreateAssn(*(settings.m_pProducer), evt, *(outputParticles.get()), *(outputSpacePoints.get()), *(outputParticlesToSpacePoints.get()),
263 outputSpacePoints->
size() - 1, outputSpacePoints->size());
268 const double T0((sumN > 0. && std::fabs(sumT) > sumN) ? (sumT / sumN) : 0.);
270 if (settings.m_shouldRunStitching && std::fabs(T0) > 0.)
272 outputT0s->emplace_back(
anab::T0(T0, 3, outputParticles->back().Self(), t0Counter++));
273 util::CreateAssn(*(settings.m_pProducer), evt, *(outputParticles.get()), *(outputT0s.get()), *(outputParticlesToT0s.get()), outputT0s->
size() - 1, outputT0s->size());
277 mf::LogDebug(
"LArPandora") <<
" Number of new particles: " << outputParticles->size() << std::endl;
278 mf::LogDebug(
"LArPandora") <<
" Number of new clusters: " << outputClusters->size() << std::endl;
279 mf::LogDebug(
"LArPandora") <<
" Number of new space points: " << outputSpacePoints->size() << std::endl;
280 mf::LogDebug(
"LArPandora") <<
" Number of new vertices: " << outputVertices->size() << std::endl;
282 if (settings.m_shouldRunStitching)
283 mf::LogDebug(
"LArPandora") <<
" Number of new T0s: " << outputT0s->size() << std::endl;
285 evt.
put(std::move(outputParticles));
286 evt.
put(std::move(outputSpacePoints));
287 evt.
put(std::move(outputClusters));
288 evt.
put(std::move(outputVertices));
289 evt.
put(std::move(outputParticleMetadata));
291 evt.
put(std::move(outputParticlesToMetadata));
292 evt.
put(std::move(outputParticlesToSpacePoints));
293 evt.
put(std::move(outputParticlesToClusters));
294 evt.
put(std::move(outputParticlesToVertices));
295 evt.
put(std::move(outputSpacePointsToHits));
296 evt.
put(std::move(outputClustersToHits));
298 if (settings.m_shouldRunStitching)
300 evt.
put(std::move(outputT0s));
301 evt.
put(std::move(outputParticlesToT0s));
304 mf::LogDebug(
"LArPandora") <<
" *** LArPandora::ProduceArtOutput() [DONE!] *** " << std::endl;
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 bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
static constexpr size_t kPFParticlePrimary
Define index to signify primary particle.
geo::WireID WireID() const
Initial tdc tick for hit.
Algorithm collection class computing cluster parameters.
static double CalculateT0(const art::Ptr< recob::Hit > hit, const pandora::CaloHit *const pCaloHit)
Convert X0 correction into T0 correction.
static art::Ptr< recob::Hit > GetHit(const IdToHitMap &idToHitMap, const pandora::CaloHit *const pCaloHit)
Lookup ART hit from an input Pandora hit.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
Definition of vertex object for LArSoft.
static recob::SpacePoint BuildSpacePoint(const int id, const pandora::CaloHit *const pCaloHit)
Build a recob::SpacePoint object.
std::map< const pandora::ParticleFlowObject *, size_t > ThreeDParticleMap
ProductID put(std::unique_ptr< PROD > &&product)
std::map< const pandora::Vertex *, unsigned int > ThreeDVertexMap
Pandora PFParticleMetadata.
std::map< int, HitVector > HitArray
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)
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
std::vector< art::Ptr< recob::Hit > > HitVector
Detector simulation of raw signals on wires.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
Hierarchical representation of particle flow.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
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 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
static recob::Cluster BuildCluster(const int id, const HitVector &hitVector, const HitList &isolatedHits, cluster::ClusterParamsAlgBase &algo)
Build a recob::Cluster object from an input vector of recob::Hit objects.
cet::coded_exception< error, detail::translate > exception