Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
StitchingCosmicRayMergingTool.cc
Go to the documentation of this file.
1
10
15
17
19
20using namespace pandora;
21
22namespace lar_content
23{
24
26 m_useXcoordinate(false),
27 m_alwaysApplyT0Calculation(true),
28 m_halfWindowLayers(30),
29 m_minLengthSquared(50.f),
30 m_minCosRelativeAngle(0.966),
31 m_relaxMinLongitudinalDisplacement(-5.f),
32 m_maxLongitudinalDisplacementX(15.f),
33 m_maxTransverseDisplacement(5.f),
34 m_relaxCosRelativeAngle(0.906),
35 m_relaxTransverseDisplacement(2.5f),
36 m_minNCaloHits3D(0),
37 m_maxX0FractionalDeviation(0.3f),
38 m_boundaryToleranceWidth(10.f)
39{
40}
41
42void StitchingCosmicRayMergingTool::Run(const MasterAlgorithm *const pAlgorithm, const PfoList *const pMultiPfoList,
43 PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map)
44{
46 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
47
48 if (this->GetPandora().GetGeometry()->GetLArTPCMap().size() < 2)
49 return;
50
51 if (pfoToLArTPCMap.empty())
52 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
53
54 PfoList primaryPfos;
55 this->SelectPrimaryPfos(pMultiPfoList, pfoToLArTPCMap, primaryPfos);
56
57 ThreeDPointingClusterMap pointingClusterMap;
58 this->BuildPointingClusterMaps(primaryPfos, pfoToLArTPCMap, pointingClusterMap);
59
60 LArTPCToPfoMap larTPCToPfoMap;
61 this->BuildTPCMaps(primaryPfos, pfoToLArTPCMap, larTPCToPfoMap);
62
63 PfoAssociationMatrix pfoAssociationMatrix;
64 this->CreatePfoMatches(larTPCToPfoMap, pointingClusterMap, pfoAssociationMatrix);
65
66 PfoMergeMap pfoSelectedMatches;
67 this->SelectPfoMatches(pfoAssociationMatrix, pfoSelectedMatches);
68
69 PfoMergeMap pfoSelectedMerges;
70 this->SelectPfoMerges(pfoSelectedMatches, pfoSelectedMerges);
71
72 PfoMergeMap pfoOrderedMerges;
73 this->OrderPfoMerges(pfoToLArTPCMap, pointingClusterMap, pfoSelectedMerges, pfoOrderedMerges);
74
75 this->StitchPfos(pAlgorithm, pointingClusterMap, pfoOrderedMerges, pfoToLArTPCMap, stitchedPfosToX0Map);
76}
77
78//------------------------------------------------------------------------------------------------------------------------------------------
79
80void StitchingCosmicRayMergingTool::SelectPrimaryPfos(const PfoList *pInputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, PfoList &outputPfoList) const
81{
82 for (const ParticleFlowObject *const pPfo : *pInputPfoList)
83 {
85 continue;
86
87 if (!pfoToLArTPCMap.count(pPfo))
88 continue;
89
90 outputPfoList.push_back(pPfo);
91 }
92
93 outputPfoList.sort(LArPfoHelper::SortByNHits);
94}
95
96//------------------------------------------------------------------------------------------------------------------------------------------
97
99 const PfoList &inputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, ThreeDPointingClusterMap &pointingClusterMap) const
100{
101 for (const ParticleFlowObject *const pPfo : inputPfoList)
102 {
103 try
104 {
105 PfoToLArTPCMap::const_iterator tpcIter(pfoToLArTPCMap.find(pPfo));
106
107 if (pfoToLArTPCMap.end() == tpcIter)
108 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
109
110 const float slidingFitPitch(tpcIter->second->GetWirePitchW());
111
112 ClusterList clusterList;
113 LArPfoHelper::GetThreeDClusterList(pPfo, clusterList);
114
115 if (1 != clusterList.size())
116 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
117
118 const ThreeDSlidingFitResult slidingFitResult(clusterList.front(), m_halfWindowLayers, slidingFitPitch);
119 (void)pointingClusterMap.insert(ThreeDPointingClusterMap::value_type(pPfo, LArPointingCluster(slidingFitResult)));
120 }
121 catch (const StatusCodeException &)
122 {
123 }
124 }
125}
126
127//------------------------------------------------------------------------------------------------------------------------------------------
128
129void StitchingCosmicRayMergingTool::BuildTPCMaps(const PfoList &inputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, LArTPCToPfoMap &larTPCToPfoMap) const
130{
131 for (const ParticleFlowObject *const pPfo : inputPfoList)
132 {
133 PfoToLArTPCMap::const_iterator iter(pfoToLArTPCMap.find(pPfo));
134
135 if (pfoToLArTPCMap.end() != iter)
136 larTPCToPfoMap[iter->second].push_back(pPfo);
137 }
138}
139
140//------------------------------------------------------------------------------------------------------------------------------------------
141
143 const ThreeDPointingClusterMap &pointingClusterMap, PfoAssociationMatrix &pfoAssociationMatrix) const
144{
145 LArTPCVector larTPCVector;
146 for (const auto &mapEntry : larTPCToPfoMap)
147 larTPCVector.push_back(mapEntry.first);
148 std::sort(larTPCVector.begin(), larTPCVector.end(), LArStitchingHelper::SortTPCs);
149
150 for (LArTPCVector::const_iterator tpcIter1 = larTPCVector.begin(), tpcIterEnd = larTPCVector.end(); tpcIter1 != tpcIterEnd; ++tpcIter1)
151 {
152 const LArTPC *const pLArTPC1(*tpcIter1);
153 const PfoList &pfoList1(larTPCToPfoMap.at(pLArTPC1));
154
155 for (LArTPCVector::const_iterator tpcIter2 = tpcIter1; tpcIter2 != tpcIterEnd; ++tpcIter2)
156 {
157 const LArTPC *const pLArTPC2(*tpcIter2);
158 const PfoList &pfoList2(larTPCToPfoMap.at(pLArTPC2));
159
160 if (!LArStitchingHelper::CanTPCsBeStitched(*pLArTPC1, *pLArTPC2))
161 continue;
162
163 for (const ParticleFlowObject *const pPfo1 : pfoList1)
164 {
165 for (const ParticleFlowObject *const pPfo2 : pfoList2)
166 this->CreatePfoMatches(*pLArTPC1, *pLArTPC2, pPfo1, pPfo2, pointingClusterMap, pfoAssociationMatrix);
167 }
168 }
169 }
170}
171
172//------------------------------------------------------------------------------------------------------------------------------------------
173
174void StitchingCosmicRayMergingTool::CreatePfoMatches(const LArTPC &larTPC1, const LArTPC &larTPC2, const ParticleFlowObject *const pPfo1,
175 const ParticleFlowObject *const pPfo2, const ThreeDPointingClusterMap &pointingClusterMap, PfoAssociationMatrix &pfoAssociationMatrix) const
176{
177 // Get centre and width of boundary between tpcs
178 const float boundaryCenterX(LArStitchingHelper::GetTPCBoundaryCenterX(larTPC1, larTPC2));
179 const float boundaryWidthX(LArStitchingHelper::GetTPCBoundaryWidthX(larTPC1, larTPC2));
180 const float maxLongitudinalDisplacementX(m_maxLongitudinalDisplacementX + boundaryWidthX);
181
182 // Get the pointing cluster corresponding to each of these Pfos
183 ThreeDPointingClusterMap::const_iterator iter1 = pointingClusterMap.find(pPfo1);
184 ThreeDPointingClusterMap::const_iterator iter2 = pointingClusterMap.find(pPfo2);
185
186 if (pointingClusterMap.end() == iter1 || pointingClusterMap.end() == iter2)
187 return;
188
189 const LArPointingCluster &pointingCluster1(iter1->second);
190 const LArPointingCluster &pointingCluster2(iter2->second);
191
192 // Check length of pointing clusters
193 if (pointingCluster1.GetLengthSquared() < m_minLengthSquared || pointingCluster2.GetLengthSquared() < m_minLengthSquared)
194 return;
195
196 // Get number of 3D hits in each of the pfos
197 CaloHitList caloHitList3D1;
198 LArPfoHelper::GetCaloHits(pPfo1, TPC_3D, caloHitList3D1);
199
200 CaloHitList caloHitList3D2;
201 LArPfoHelper::GetCaloHits(pPfo2, TPC_3D, caloHitList3D2);
202
203 // Check number of 3D hits in each of the pfos
204 if (caloHitList3D1.size() < m_minNCaloHits3D || caloHitList3D2.size() < m_minNCaloHits3D)
205 return;
206
207 // Get closest pair of vertices
208 LArPointingCluster::Vertex pointingVertex1, pointingVertex2;
209
210 try
211 {
212 LArStitchingHelper::GetClosestVertices(larTPC1, larTPC2, pointingCluster1, pointingCluster2, pointingVertex1, pointingVertex2);
213 }
214 catch (const pandora::StatusCodeException &)
215 {
216 return;
217 }
218
219 // Pointing clusters must have a parallel direction
220 const float cosRelativeAngle(-pointingVertex1.GetDirection().GetDotProduct(pointingVertex2.GetDirection()));
221
222 if (cosRelativeAngle < m_relaxCosRelativeAngle)
223 return;
224
225 // Pointing clusters must have a non-zero X direction (so that they point across drift volume boundary)
226 const float pX1(std::fabs(pointingVertex1.GetDirection().GetX()));
227 const float pX2(std::fabs(pointingVertex2.GetDirection().GetX()));
228
229 if (pX1 < std::numeric_limits<float>::epsilon() || pX2 < std::numeric_limits<float>::epsilon())
230 return;
231
232 // Pointing clusters must intersect at a drift volume boundary
233 const float intersectX(0.5 * (pointingVertex1.GetPosition().GetX() + pointingVertex2.GetPosition().GetX()));
234
235 if (std::fabs(intersectX - boundaryCenterX) > maxLongitudinalDisplacementX)
236 return;
237
238 // Impact parameters
239 float rT1(0.f), rL1(0.f), rT2(0.f), rL2(0.f);
240
241 try
242 {
244 {
245 LArPointingClusterHelper::GetImpactParameters(pointingVertex1, pointingVertex2, rL1, rT1);
246 LArPointingClusterHelper::GetImpactParameters(pointingVertex2, pointingVertex1, rL2, rT2);
247 }
248 else
249 {
250 LArPointingClusterHelper::GetImpactParametersInYZ(pointingVertex1, pointingVertex2, rL1, rT1);
251 LArPointingClusterHelper::GetImpactParametersInYZ(pointingVertex2, pointingVertex1, rL2, rT2);
252 }
253 }
254 catch (const pandora::StatusCodeException &)
255 {
256 return;
257 }
258
259 const float minL((!LArGeometryHelper::IsInGap(this->GetPandora(), pointingVertex1.GetPosition(), TPC_3D) ||
260 !LArGeometryHelper::IsInGap(this->GetPandora(), pointingVertex2.GetPosition(), TPC_3D))
261 ? -1.f
263 const float dXdL1(m_useXcoordinate ? pX1 : (1.f - pX1 * pX1 > std::numeric_limits<float>::epsilon()) ? pX1 / std::sqrt(1.f - pX1 * pX1) : minL);
264 const float dXdL2(m_useXcoordinate ? pX2 : (1.f - pX2 * pX2 > std::numeric_limits<float>::epsilon()) ? pX2 / std::sqrt(1.f - pX2 * pX2) : minL);
265 const float maxL1(maxLongitudinalDisplacementX / dXdL1);
266 const float maxL2(maxLongitudinalDisplacementX / dXdL2);
267
268 if (rL1 < minL || rL1 > maxL1 || rL2 < minL || rL2 > maxL2)
269 return;
270
271 // Selection cuts on transverse impact parameters
272 const bool minPass(std::min(rT1, rT2) < m_relaxTransverseDisplacement && cosRelativeAngle > m_relaxCosRelativeAngle);
273 const bool maxPass(std::max(rT1, rT2) < m_maxTransverseDisplacement && cosRelativeAngle > m_minCosRelativeAngle);
274
275 if (!minPass && !maxPass)
276 return;
277
278 // Store this association
281
282 const float particleLength1(pointingCluster1.GetLengthSquared());
283 const float particleLength2(pointingCluster2.GetLengthSquared());
284
285 pfoAssociationMatrix[pPfo1].insert(PfoAssociationMap::value_type(pPfo2, PfoAssociation(vertexType1, vertexType2, particleLength2)));
286 pfoAssociationMatrix[pPfo2].insert(PfoAssociationMap::value_type(pPfo1, PfoAssociation(vertexType2, vertexType1, particleLength1)));
287}
288
289//------------------------------------------------------------------------------------------------------------------------------------------
290
291void StitchingCosmicRayMergingTool::SelectPfoMatches(const PfoAssociationMatrix &pfoAssociationMatrix, PfoMergeMap &pfoMatches) const
292{
293 // First step: loop over association matrix and find best associations A -> X and B -> Y
294 // =====================================================================================
295 PfoAssociationMatrix bestAssociationMatrix;
296
297 PfoVector pfoVector1;
298 for (const auto &mapEntry : pfoAssociationMatrix)
299 pfoVector1.push_back(mapEntry.first);
300 std::sort(pfoVector1.begin(), pfoVector1.end(), LArPfoHelper::SortByNHits);
301
302 for (const ParticleFlowObject *const pPfo1 : pfoVector1)
303 {
304 const PfoAssociationMap &pfoAssociationMap(pfoAssociationMatrix.at(pPfo1));
305
306 const ParticleFlowObject *pBestPfoInner(nullptr);
308
309 const ParticleFlowObject *pBestPfoOuter(nullptr);
311
312 PfoVector pfoVector2;
313 for (const auto &mapEntry : pfoAssociationMap)
314 pfoVector2.push_back(mapEntry.first);
315 std::sort(pfoVector2.begin(), pfoVector2.end(), LArPfoHelper::SortByNHits);
316
317 for (const ParticleFlowObject *const pPfo2 : pfoVector2)
318 {
319 const PfoAssociation &pfoAssociation(pfoAssociationMap.at(pPfo2));
320
321 // Inner associations
322 if (pfoAssociation.GetParent() == PfoAssociation::INNER)
323 {
324 if (pfoAssociation.GetFigureOfMerit() > bestAssociationInner.GetFigureOfMerit())
325 {
326 bestAssociationInner = pfoAssociation;
327 pBestPfoInner = pPfo2;
328 }
329 }
330
331 // Outer associations
332 if (pfoAssociation.GetParent() == PfoAssociation::OUTER)
333 {
334 if (pfoAssociation.GetFigureOfMerit() > bestAssociationOuter.GetFigureOfMerit())
335 {
336 bestAssociationOuter = pfoAssociation;
337 pBestPfoOuter = pPfo2;
338 }
339 }
340 }
341
342 if (pBestPfoInner)
343 (void)bestAssociationMatrix[pPfo1].insert(PfoAssociationMap::value_type(pBestPfoInner, bestAssociationInner));
344
345 if (pBestPfoOuter)
346 (void)bestAssociationMatrix[pPfo1].insert(PfoAssociationMap::value_type(pBestPfoOuter, bestAssociationOuter));
347 }
348
349 // Second step: make the merge if A -> X and B -> Y is in fact A -> B and B -> A
350 // =============================================================================
351 PfoVector pfoVector3;
352 for (const auto &mapEntry : bestAssociationMatrix)
353 pfoVector3.push_back(mapEntry.first);
354 std::sort(pfoVector3.begin(), pfoVector3.end(), LArPfoHelper::SortByNHits);
355
356 for (const ParticleFlowObject *const pParentPfo : pfoVector3)
357 {
358 const PfoAssociationMap &parentAssociationMap(bestAssociationMatrix.at(pParentPfo));
359
360 PfoVector pfoVector4;
361 for (const auto &mapEntry : parentAssociationMap)
362 pfoVector4.push_back(mapEntry.first);
363 std::sort(pfoVector4.begin(), pfoVector4.end(), LArPfoHelper::SortByNHits);
364
365 for (const ParticleFlowObject *const pDaughterPfo : pfoVector4)
366 {
367 const PfoAssociation &parentToDaughterAssociation(parentAssociationMap.at(pDaughterPfo));
368 PfoAssociationMatrix::const_iterator iter5 = bestAssociationMatrix.find(pDaughterPfo);
369
370 if (bestAssociationMatrix.end() == iter5)
371 continue;
372
373 const PfoAssociationMap &daughterAssociationMap(iter5->second);
374
375 PfoAssociationMap::const_iterator iter6 = daughterAssociationMap.find(pParentPfo);
376 if (daughterAssociationMap.end() == iter6)
377 continue;
378
379 const PfoAssociation &daughterToParentAssociation(iter6->second);
380
381 if (parentToDaughterAssociation.GetParent() == daughterToParentAssociation.GetDaughter() &&
382 parentToDaughterAssociation.GetDaughter() == daughterToParentAssociation.GetParent())
383 {
384 pfoMatches[pParentPfo].push_back(pDaughterPfo);
385 }
386 }
387 }
388}
389
390//------------------------------------------------------------------------------------------------------------------------------------------
391
393{
394 PfoSet vetoSet;
395
396 PfoVector inputPfoVector;
397 for (const auto &mapEntry : pfoMatches)
398 inputPfoVector.push_back(mapEntry.first);
399 std::sort(inputPfoVector.begin(), inputPfoVector.end(), LArPfoHelper::SortByNHits);
400
401 for (const ParticleFlowObject *const pInputPfo : inputPfoVector)
402 {
403 const PfoList &pfoList(pfoMatches.at(pInputPfo));
404
405 for (const ParticleFlowObject *const pSeedPfo : pfoList)
406 {
407 if (vetoSet.count(pSeedPfo))
408 continue;
409
410 PfoList mergeList;
411 this->CollectAssociatedPfos(pSeedPfo, pSeedPfo, pfoMatches, vetoSet, mergeList);
412
413 vetoSet.insert(pSeedPfo);
414 PfoList &selectedPfoList(pfoMerges[pSeedPfo]);
415 selectedPfoList.push_back(pSeedPfo);
416
417 for (const ParticleFlowObject *const pAssociatedPfo : mergeList)
418 {
419 // Check if particle has already been counted
420 if (vetoSet.count(pAssociatedPfo) || (selectedPfoList.end() != std::find(selectedPfoList.begin(), selectedPfoList.end(), pAssociatedPfo)))
421 throw StatusCodeException(STATUS_CODE_FAILURE);
422
423 vetoSet.insert(pAssociatedPfo);
424 selectedPfoList.push_back(pAssociatedPfo);
425 }
426 }
427 }
428}
429
430//------------------------------------------------------------------------------------------------------------------------------------------
431
433 const ParticleFlowObject *const pCurrentPfo, const PfoMergeMap &pfoMergeMap, const PfoSet &vetoSet, PfoList &associatedList) const
434{
435 if (vetoSet.count(pCurrentPfo))
436 return;
437
438 PfoMergeMap::const_iterator iter1 = pfoMergeMap.find(pCurrentPfo);
439
440 if (pfoMergeMap.end() == iter1)
441 return;
442
443 for (PfoList::const_iterator iter2 = iter1->second.begin(), iterEnd2 = iter1->second.end(); iter2 != iterEnd2; ++iter2)
444 {
445 const ParticleFlowObject *const pAssociatedPfo = *iter2;
446
447 if (pAssociatedPfo == pSeedPfo)
448 continue;
449
450 if (associatedList.end() != std::find(associatedList.begin(), associatedList.end(), pAssociatedPfo))
451 continue;
452
453 associatedList.push_back(pAssociatedPfo);
454
455 this->CollectAssociatedPfos(pSeedPfo, pAssociatedPfo, pfoMergeMap, vetoSet, associatedList);
456 }
457}
458
459//------------------------------------------------------------------------------------------------------------------------------------------
460
462 const PfoMergeMap &inputPfoMerges, PfoMergeMap &outputPfoMerges) const
463{
464 PfoVector inputPfoVector;
465 for (const auto &mapEntry : inputPfoMerges)
466 inputPfoVector.push_back(mapEntry.first);
467 std::sort(inputPfoVector.begin(), inputPfoVector.end(), LArPfoHelper::SortByNHits);
468
469 for (const ParticleFlowObject *const pInputPfo : inputPfoVector)
470 {
471 const PfoList &pfoList(inputPfoMerges.at(pInputPfo));
472
473 float bestLength(0.f);
474 const ParticleFlowObject *pVertexPfo = nullptr;
475
476 for (PfoList::const_iterator iter1 = pfoList.begin(), iterEnd = pfoList.end(); iter1 != iterEnd; ++iter1)
477 {
478 const ParticleFlowObject *const pPfo1(*iter1);
479 PfoToLArTPCMap::const_iterator tpcIter1 = pfoToLArTPCMap.find(pPfo1);
480 ThreeDPointingClusterMap::const_iterator pointingIter1 = pointingClusterMap.find(pPfo1);
481
482 if (pfoToLArTPCMap.end() == tpcIter1 || pointingClusterMap.end() == pointingIter1)
483 throw StatusCodeException(STATUS_CODE_FAILURE);
484
485 const LArTPC *const pLArTPC1(tpcIter1->second);
486 const LArPointingCluster &pointingCluster1(pointingIter1->second);
487
488 for (PfoList::const_iterator iter2 = iter1; iter2 != iterEnd; ++iter2)
489 {
490 const ParticleFlowObject *const pPfo2(*iter2);
491 PfoToLArTPCMap::const_iterator tpcIter2 = pfoToLArTPCMap.find(pPfo2);
492 ThreeDPointingClusterMap::const_iterator pointingIter2 = pointingClusterMap.find(pPfo2);
493
494 if (pfoToLArTPCMap.end() == tpcIter2 || pointingClusterMap.end() == pointingIter2)
495 throw StatusCodeException(STATUS_CODE_FAILURE);
496
497 const LArTPC *const pLArTPC2(tpcIter2->second);
498 const LArPointingCluster &pointingCluster2(pointingIter2->second);
499
500 if (pLArTPC1 == pLArTPC2)
501 continue;
502
503 const float thisLength(LArStitchingHelper::GetTPCDisplacement(*pLArTPC1, *pLArTPC2));
504
505 if (thisLength < bestLength)
506 continue;
507
508 bestLength = thisLength;
509
510 try
511 {
512 pVertexPfo = nullptr;
513
514 LArPointingCluster::Vertex nearVertex1, nearVertex2;
515 LArStitchingHelper::GetClosestVertices(*pLArTPC1, *pLArTPC2, pointingCluster1, pointingCluster2, nearVertex1, nearVertex2);
516
517 const LArPointingCluster::Vertex &farVertex1(
518 nearVertex1.IsInnerVertex() ? pointingCluster1.GetOuterVertex() : pointingCluster1.GetInnerVertex());
519 const LArPointingCluster::Vertex &farVertex2(
520 nearVertex2.IsInnerVertex() ? pointingCluster2.GetOuterVertex() : pointingCluster2.GetInnerVertex());
521 const float deltaY(farVertex1.GetPosition().GetY() - farVertex2.GetPosition().GetY());
522
523 if (std::fabs(deltaY) < std::numeric_limits<float>::epsilon())
524 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
525
526 pVertexPfo = ((deltaY > 0.f) ? pPfo1 : pPfo2);
527 }
528 catch (const pandora::StatusCodeException &)
529 {
530 }
531 }
532 }
533
534 if (pVertexPfo)
535 outputPfoMerges[pVertexPfo].insert(outputPfoMerges[pVertexPfo].begin(), pfoList.begin(), pfoList.end());
536 }
537}
538
539//------------------------------------------------------------------------------------------------------------------------------------------
540
541void StitchingCosmicRayMergingTool::StitchPfos(const MasterAlgorithm *const pAlgorithm, const ThreeDPointingClusterMap &pointingClusterMap,
542 const PfoMergeMap &pfoMerges, PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map) const
543{
544 PfoVector pfoVectorToEnlarge;
545 for (const auto &mapEntry : pfoMerges)
546 pfoVectorToEnlarge.push_back(mapEntry.first);
547 std::sort(pfoVectorToEnlarge.begin(), pfoVectorToEnlarge.end(), LArPfoHelper::SortByNHits);
548
549 for (const ParticleFlowObject *const pPfoToEnlarge : pfoVectorToEnlarge)
550 {
551 const PfoList &pfoList(pfoMerges.at(pPfoToEnlarge));
552 const PfoVector pfoVector(pfoList.begin(), pfoList.end());
553 PfoToPointingVertexMatrix pfoToPointingVertexMatrix;
554 float x0(0.f);
555
557 {
558 try
559 {
560 // If stitching contributions are inconsistent, abort
561 if (!this->CalculateX0(pfoToLArTPCMap, pointingClusterMap, pfoVector, x0, pfoToPointingVertexMatrix))
562 continue;
563 }
564 catch (const pandora::StatusCodeException &)
565 {
566 continue;
567 }
568 }
569
570 // ATTN: shift the pfos one at a time
571 PfoSet shiftedPfos;
572 for (PfoVector::const_iterator iterI = pfoVector.begin(); iterI != pfoVector.end(); ++iterI)
573 {
574 const ParticleFlowObject *const pPfoI(*iterI);
575 const LArTPC *const pLArTPCI(pfoToLArTPCMap.at(pPfoI));
576
577 for (PfoVector::const_iterator iterJ = std::next(iterI); iterJ != pfoVector.end(); ++iterJ)
578 {
579 const ParticleFlowObject *const pPfoJ(*iterJ);
580 const LArTPC *const pLArTPCJ(pfoToLArTPCMap.at(pPfoJ));
581
582 if (!LArStitchingHelper::CanTPCsBeStitched(*pLArTPCI, *pLArTPCJ))
583 continue;
584
585 if (std::find(shiftedPfos.begin(), shiftedPfos.end(), pPfoI) == shiftedPfos.end())
586 {
588 this->ShiftPfo(pAlgorithm, pPfoI, pPfoJ, x0, pfoToLArTPCMap, pfoToPointingVertexMatrix);
589
590 shiftedPfos.insert(pPfoI);
591 }
592
593 if (std::find(shiftedPfos.begin(), shiftedPfos.end(), pPfoJ) == shiftedPfos.end())
594 {
596 this->ShiftPfo(pAlgorithm, pPfoJ, pPfoI, x0, pfoToLArTPCMap, pfoToPointingVertexMatrix);
597
598 shiftedPfos.insert(pPfoJ);
599 }
600 }
601 }
602
603 // now merge all pfos
604 for (const ParticleFlowObject *const pPfoToDelete : shiftedPfos)
605 {
606 if (pPfoToDelete == pPfoToEnlarge)
607 continue;
608
609 pAlgorithm->StitchPfos(pPfoToEnlarge, pPfoToDelete, pfoToLArTPCMap);
610 }
611
612 stitchedPfosToX0Map.insert(PfoToFloatMap::value_type(pPfoToEnlarge, x0));
613 }
614}
615
616//------------------------------------------------------------------------------------------------------------------------------------------
617
618void StitchingCosmicRayMergingTool::ShiftPfo(const MasterAlgorithm *const pAlgorithm, const ParticleFlowObject *const pPfoToShift,
619 const ParticleFlowObject *const pMatchedPfo, const float x0, const PfoToLArTPCMap &pfoToLArTPCMap,
620 const PfoToPointingVertexMatrix &pfoToPointingVertexMatrix) const
621{
622 // get stitching vertex for the pfo to be shifted
623 const PfoToPointingVertexMatrix::const_iterator pfoToPointingVertexMatrixIter(pfoToPointingVertexMatrix.find(pPfoToShift));
624 const LArPointingCluster::Vertex stitchingVertex(pfoToPointingVertexMatrixIter->second.at(pMatchedPfo));
625
626 const LArTPC *const pShiftLArTPC(pfoToLArTPCMap.at(pPfoToShift));
627 const LArTPC *const pMatchedLArTPC(pfoToLArTPCMap.at(pMatchedPfo));
628
629 // determine shift sign from the relative position of stitching vertex and the relevant TPC boundary position
630 const float tpcBoundaryCenterX(LArStitchingHelper::GetTPCBoundaryCenterX(*pShiftLArTPC, *pMatchedLArTPC));
631 float tpcBoundaryX(0.f);
632
633 if (pShiftLArTPC->GetCenterX() < tpcBoundaryCenterX)
634 {
635 tpcBoundaryX = pShiftLArTPC->GetCenterX() + (pShiftLArTPC->GetWidthX() / 2.f);
636 }
637 else
638 {
639 tpcBoundaryX = pShiftLArTPC->GetCenterX() - (pShiftLArTPC->GetWidthX() / 2.f);
640 }
641
642 const float positionShiftSign = stitchingVertex.GetPosition().GetX() < tpcBoundaryX ? 1.f : -1.f;
643
644 // ATTN: No CPA/APA sign needed since x0 calculation corresponds to an APA
646 metadata.m_propertiesToAdd["X0"] = x0;
647
648 // ATTN: Set the X0 shift for all particles in hierarchy
649 PfoList downstreamPfoList;
650 LArPfoHelper::GetAllDownstreamPfos(pPfoToShift, downstreamPfoList);
651
652 for (const ParticleFlowObject *const pHierarchyPfo : downstreamPfoList)
653 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*pAlgorithm, pHierarchyPfo, metadata));
654
655 const float signedX0(std::fabs(x0) * positionShiftSign);
656
657 pAlgorithm->ShiftPfoHierarchy(pPfoToShift, pfoToLArTPCMap, signedX0);
658}
659
660//------------------------------------------------------------------------------------------------------------------------------------------
661
662bool StitchingCosmicRayMergingTool::CalculateX0(const PfoToLArTPCMap &pfoToLArTPCMap, const ThreeDPointingClusterMap &pointingClusterMap,
663 const PfoVector &pfoVector, float &x0, PfoToPointingVertexMatrix &pfoToPointingVertexMatrix) const
664{
665 float sumX(0.f), sumN(0.f);
666
667 for (PfoVector::const_iterator iter1 = pfoVector.begin(), iterEnd = pfoVector.end(); iter1 != iterEnd; ++iter1)
668 {
669 const ParticleFlowObject *const pPfo1(*iter1);
670 PfoToLArTPCMap::const_iterator tpcIter1 = pfoToLArTPCMap.find(pPfo1);
671 ThreeDPointingClusterMap::const_iterator pointingIter1 = pointingClusterMap.find(pPfo1);
672
673 if (pfoToLArTPCMap.end() == tpcIter1 || pointingClusterMap.end() == pointingIter1)
674 throw StatusCodeException(STATUS_CODE_FAILURE);
675
676 const LArTPC *const pLArTPC1(tpcIter1->second);
677 const LArPointingCluster &pointingCluster1(pointingIter1->second);
678
679 for (PfoVector::const_iterator iter2 = std::next(iter1); iter2 != iterEnd; ++iter2)
680 {
681 const ParticleFlowObject *const pPfo2(*iter2);
682 PfoToLArTPCMap::const_iterator tpcIter2 = pfoToLArTPCMap.find(pPfo2);
683 ThreeDPointingClusterMap::const_iterator pointingIter2 = pointingClusterMap.find(pPfo2);
684
685 if (pfoToLArTPCMap.end() == tpcIter2 || pointingClusterMap.end() == pointingIter2)
686 throw StatusCodeException(STATUS_CODE_FAILURE);
687
688 const LArTPC *const pLArTPC2(tpcIter2->second);
689 const LArPointingCluster &pointingCluster2(pointingIter2->second);
690
691 if (!LArStitchingHelper::CanTPCsBeStitched(*pLArTPC1, *pLArTPC2))
692 continue;
693
694 // Calculate X0 for the closest pair of vertices
695 LArPointingCluster::Vertex pointingVertex1, pointingVertex2;
696 try
697 {
698 LArStitchingHelper::GetClosestVertices(*pLArTPC1, *pLArTPC2, pointingCluster1, pointingCluster2, pointingVertex1, pointingVertex2);
699
700 // Record pfo1 stitching vertex for pfo1<->pfo2 match, used to determine shifting direction in later step
701 const PfoToPointingVertexMatrix::iterator pfoToPointingVertexMatrixIter1(pfoToPointingVertexMatrix.find(pPfo1));
702 if (pfoToPointingVertexMatrixIter1 == pfoToPointingVertexMatrix.end())
703 {
704 // No matches present in map, add pfo1<->pfo2 match
705 const PfoToPointingVertexMap pfoToPointingVertexMap({{pPfo2, pointingVertex1}});
706 (void)pfoToPointingVertexMatrix.insert(PfoToPointingVertexMatrix::value_type(pPfo1, pfoToPointingVertexMap));
707 }
708 else
709 {
710 // ATTN: another match for a different TPC boundary may be present, add pfo1<->pfo2 match
711 PfoToPointingVertexMap &pfoToPointingVertexMap(pfoToPointingVertexMatrixIter1->second);
712 const PfoToPointingVertexMap::iterator pfoToPointingVertexMapIter(pfoToPointingVertexMap.find(pPfo2));
713 if (pfoToPointingVertexMapIter == pfoToPointingVertexMap.end())
714 {
715 (void)pfoToPointingVertexMap.insert(PfoToPointingVertexMap::value_type(pPfo2, pointingVertex1));
716 }
717 else
718 {
719 if ((pfoToPointingVertexMapIter->second.GetPosition() - pointingVertex1.GetPosition()).GetMagnitude() >
720 std::numeric_limits<float>::epsilon())
721 throw StatusCodeException(STATUS_CODE_FAILURE);
722 }
723 }
724
725 // Record pfo2 stitching vertex for pfo1<->pfo2 match, used to determine shifting direction in later step
726 const PfoToPointingVertexMatrix::iterator pfoToPointingVertexMatrixIter2(pfoToPointingVertexMatrix.find(pPfo2));
727 if (pfoToPointingVertexMatrixIter2 == pfoToPointingVertexMatrix.end())
728 {
729 // No matches present in map, add pfo1<->pfo2 match
730 const PfoToPointingVertexMap pfoToPointingVertexMap({{pPfo1, pointingVertex2}});
731 (void)pfoToPointingVertexMatrix.insert(PfoToPointingVertexMatrix::value_type(pPfo2, pfoToPointingVertexMap));
732 }
733 else
734 {
735 // ATTN: another match for a different TPC boundary may be present, add pfo1<->pfo2 match
736 PfoToPointingVertexMap &pfoToPointingVertexMap(pfoToPointingVertexMatrixIter2->second);
737 const PfoToPointingVertexMap::iterator pfoToPointingVertexMapIter(pfoToPointingVertexMap.find(pPfo1));
738 if (pfoToPointingVertexMapIter == pfoToPointingVertexMap.end())
739 {
740 (void)pfoToPointingVertexMap.insert(PfoToPointingVertexMap::value_type(pPfo1, pointingVertex2));
741 }
742 else
743 {
744 if ((pfoToPointingVertexMapIter->second.GetPosition() - pointingVertex2.GetPosition()).GetMagnitude() >
745 std::numeric_limits<float>::epsilon())
746 throw StatusCodeException(STATUS_CODE_FAILURE);
747 }
748 }
749
750 const float tpcBoundaryCenterX(LArStitchingHelper::GetTPCBoundaryCenterX(*pLArTPC1, *pLArTPC2));
751 const bool isCPAStitch(pLArTPC1->GetCenterX() < tpcBoundaryCenterX ? !pLArTPC1->IsDriftInPositiveX() : !pLArTPC2->IsDriftInPositiveX());
752 float thisX0(LArStitchingHelper::CalculateX0(*pLArTPC1, *pLArTPC2, pointingVertex1, pointingVertex2));
753
754 thisX0 *= isCPAStitch ? -1.f : 1.f;
755
756 // If multiple boundaries identified, check if stitching contribution is consistent
757 if ((sumN > std::numeric_limits<float>::epsilon()) && (sumX > std::numeric_limits<float>::epsilon()))
758 {
759 const float fractionalDiff(std::fabs((sumX - (thisX0 * sumN)) / sumX));
760
761 if ((fractionalDiff > m_maxX0FractionalDeviation) && (std::fabs(sumX / sumN) > m_boundaryToleranceWidth))
762 return false;
763 }
764
765 sumX += thisX0;
766 sumN += 1.f;
767 }
768 catch (const pandora::StatusCodeException &statusCodeException)
769 {
770 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
771 std::cout << "StitchingCosmicRayMergingTool: Attempting to stitch a pfo with multiple vertices for the same match" << std::endl;
772 }
773 }
774 }
775
776 if ((sumN < std::numeric_limits<float>::epsilon()) || (std::fabs(sumX) < std::numeric_limits<float>::epsilon()))
777 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
778
779 x0 = (sumX / sumN);
780
781 return true;
782}
783
784//------------------------------------------------------------------------------------------------------------------------------------------
785//------------------------------------------------------------------------------------------------------------------------------------------
786
788 m_parent(parent),
789 m_daughter(daughter),
790 m_fom(fom)
791{
792}
793
794//------------------------------------------------------------------------------------------------------------------------------------------
795
800
801//------------------------------------------------------------------------------------------------------------------------------------------
802
807
808//------------------------------------------------------------------------------------------------------------------------------------------
809
814
815//------------------------------------------------------------------------------------------------------------------------------------------
816//------------------------------------------------------------------------------------------------------------------------------------------
817
819{
821 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ThreeDStitchingMode", m_useXcoordinate));
822
823 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
824 XmlHelper::ReadValue(xmlHandle, "AlwaysApplyT0Calculation", m_alwaysApplyT0Calculation));
825
827 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HalfWindowLayers", m_halfWindowLayers));
828
829 float minLength(std::sqrt(m_minLengthSquared));
830 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinPfoLength", minLength));
831 m_minLengthSquared = minLength * minLength;
832
834 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCosRelativeAngle", m_minCosRelativeAngle));
835
836 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
837 XmlHelper::ReadValue(xmlHandle, "RelaxMinLongitudinalDisplacement", m_relaxMinLongitudinalDisplacement));
838
839 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
840 XmlHelper::ReadValue(xmlHandle, "MaxLongitudinalDisplacementX", m_maxLongitudinalDisplacementX));
841
842 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
843 XmlHelper::ReadValue(xmlHandle, "MaxTransverseDisplacement", m_maxTransverseDisplacement));
844
845 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
846 XmlHelper::ReadValue(xmlHandle, "LooserMinCosRelativeAngle", m_relaxCosRelativeAngle));
847
848 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
849 XmlHelper::ReadValue(xmlHandle, "LooserMaxTransverseDisplacement", m_relaxTransverseDisplacement));
850
851 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinNCaloHits3D", m_minNCaloHits3D));
852
853 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
854 XmlHelper::ReadValue(xmlHandle, "MaxX0FractionalDeviation", m_maxX0FractionalDeviation));
855
857 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "BoundaryToleranceWidth", m_boundaryToleranceWidth));
858
859 return STATUS_CODE_SUCCESS;
860}
861
862} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the geometry helper class.
Header file for the pfo helper class.
Header file for the helper class for multiple drift volumes.
Header file for the lar three dimensional sliding fit result class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
static bool IsInGap(const pandora::Pandora &pandora, const pandora::CartesianVector &testPoint2D, const pandora::HitType hitType, const float gapTolerance=0.f)
Whether a 2D test point lies in a registered gap with the associated hit type.
static bool IsFinalState(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a primary parent particle.
static void GetThreeDClusterList(const pandora::ParticleFlowObject *const pPfo, pandora::ClusterList &clusterList)
Get the list of 3D clusters from an input pfo.
static void GetAllDownstreamPfos(const pandora::PfoList &inputPfoList, pandora::PfoList &outputPfoList)
Get a flat list of all pfos, recursively, of all daughters associated with those pfos in an input lis...
static bool IsTrack(const pandora::ParticleFlowObject *const pPfo)
Return track flag based on Pfo Particle ID.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
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.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
bool IsInnerVertex() const
Is this the inner vertex.
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
static void GetImpactParametersInYZ(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices using yz-coordinates.
LArPointingCluster class.
const Vertex & GetInnerVertex() const
Get the inner vertex.
const Vertex & GetOuterVertex() const
Get the outer vertex.
float GetLengthSquared() const
Get length squared of pointing cluster.
static bool SortTPCs(const pandora::LArTPC *const pLhs, const pandora::LArTPC *const pRhs)
Sort tpcs by central positions.
static bool CanTPCsBeStitched(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Whether particles from a given pair of tpcs can be stitched together.
static float GetTPCBoundaryWidthX(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Determine width in X at the boundary between a pair of tpcs.
static float GetTPCBoundaryCenterX(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Determine centre in X at the boundary between a pair of tpcs.
static float GetTPCDisplacement(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC)
Calculate distance between central positions of a pair of tpcs.
static void GetClosestVertices(const pandora::LArTPC &larTPC1, const pandora::LArTPC &larTPC2, const LArPointingCluster &pointingCluster1, const LArPointingCluster &pointingCluster2, LArPointingCluster::Vertex &closestVertex1, LArPointingCluster::Vertex &closestVertex2)
Given a pair of pointing clusters, find the pair of vertices with smallest yz-separation.
static float CalculateX0(const pandora::LArTPC &firstTPC, const pandora::LArTPC &secondTPC, const LArPointingCluster::Vertex &firstVertex, const LArPointingCluster::Vertex &secondVertex)
Calculate X0 for a pair of vertices.
MasterAlgorithm class.
void StitchPfos(const pandora::ParticleFlowObject *const pPfoToEnlarge, const pandora::ParticleFlowObject *const pPfoToDelete, PfoToLArTPCMap &pfoToLArTPCMap) const
Stitch together a pair of pfos.
void ShiftPfoHierarchy(const pandora::ParticleFlowObject *const pParentPfo, const PfoToLArTPCMap &pfoToLArTPCMap, const float x0) const
Shift a Pfo hierarchy by a specified x0 value.
PfoAssociation(const VertexType parent, const VertexType daughter, const float fom)
Constructor.
void SelectPfoMerges(const PfoMergeMap &pfoMatches, PfoMergeMap &pfoMerges) const
Create an initial map of Pfo merges to be made.
std::unordered_map< const pandora::ParticleFlowObject *, pandora::PfoList > PfoMergeMap
float m_maxX0FractionalDeviation
The maximum allowed fractional difference of an X0 contribution for matches to be stitched.
void Run(const MasterAlgorithm *const pAlgorithm, const pandora::PfoList *const pMultiPfoList, PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map)
Run the algorithm tool.
std::unordered_map< const pandora::ParticleFlowObject *, PfoAssociationMap > PfoAssociationMatrix
bool CalculateX0(const PfoToLArTPCMap &pfoToLArTPCMap, const ThreeDPointingClusterMap &pointingClusterMap, const pandora::PfoVector &pfoVector, float &x0, PfoToPointingVertexMatrix &pfoToPointingVertexMatrix) const
Calculate x0 shift for a group of associated Pfos.
std::unordered_map< const pandora::ParticleFlowObject *, PfoAssociation > PfoAssociationMap
float m_boundaryToleranceWidth
The distance from the APA/CPA boundary inside which the deviation consideration is ignored.
void StitchPfos(const MasterAlgorithm *const pAlgorithm, const ThreeDPointingClusterMap &pointingClusterMap, const PfoMergeMap &pfoMerges, PfoToLArTPCMap &pfoToLArTPCMap, PfoToFloatMap &stitchedPfosToX0Map) const
Apply X0 corrections, and then stitch together Pfos.
void CreatePfoMatches(const LArTPCToPfoMap &larTPCToPfoMap, const ThreeDPointingClusterMap &pointingClusterMap, PfoAssociationMatrix &pfoAssociationMatrix) const
Create associations between Pfos using 3D pointing clusters.
float m_relaxMinLongitudinalDisplacement
The minimum value of the longitudinal impact parameter for association if both verticies fall in the ...
void CollectAssociatedPfos(const pandora::ParticleFlowObject *const pSeedPfo, const pandora::ParticleFlowObject *const pCurrentPfo, const PfoMergeMap &pfoMerges, const pandora::PfoSet &vetoSet, pandora::PfoList &associatedList) const
Collect up associations between Pfos.
std::unordered_map< const pandora::ParticleFlowObject *, LArPointingCluster > ThreeDPointingClusterMap
void OrderPfoMerges(const PfoToLArTPCMap &pfoToLArTPCMap, const ThreeDPointingClusterMap &pointingClusterMap, const PfoMergeMap &inputPfoMerges, PfoMergeMap &outputPfoMerges) const
Identify the vertex Pfo and then re-order the map of merges so that the vertex Pfo will be enlarged.
void BuildPointingClusterMaps(const pandora::PfoList &inputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, ThreeDPointingClusterMap &pointingClusterMap) const
Build a 3D pointing cluster for each Pfo.
void BuildTPCMaps(const pandora::PfoList &inputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, LArTPCToPfoMap &larTPCToPfoMap) const
Build a list of Pfos for each tpc.
void SelectPfoMatches(const PfoAssociationMatrix &pfoAssociationMatrix, PfoMergeMap &pfoSelectedMatches) const
Select the best associations between Pfos; create a mapping between associated Pfos,...
std::unordered_map< const pandora::ParticleFlowObject *, LArPointingCluster::Vertex > PfoToPointingVertexMap
std::unordered_map< const pandora::ParticleFlowObject *, PfoToPointingVertexMap > PfoToPointingVertexMatrix
void ShiftPfo(const MasterAlgorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pPfoToShift, const pandora::ParticleFlowObject *const pMatchedPfo, const float x0, const PfoToLArTPCMap &pfoToLArTPCMap, const PfoToPointingVertexMatrix &pfoToPointingVertexMatrix) const
Shift a pfo given its pfo stitching pair.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
std::unordered_map< const pandora::LArTPC *, pandora::PfoList > LArTPCToPfoMap
void SelectPrimaryPfos(const pandora::PfoList *pInputPfoList, const PfoToLArTPCMap &pfoToLArTPCMap, pandora::PfoList &outputPfoList) const
Select primary Pfos from the input list of Pfos.
float GetX() const
Get the cartesian x coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
LArTPC class.
Definition LArTPC.h:26
bool IsDriftInPositiveX() const
Whether the electron drift is in the positive x direction.
Definition LArTPC.h:266
float GetCenterX() const
Get center in x, units mm.
Definition LArTPC.h:175
float GetWidthX() const
Get the width in x, units mm.
Definition LArTPC.h:196
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
StatusCode AlterMetadata(const object_creation::ParticleFlowObject::Metadata &metadata)
Alter particle flow object metadata parameters.
const std::string & GetType() const
Get the type.
Definition Process.h:102
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
const std::string & GetInstanceName() const
Get the instance name.
Definition Process.h:109
StatusCodeException class.
StatusCode GetStatusCode() const
Get status code.
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoToFloatMap
std::unordered_map< const pandora::ParticleFlowObject *, const pandora::LArTPC * > PfoToLArTPCMap
std::vector< const LArTPC * > LArTPCVector
std::unordered_set< const ParticleFlowObject * > PfoSet
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< const ParticleFlowObject * > PfoVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList