Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
DeltaRayMatchingAlgorithm.cc
Go to the documentation of this file.
1
10
14
16
18
19using namespace pandora;
20
21namespace lar_content
22{
23
25 m_minCaloHitsPerCluster(3),
26 m_xOverlapWindow(1.f),
27 m_distanceForMatching(5.f),
28 m_pseudoChi2Cut(3.f),
29 m_searchRegion1D(5.f)
30{
31}
32
33//------------------------------------------------------------------------------------------------------------------------------------------
34
36{
37 PfoVector pfoVector;
38 this->GetAllPfos(m_parentPfoListName, pfoVector);
39
40 if (pfoVector.empty())
41 {
43 std::cout << "DeltaRayMatchingAlgorithm: pfo list " << m_parentPfoListName << " unavailable." << std::endl;
44
45 return STATUS_CODE_SUCCESS;
46 }
47
49
50 ClusterLengthMap clusterLengthMap;
51 this->ThreeViewMatching(clusterLengthMap);
52 this->TwoViewMatching(clusterLengthMap);
53 this->OneViewMatching(clusterLengthMap);
54
56
57 return STATUS_CODE_SUCCESS;
58}
59
60//------------------------------------------------------------------------------------------------------------------------------------------
61
69
70//------------------------------------------------------------------------------------------------------------------------------------------
71
72void DeltaRayMatchingAlgorithm::InitializeNearbyClusterMap(const std::string &clusterListName, ClusterToClustersMap &nearbyClusters)
73{
74 const ClusterList *pClusterList = NULL;
75 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, clusterListName, pClusterList))
76
77 if ((NULL == pClusterList) || pClusterList->empty())
78 return;
79
80 HitToClusterMap hitToClusterMap;
81 CaloHitList allCaloHits;
82
83 for (const Cluster *const pCluster : *pClusterList)
84 {
85 CaloHitList daughterHits;
86 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
87 allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
88
89 for (const CaloHit *const pCaloHit : daughterHits)
90 (void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
91 }
92
93 HitKDTree2D kdTree;
94 HitKDNode2DList hitKDNode2DList;
95
96 KDTreeBox hitsBoundingRegion2D(fill_and_bound_2d_kd_tree(allCaloHits, hitKDNode2DList));
97 kdTree.build(hitKDNode2DList, hitsBoundingRegion2D);
98
99 for (const Cluster *const pCluster : *pClusterList)
100 {
101 CaloHitList daughterHits;
102 pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
103
104 for (const CaloHit *const pCaloHit : daughterHits)
105 {
107
108 HitKDNode2DList found;
109 kdTree.search(searchRegionHits, found);
110
111 for (const auto &hit : found)
112 {
113 ClusterList &nearbyClusterList(nearbyClusters[pCluster]);
114 const Cluster *const pNearbyCluster(hitToClusterMap.at(hit.data));
115
116 if (nearbyClusterList.end() == std::find(nearbyClusterList.begin(), nearbyClusterList.end(), pNearbyCluster))
117 nearbyClusterList.push_back(pNearbyCluster);
118 }
119 }
120 }
121}
122
123//------------------------------------------------------------------------------------------------------------------------------------------
124
131
132//------------------------------------------------------------------------------------------------------------------------------------------
133
134void DeltaRayMatchingAlgorithm::GetAllPfos(const std::string &inputPfoListName, PfoVector &pfoVector) const
135{
136 const PfoList *pPfoList = NULL;
137 PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, inputPfoListName, pPfoList));
138
139 if (NULL == pPfoList)
140 return;
141
142 for (PfoList::const_iterator iter = pPfoList->begin(), iterEnd = pPfoList->end(); iter != iterEnd; ++iter)
143 pfoVector.push_back(*iter);
144
145 std::sort(pfoVector.begin(), pfoVector.end(), LArPfoHelper::SortByNHits);
146}
147
148//------------------------------------------------------------------------------------------------------------------------------------------
149
150void DeltaRayMatchingAlgorithm::GetTrackPfos(const std::string &inputPfoListName, PfoVector &pfoVector) const
151{
152 PfoVector inputVector;
153 this->GetAllPfos(inputPfoListName, inputVector);
154
155 for (PfoVector::const_iterator iter = inputVector.begin(), iterEnd = inputVector.end(); iter != iterEnd; ++iter)
156 {
157 const ParticleFlowObject *const pPfo = *iter;
158
159 if (!LArPfoHelper::IsTrack(pPfo))
160 continue;
161
162 pfoVector.push_back(pPfo);
163 }
164
165 // ATTN Track pfo list is sorted only because the inputVector is sorted
166}
167
168//------------------------------------------------------------------------------------------------------------------------------------------
169
170void DeltaRayMatchingAlgorithm::GetClusters(const std::string &inputClusterListName, pandora::ClusterVector &clusterVector) const
171{
172 const ClusterList *pClusterList = NULL;
174 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, inputClusterListName, pClusterList))
175
176 if (NULL == pClusterList)
177 return;
178
179 for (ClusterList::const_iterator cIter = pClusterList->begin(), cIterEnd = pClusterList->end(); cIter != cIterEnd; ++cIter)
180 {
181 const Cluster *const pCluster = *cIter;
182
183 if (!pCluster->IsAvailable() || (pCluster->GetNCaloHits() < m_minCaloHitsPerCluster))
184 continue;
185
186 clusterVector.push_back(pCluster);
187 }
188
189 std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
190}
191
192//------------------------------------------------------------------------------------------------------------------------------------------
193
195{
196 ClusterVector clustersU, clustersV, clustersW;
197 this->GetClusters(m_inputClusterListNameU, clustersU);
198 this->GetClusters(m_inputClusterListNameV, clustersV);
199 this->GetClusters(m_inputClusterListNameW, clustersW);
200
201 PfoLengthMap pfoLengthMap;
202 ParticleList initialParticleList, finalParticleList;
203 this->ThreeViewMatching(clustersU, clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
204 this->SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
205 this->CreateParticles(finalParticleList);
206}
207
208//------------------------------------------------------------------------------------------------------------------------------------------
209
211{
212 ClusterVector clustersU, clustersV, clustersW;
213 this->GetClusters(m_inputClusterListNameU, clustersU);
214 this->GetClusters(m_inputClusterListNameV, clustersV);
215 this->GetClusters(m_inputClusterListNameW, clustersW);
216
217 PfoLengthMap pfoLengthMap;
218 ParticleList initialParticleList, finalParticleList;
219 this->TwoViewMatching(clustersU, clustersV, clusterLengthMap, pfoLengthMap, initialParticleList);
220 this->TwoViewMatching(clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
221 this->TwoViewMatching(clustersW, clustersU, clusterLengthMap, pfoLengthMap, initialParticleList);
222 this->SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
223 this->CreateParticles(finalParticleList);
224}
225
226//------------------------------------------------------------------------------------------------------------------------------------------
227
229{
230 ClusterVector clustersU, clustersV, clustersW;
231 this->GetClusters(m_inputClusterListNameU, clustersU);
232 this->GetClusters(m_inputClusterListNameV, clustersV);
233 this->GetClusters(m_inputClusterListNameW, clustersW);
234
235 PfoLengthMap pfoLengthMap;
236 ParticleList initialParticleList, finalParticleList;
237 this->ThreeViewMatching(clustersU, clustersV, clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
238 this->OneViewMatching(clustersU, clusterLengthMap, pfoLengthMap, initialParticleList);
239 this->OneViewMatching(clustersV, clusterLengthMap, pfoLengthMap, initialParticleList);
240 this->OneViewMatching(clustersW, clusterLengthMap, pfoLengthMap, initialParticleList);
241 this->SelectParticles(initialParticleList, clusterLengthMap, finalParticleList);
242 this->CreateParticles(finalParticleList);
243}
244
245//------------------------------------------------------------------------------------------------------------------------------------------
246
248 const ClusterVector &clusters3, ClusterLengthMap &clusterLengthMap, PfoLengthMap &pfoLengthMap, ParticleList &particleList) const
249{
250 if (clusters1.empty() || clusters2.empty() || clusters3.empty())
251 return;
252
253 for (const Cluster *const pCluster1 : clusters1)
254 {
255 if (!pCluster1->IsAvailable())
256 continue;
257
258 for (const Cluster *const pCluster2 : clusters2)
259 {
260 if (!pCluster2->IsAvailable())
261 continue;
262
263 for (const Cluster *const pCluster3 : clusters3)
264 {
265 if (!pCluster3->IsAvailable())
266 continue;
267
268 if (!this->AreClustersMatched(pCluster1, pCluster2, pCluster3))
269 continue;
270
271 const ParticleFlowObject *pBestPfo = NULL;
272 this->FindBestParentPfo(pCluster1, pCluster2, pCluster3, clusterLengthMap, pfoLengthMap, pBestPfo);
273
274 // ATTN Need to record all matches when all three views are used
275 particleList.push_back(Particle(pCluster1, pCluster2, pCluster3, pBestPfo));
276 }
277 }
278 }
279}
280
281//------------------------------------------------------------------------------------------------------------------------------------------
282
284 ClusterLengthMap &clusterLengthMap, PfoLengthMap &pfoLengthMap, ParticleList &particleList) const
285{
286 if (clusters1.empty() || clusters2.empty())
287 return;
288
289 for (const Cluster *const pCluster1 : clusters1)
290 {
291 if (!pCluster1->IsAvailable())
292 continue;
293
294 for (const Cluster *const pCluster2 : clusters2)
295 {
296 if (!pCluster2->IsAvailable())
297 continue;
298
299 if (!this->AreClustersMatched(pCluster1, pCluster2, NULL))
300 continue;
301
302 const ParticleFlowObject *pBestPfo = NULL;
303 this->FindBestParentPfo(pCluster1, pCluster2, NULL, clusterLengthMap, pfoLengthMap, pBestPfo);
304
305 if (NULL == pBestPfo)
306 continue;
307
308 particleList.push_back(Particle(pCluster1, pCluster2, NULL, pBestPfo));
309 }
310 }
311}
312
313//------------------------------------------------------------------------------------------------------------------------------------------
314
316 const ClusterVector &clusters, ClusterLengthMap &clusterLengthMap, PfoLengthMap &pfoLengthMap, ParticleList &particleList) const
317{
318 if (clusters.empty())
319 return;
320
321 for (const Cluster *const pCluster : clusters)
322 {
323 if (!pCluster->IsAvailable())
324 continue;
325
326 const ParticleFlowObject *pBestPfo = NULL;
327 this->FindBestParentPfo(pCluster, NULL, NULL, clusterLengthMap, pfoLengthMap, pBestPfo);
328
329 if (NULL == pBestPfo)
330 continue;
331
332 particleList.push_back(Particle(pCluster, NULL, NULL, pBestPfo));
333 }
334}
335
336//------------------------------------------------------------------------------------------------------------------------------------------
337
338void DeltaRayMatchingAlgorithm::SelectParticles(const ParticleList &initialParticles, ClusterLengthMap &clusterLengthMap, ParticleList &finalParticles) const
339{
340 for (const Particle &particle1 : initialParticles)
341 {
342 bool isGoodParticle(true);
343
344 for (const Particle &particle2 : initialParticles)
345 {
346 const bool commonU(particle1.GetClusterU() == particle2.GetClusterU());
347 const bool commonV(particle1.GetClusterV() == particle2.GetClusterV());
348 const bool commonW(particle1.GetClusterW() == particle2.GetClusterW());
349
350 const bool ambiguousU(commonU && NULL != particle1.GetClusterU());
351 const bool ambiguousV(commonV && NULL != particle1.GetClusterV());
352 const bool ambiguousW(commonW && NULL != particle1.GetClusterW());
353
354 if (commonU && commonV && commonW)
355 continue;
356
357 if (ambiguousU || ambiguousV || ambiguousW)
358 {
359 if (particle2.GetNViews() > particle1.GetNViews())
360 {
361 isGoodParticle = false;
362 }
363 else if (particle2.GetNViews() == particle1.GetNViews() && NULL != particle2.GetParentPfo())
364 {
365 if ((NULL == particle1.GetParentPfo()) || (particle2.GetNCaloHits() > particle1.GetNCaloHits()) ||
366 (particle2.GetNCaloHits() == particle1.GetNCaloHits() &&
367 this->GetLength(particle2, clusterLengthMap) >= this->GetLength(particle1, clusterLengthMap)))
368 {
369 isGoodParticle = false;
370 }
371 }
372
373 if (!isGoodParticle)
374 break;
375 }
376 }
377
378 if (isGoodParticle && NULL != particle1.GetParentPfo())
379 finalParticles.push_back(particle1);
380 }
381}
382
383//------------------------------------------------------------------------------------------------------------------------------------------
384
386{
387 PfoVector parentVector, daughterVector;
388 this->GetTrackPfos(m_parentPfoListName, parentVector);
389 this->GetAllPfos(m_daughterPfoListName, daughterVector);
390
391 PfoList parentList(parentVector.begin(), parentVector.end());
392 PfoList daughterList(daughterVector.begin(), daughterVector.end());
393
394 for (const Particle &particle : particleList)
395 {
396 const ParticleFlowObject *const pParentPfo = particle.GetParentPfo();
397
398 if (NULL == pParentPfo)
399 continue;
400
401 const Cluster *const pClusterU = particle.GetClusterU();
402 const Cluster *const pClusterV = particle.GetClusterV();
403 const Cluster *const pClusterW = particle.GetClusterW();
404
405 if (NULL == pClusterU && NULL == pClusterV && NULL == pClusterW)
406 throw StatusCodeException(STATUS_CODE_FAILURE);
407
408 ClusterList clusterList;
409
410 if (pClusterU)
411 clusterList.push_back(pClusterU);
412
413 if (pClusterV)
414 clusterList.push_back(pClusterV);
415
416 if (pClusterW)
417 clusterList.push_back(pClusterW);
418
419 if (parentList.end() != std::find(parentList.begin(), parentList.end(), pParentPfo))
420 {
421 this->CreateDaughterPfo(clusterList, pParentPfo);
422 }
423 else if (daughterList.end() != std::find(daughterList.begin(), daughterList.end(), pParentPfo))
424 {
425 this->AddToDaughterPfo(clusterList, pParentPfo);
426 }
427 else
428 {
429 throw StatusCodeException(STATUS_CODE_FAILURE);
430 }
431 }
432}
433
434//------------------------------------------------------------------------------------------------------------------------------------------
435
436bool DeltaRayMatchingAlgorithm::AreClustersMatched(const Cluster *const pCluster1, const Cluster *const pCluster2, const Cluster *const pCluster3) const
437{
438 if (nullptr == pCluster1 && nullptr == pCluster2 && nullptr == pCluster3)
439 throw StatusCodeException(STATUS_CODE_FAILURE);
440
441 // First step: Check X overlap
442 float xMin1(-std::numeric_limits<float>::max()), xMax1(+std::numeric_limits<float>::max());
443 float xMin2(-std::numeric_limits<float>::max()), xMax2(+std::numeric_limits<float>::max());
444 float xMin3(-std::numeric_limits<float>::max()), xMax3(+std::numeric_limits<float>::max());
445
446 if (nullptr != pCluster1)
447 pCluster1->GetClusterSpanX(xMin1, xMax1);
448
449 if (nullptr != pCluster2)
450 pCluster2->GetClusterSpanX(xMin2, xMax2);
451
452 if (nullptr != pCluster3)
453 pCluster3->GetClusterSpanX(xMin3, xMax3);
454
455 const float xPitch(0.5 * m_xOverlapWindow);
456 const float xMin(std::max(xMin1, std::max(xMin2, xMin3)) - xPitch);
457 const float xMax(std::min(xMax1, std::min(xMax2, xMax3)) + xPitch);
458 const float xOverlap(xMax - xMin);
459
460 if (xOverlap < std::numeric_limits<float>::epsilon())
461 return false;
462
463 if (nullptr == pCluster1 || nullptr == pCluster2 || nullptr == pCluster3)
464 return true;
465
466 // Second step: Check 3D matching
467 const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
468 const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
469 const HitType hitType3(LArClusterHelper::GetClusterHitType(pCluster3));
470
471 if (hitType1 == hitType2 || hitType2 == hitType3 || hitType3 == hitType1)
472 throw StatusCodeException(STATUS_CODE_FAILURE);
473
474 const unsigned int nSamplingPoints(1 + static_cast<unsigned int>(xOverlap / xPitch));
475
476 for (unsigned int n = 0; n < nSamplingPoints; ++n)
477 {
478 const float x(xMin + (xMax - xMin) * (static_cast<float>(n) + 0.5f) / static_cast<float>(nSamplingPoints));
479 const float xmin(x - xPitch);
480 const float xmax(x + xPitch);
481
482 try
483 {
484 float zMin1(0.f), zMin2(0.f), zMin3(0.f), zMax1(0.f), zMax2(0.f), zMax3(0.f);
485 pCluster1->GetClusterSpanZ(xmin, xmax, zMin1, zMax1);
486 pCluster2->GetClusterSpanZ(xmin, xmax, zMin2, zMax2);
487 pCluster3->GetClusterSpanZ(xmin, xmax, zMin3, zMax3);
488
489 const float z1(0.5f * (zMin1 + zMax1));
490 const float z2(0.5f * (zMin2 + zMax2));
491 const float z3(0.5f * (zMin3 + zMax3));
492
493 const float dz1(zMax1 - zMin1);
494 const float dz2(zMax2 - zMin2);
495 const float dz3(zMax3 - zMin3);
496 const float dz4(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
497
498 const float zproj1(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitType2, hitType3, z2, z3));
499 const float zproj2(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitType3, hitType1, z3, z1));
500 const float zproj3(LArGeometryHelper::MergeTwoPositions(this->GetPandora(), hitType1, hitType2, z1, z2));
501
502 const float deltaSquared(((z1 - zproj1) * (z1 - zproj1) + (z2 - zproj2) * (z2 - zproj2) + (z3 - zproj3) * (z3 - zproj3)) / 3.f);
503 const float sigmaSquared(dz1 * dz1 + dz2 * dz2 + dz3 * dz3 + dz4 * dz4);
504 const float pseudoChi2(deltaSquared / sigmaSquared);
505
506 if (pseudoChi2 < m_pseudoChi2Cut)
507 return true;
508 }
509 catch (StatusCodeException &statusCodeException)
510 {
511 if (STATUS_CODE_NOT_FOUND != statusCodeException.GetStatusCode())
512 throw statusCodeException;
513 }
514 }
515
516 return false;
517}
518
519//------------------------------------------------------------------------------------------------------------------------------------------
520
521void DeltaRayMatchingAlgorithm::FindBestParentPfo(const Cluster *const pCluster1, const Cluster *const pCluster2,
522 const Cluster *const pCluster3, ClusterLengthMap &clusterLengthMap, PfoLengthMap &pfoLengthMap, const ParticleFlowObject *&pBestPfo) const
523{
524 PfoVector pfoVector;
525 this->GetTrackPfos(m_parentPfoListName, pfoVector);
526 this->GetAllPfos(m_daughterPfoListName, pfoVector);
527
528 if (pfoVector.empty())
529 throw StatusCodeException(STATUS_CODE_FAILURE);
530
531 unsigned int numViews(0);
532 float lengthSquared(0.f);
533
534 if (pCluster1)
535 {
536 lengthSquared += this->GetLengthFromCache(pCluster1, clusterLengthMap);
537 ++numViews;
538 }
539
540 if (pCluster2)
541 {
542 lengthSquared += this->GetLengthFromCache(pCluster2, clusterLengthMap);
543 ++numViews;
544 }
545
546 if (pCluster3)
547 {
548 lengthSquared += this->GetLengthFromCache(pCluster3, clusterLengthMap);
549 ++numViews;
550 }
551
552 float bestDistanceSquared(static_cast<float>(numViews) * m_distanceForMatching * m_distanceForMatching);
553
554 for (const ParticleFlowObject *const pPfo : pfoVector)
555 {
556 if (lengthSquared > this->GetLengthFromCache(pPfo, pfoLengthMap))
557 continue;
558
559 try
560 {
561 float distanceSquared(0.f);
562
563 if (NULL != pCluster1)
564 distanceSquared += this->GetDistanceSquaredToPfo(pCluster1, pPfo);
565
566 if (NULL != pCluster2)
567 distanceSquared += this->GetDistanceSquaredToPfo(pCluster2, pPfo);
568
569 if (NULL != pCluster3)
570 distanceSquared += this->GetDistanceSquaredToPfo(pCluster3, pPfo);
571
572 if (distanceSquared < bestDistanceSquared)
573 {
574 pBestPfo = pPfo;
575 bestDistanceSquared = distanceSquared;
576 }
577 }
578 catch (StatusCodeException &statusCodeException)
579 {
580 if (!(STATUS_CODE_NOT_FOUND == statusCodeException.GetStatusCode()))
581 throw statusCodeException;
582 }
583 }
584}
585
586//------------------------------------------------------------------------------------------------------------------------------------------
587
588float DeltaRayMatchingAlgorithm::GetLengthFromCache(const Cluster *const pCluster, ClusterLengthMap &clusterLengthMap) const
589{
590 ClusterLengthMap::const_iterator iter = clusterLengthMap.find(pCluster);
591
592 if (clusterLengthMap.end() != iter)
593 return iter->second;
594
595 const float lengthSquared(LArClusterHelper::GetLengthSquared(pCluster));
596 (void)clusterLengthMap.insert(ClusterLengthMap::value_type(pCluster, lengthSquared));
597 return lengthSquared;
598}
599
600//------------------------------------------------------------------------------------------------------------------------------------------
601
603{
604 PfoLengthMap::const_iterator iter = pfoLengthMap.find(pPfo);
605
606 if (pfoLengthMap.end() != iter)
607 return iter->second;
608
609 const float lengthSquared(LArPfoHelper::GetTwoDLengthSquared(pPfo));
610 (void)pfoLengthMap.insert(PfoLengthMap::value_type(pPfo, lengthSquared));
611 return lengthSquared;
612}
613
614//------------------------------------------------------------------------------------------------------------------------------------------
615
616float DeltaRayMatchingAlgorithm::GetLength(const Particle &particle, ClusterLengthMap &clusterLengthMap) const
617{
618 float lengthSquared(0.f);
619
620 if (particle.GetClusterU())
621 lengthSquared += this->GetLengthFromCache(particle.GetClusterU(), clusterLengthMap);
622
623 if (particle.GetClusterV())
624 lengthSquared += this->GetLengthFromCache(particle.GetClusterV(), clusterLengthMap);
625
626 if (particle.GetClusterW())
627 lengthSquared += this->GetLengthFromCache(particle.GetClusterW(), clusterLengthMap);
628
629 return lengthSquared;
630}
631
632//------------------------------------------------------------------------------------------------------------------------------------------
633
634float DeltaRayMatchingAlgorithm::GetDistanceSquaredToPfo(const Cluster *const pCluster, const ParticleFlowObject *const pPfo) const
635{
636 const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
637
638 if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
639 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
640
641 ClusterList comparisonList;
642 const ClusterToClustersMap &nearbyClusters((TPC_VIEW_U == hitType) ? m_nearbyClustersU : (TPC_VIEW_V == hitType) ? m_nearbyClustersV : m_nearbyClustersW);
643
644 if (!nearbyClusters.count(pCluster))
645 return std::numeric_limits<float>::max();
646
647 ClusterList pfoClusterList;
648 LArPfoHelper::GetClusters(pPfo, hitType, pfoClusterList);
649
650 for (const Cluster *const pPfoCluster : pfoClusterList)
651 {
652 const ClusterList &clusterList(nearbyClusters.at(pCluster));
653
654 if ((clusterList.end() != std::find(clusterList.begin(), clusterList.end(), pPfoCluster)) &&
655 (comparisonList.end() == std::find(comparisonList.begin(), comparisonList.end(), pPfoCluster)))
656 {
657 comparisonList.push_back(pPfoCluster);
658 }
659 }
660
661 if (comparisonList.empty())
662 return std::numeric_limits<float>::max();
663
664 return LArClusterHelper::GetClosestDistance(pCluster, comparisonList);
665}
666
667//------------------------------------------------------------------------------------------------------------------------------------------
668
669void DeltaRayMatchingAlgorithm::CreateDaughterPfo(const ClusterList &clusterList, const ParticleFlowObject *const pParentPfo) const
670{
671 const PfoList *pPfoList = NULL;
672 std::string pfoListName;
673 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pPfoList, pfoListName));
674
675 // TODO Correct these placeholder parameters
676 PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
677 pfoParameters.m_particleId = E_MINUS; // SHOWER
678 pfoParameters.m_charge = PdgTable::GetParticleCharge(pfoParameters.m_particleId.Get());
679 pfoParameters.m_mass = PdgTable::GetParticleMass(pfoParameters.m_particleId.Get());
680 pfoParameters.m_energy = 0.f;
681 pfoParameters.m_momentum = CartesianVector(0.f, 0.f, 0.f);
682 pfoParameters.m_clusterList = clusterList;
683
684 const ParticleFlowObject *pDaughterPfo(NULL);
685 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, pfoParameters, pDaughterPfo));
686
687 if (!pPfoList->empty())
688 {
690 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pParentPfo, pDaughterPfo));
691 }
692}
693
694//------------------------------------------------------------------------------------------------------------------------------------------
695
696void DeltaRayMatchingAlgorithm::AddToDaughterPfo(const ClusterList &clusterList, const ParticleFlowObject *const pParentPfo) const
697{
698 for (const Cluster *const pDaughterCluster : clusterList)
699 {
700 const HitType hitType(LArClusterHelper::GetClusterHitType(pDaughterCluster));
701 const std::string clusterListName(
703
704 ClusterList pfoClusters;
705 LArPfoHelper::GetClusters(pParentPfo, hitType, pfoClusters);
706
707 if (pfoClusters.empty())
708 throw StatusCodeException(STATUS_CODE_FAILURE);
709
710 const Cluster *const pParentCluster = *(pfoClusters.begin());
711
712 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
713 PandoraContentApi::MergeAndDeleteClusters(*this, pParentCluster, pDaughterCluster, clusterListName, clusterListName));
714 }
715}
716
717//------------------------------------------------------------------------------------------------------------------------------------------
718//------------------------------------------------------------------------------------------------------------------------------------------
719
721 const Cluster *const pCluster1, const Cluster *const pCluster2, const Cluster *const pCluster3, const ParticleFlowObject *const pPfo) :
722 m_pClusterU(NULL),
723 m_pClusterV(NULL),
724 m_pClusterW(NULL),
725 m_pParentPfo(NULL)
726{
727 const HitType hitType1(NULL != pCluster1 ? LArClusterHelper::GetClusterHitType(pCluster1) : HIT_CUSTOM);
728 const HitType hitType2(NULL != pCluster2 ? LArClusterHelper::GetClusterHitType(pCluster2) : HIT_CUSTOM);
729 const HitType hitType3(NULL != pCluster3 ? LArClusterHelper::GetClusterHitType(pCluster3) : HIT_CUSTOM);
730
731 m_pClusterU = ((TPC_VIEW_U == hitType1) ? pCluster1 : (TPC_VIEW_U == hitType2) ? pCluster2 : (TPC_VIEW_U == hitType3) ? pCluster3 : NULL);
732 m_pClusterV = ((TPC_VIEW_V == hitType1) ? pCluster1 : (TPC_VIEW_V == hitType2) ? pCluster2 : (TPC_VIEW_V == hitType3) ? pCluster3 : NULL);
733 m_pClusterW = ((TPC_VIEW_W == hitType1) ? pCluster1 : (TPC_VIEW_W == hitType2) ? pCluster2 : (TPC_VIEW_W == hitType3) ? pCluster3 : NULL);
734 m_pParentPfo = pPfo;
735
736 if (NULL == m_pClusterU && NULL == m_pClusterV && NULL == m_pClusterW)
737 throw StatusCodeException(STATUS_CODE_FAILURE);
738}
739
740//------------------------------------------------------------------------------------------------------------------------------------------
741
743{
744 unsigned int numViews(0);
745
746 if (NULL != m_pClusterU)
747 numViews += 1;
748
749 if (NULL != m_pClusterV)
750 numViews += 1;
751
752 if (NULL != m_pClusterW)
753 numViews += 1;
754
755 return numViews;
756}
757
758//------------------------------------------------------------------------------------------------------------------------------------------
759
761{
762 unsigned int numCaloHits(0);
763
764 if (NULL != m_pClusterU)
765 numCaloHits += m_pClusterU->GetNCaloHits();
766
767 if (NULL != m_pClusterV)
768 numCaloHits += m_pClusterV->GetNCaloHits();
769
770 if (NULL != m_pClusterW)
771 numCaloHits += m_pClusterW->GetNCaloHits();
772
773 return numCaloHits;
774}
775
776//------------------------------------------------------------------------------------------------------------------------------------------
777//------------------------------------------------------------------------------------------------------------------------------------------
778
780{
781 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "ParentPfoListName", m_parentPfoListName));
782 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "DaughterPfoListName", m_daughterPfoListName));
783 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameU", m_inputClusterListNameU));
784 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameV", m_inputClusterListNameV));
785 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameW", m_inputClusterListNameW));
786
788 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCaloHitsPerCluster", m_minCaloHitsPerCluster));
789
790 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "OverlapWindow", m_xOverlapWindow));
791
793 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "DistanceForMatching", m_distanceForMatching));
794
795 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PseudoChi2Cut", m_pseudoChi2Cut));
796
797 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SearchRegion1D", m_searchRegion1D));
798
799 return STATUS_CODE_SUCCESS;
800}
801
802} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the delta ray matching algorithm class.
Header file for the kd tree linker algo template class.
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the pfo helper class.
#define PANDORA_THROW_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:55
#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
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:19
static pandora::StatusCode ReplaceCurrentList(const pandora::Algorithm &algorithm, const std::string &newListName)
Replace the current list with a pre-saved list; use this new list as a permanent replacement for the ...
static pandora::StatusCode CreateTemporaryListAndSetCurrent(const pandora::Algorithm &algorithm, const T *&pT, std::string &temporaryListName)
Create a temporary list and set it to be the current list, enabling object creation.
static pandora::StatusCode MergeAndDeleteClusters(const pandora::Algorithm &algorithm, const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete)
Merge two clusters in the current list, enlarging one cluster and deleting the second.
static pandora::StatusCode SetPfoParentDaughterRelationship(const pandora::Algorithm &algorithm, const pandora::ParticleFlowObject *const pParentPfo, const pandora::ParticleFlowObject *const pDaughterPfo)
Set parent-daughter particle flow object relationship.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
const pandora::ParticleFlowObject * m_pParentPfo
Address of parent Pfo.
const pandora::Cluster * m_pClusterV
Address of cluster in V view.
unsigned int GetNCaloHits() const
Get number of calo hits.
const pandora::Cluster * m_pClusterU
Address of cluster in U view.
const pandora::Cluster * GetClusterV() const
Get cluster in V view.
unsigned int GetNViews() const
Get number of views.
Particle(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3, const pandora::ParticleFlowObject *const pPfo)
Constructor.
const pandora::Cluster * GetClusterW() const
Get cluster in W view.
const pandora::Cluster * GetClusterU() const
Get cluster in U view.
const pandora::Cluster * m_pClusterW
Address of cluster in W view.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
std::string m_inputClusterListNameW
The input cluster list name for the w view.
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.
std::unordered_map< const pandora::Cluster *, float > ClusterLengthMap
void OneViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using single views.
ClusterToClustersMap m_nearbyClustersV
The nearby clusters map for the v view.
void CreateDaughterPfo(const pandora::ClusterList &clusterList, const pandora::ParticleFlowObject *const pParentPfo) const
Create a new Pfo from an input cluster list and set up a parent/daughter relationship.
void CreateParticles(const ParticleList &particleList) const
Build new particle flow objects.
float m_distanceForMatching
The maximum allowed distance between tracks and delta rays.
void InitializeNearbyClusterMaps()
Initialize nearby cluster maps.
pandora::StatusCode Run()
Run the algorithm.
void ThreeViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using all three views.
std::string m_inputClusterListNameV
The input cluster list name for the v view.
std::string m_parentPfoListName
The parent pfo list name.
void SelectParticles(const ParticleList &inputParticles, ClusterLengthMap &clusterLengthMap, ParticleList &outputParticles) const
Resolve any ambiguities between candidate particles.
float m_xOverlapWindow
The maximum allowed displacement in x position.
bool AreClustersMatched(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3) const
Look at consistency of a combination of clusters.
ClusterToClustersMap m_nearbyClustersW
The nearby clusters map for the w view.
void InitializeNearbyClusterMap(const std::string &clusterListName, ClusterToClustersMap &nearbyClusters)
Initialize a nearby cluster map with details relating to a specific cluster list.
void ClearNearbyClusterMaps()
Clear nearby cluster maps.
float m_pseudoChi2Cut
Pseudo chi2 cut for three view matching.
std::string m_inputClusterListNameU
The input cluster list name for the u view.
void FindBestParentPfo(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW, ClusterLengthMap &clusterLengthMap, PfoLengthMap &pfoLengthMap, const pandora::ParticleFlowObject *&pBestPfo) const
Find best Pfo to associate a UVW triplet.
std::string m_daughterPfoListName
The daughter pfo list name for new daughter particles.
unsigned int m_minCaloHitsPerCluster
The min number of calo hits per candidate cluster.
std::unordered_map< const pandora::ParticleFlowObject *, float > PfoLengthMap
void AddToDaughterPfo(const pandora::ClusterList &clusterList, const pandora::ParticleFlowObject *const pParentPfo) const
Merge an input cluster list with an existing daughter Pfo.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterToClustersMap
void GetAllPfos(const std::string &inputPfoListName, pandora::PfoVector &pfoVector) const
Get a vector of all Pfos in the provided input Pfo lists.
float GetLength(const Particle &particle, ClusterLengthMap &clusterLengthMap) const
Get the length (squared) of a candidate particle.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float GetLengthFromCache(const pandora::Cluster *const pCluster, ClusterLengthMap &clusterLengthMap) const
Reduce number of length (squared) calculations by caching results when they are first obtained.
void GetTrackPfos(const std::string &inputPfoListName, pandora::PfoVector &pfoVector) const
Get a vector of track-like Pfos in the provided input Pfo lists.
void TwoViewMatching(ClusterLengthMap &clusterLengthMap) const
Match clusters using pairs of views.
ClusterToClustersMap m_nearbyClustersU
The nearby clusters map for the u view.
void GetClusters(const std::string &clusterListName, pandora::ClusterVector &clusterVector) const
Get a vector containing all available input clusters in the provided cluster list,...
float GetDistanceSquaredToPfo(const pandora::Cluster *const pCluster, const pandora::ParticleFlowObject *const pPfo) const
Get displacementr between cluster and particle flow object.
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > &region)
Build the KD tree from the "eltList" in the space define by "region".
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM > > &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position,...
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
static float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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 GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
static float GetTwoDLengthSquared(const pandora::ParticleFlowObject *const pPfo)
Calculate length of Pfo using 2D clusters.
CaloHit class.
Definition CaloHit.h:26
CartesianVector class.
Cluster class.
Definition Cluster.h:31
bool IsAvailable() const
Whether the cluster is available to be added to a particle flow object.
Definition Cluster.h:582
unsigned int GetNCaloHits() const
Get the number of calo hits in the cluster.
Definition Cluster.h:484
void GetClusterSpanX(float &xmin, float &xmax) const
Get minimum and maximum X positions of the calo hits in this cluster.
Definition Cluster.cc:169
void GetClusterSpanZ(const float xmin, const float xmax, float &zmin, float &zmax) const
Get upper and lower Z positions of the calo hits in a cluster in range xmin to xmax.
Definition Cluster.cc:198
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
static float GetParticleMass(const int pdgCode)
Get the mass of a particle type.
Definition PdgTable.h:205
static int GetParticleCharge(const int pdgCode)
Get the charge of a particle type.
Definition PdgTable.h:227
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
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
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 > > &nodes)
fill_and_bound_2d_kd_tree
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< const ParticleFlowObject * > PfoVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList