LArSoft  v10_06_00
Liquid Argon Software toolkit - https://larsoft.org/
LArPfoHelper.cc
Go to the documentation of this file.
1 
9 #include "Pandora/PdgTable.h"
10 
15 
17 
18 #include <algorithm>
19 #include <cmath>
20 #include <limits>
21 
22 using namespace pandora;
23 
24 namespace lar_content
25 {
26 
27 void LArPfoHelper::GetCoordinateVector(const ParticleFlowObject *const pPfo, const HitType &hitType, CartesianPointVector &coordinateVector)
28 {
29  ClusterList clusterList;
30  LArPfoHelper::GetClusters(pPfo, hitType, clusterList);
31 
32  for (const Cluster *const pCluster : clusterList)
33  LArClusterHelper::GetCoordinateVector(pCluster, coordinateVector);
34 }
35 
36 //------------------------------------------------------------------------------------------------------------------------------------------
37 
38 void LArPfoHelper::GetCaloHits(const PfoList &pfoList, const HitType &hitType, CaloHitList &caloHitList)
39 {
40  for (const ParticleFlowObject *const pPfo : pfoList)
41  LArPfoHelper::GetCaloHits(pPfo, hitType, caloHitList);
42 }
43 
44 //------------------------------------------------------------------------------------------------------------------------------------------
45 
46 void LArPfoHelper::GetCaloHits(const ParticleFlowObject *const pPfo, const HitType &hitType, CaloHitList &caloHitList)
47 {
48  ClusterList clusterList;
49  LArPfoHelper::GetClusters(pPfo, hitType, clusterList);
50 
51  for (const Cluster *const pCluster : clusterList)
52  pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
53 }
54 
55 //------------------------------------------------------------------------------------------------------------------------------------------
56 
57 void LArPfoHelper::GetIsolatedCaloHits(const PfoList &pfoList, const HitType &hitType, CaloHitList &caloHitList)
58 {
59  for (const ParticleFlowObject *const pPfo : pfoList)
60  LArPfoHelper::GetIsolatedCaloHits(pPfo, hitType, caloHitList);
61 }
62 
63 //------------------------------------------------------------------------------------------------------------------------------------------
64 
65 void LArPfoHelper::GetIsolatedCaloHits(const ParticleFlowObject *const pPfo, const HitType &hitType, CaloHitList &caloHitList)
66 {
67  ClusterList clusterList;
68  LArPfoHelper::GetClusters(pPfo, hitType, clusterList);
69 
70  for (const Cluster *const pCluster : clusterList)
71  caloHitList.insert(caloHitList.end(), pCluster->GetIsolatedCaloHitList().begin(), pCluster->GetIsolatedCaloHitList().end());
72 }
73 
74 //------------------------------------------------------------------------------------------------------------------------------------------
75 
76 void LArPfoHelper::GetAllCaloHits(const ParticleFlowObject *const pPfo, CaloHitList &caloHitList)
77 {
78  LArPfoHelper::GetCaloHits(pPfo, TPC_VIEW_U, caloHitList);
79  LArPfoHelper::GetCaloHits(pPfo, TPC_VIEW_V, caloHitList);
80  LArPfoHelper::GetCaloHits(pPfo, TPC_VIEW_W, caloHitList);
81  LArPfoHelper::GetIsolatedCaloHits(pPfo, TPC_VIEW_U, caloHitList);
82  LArPfoHelper::GetIsolatedCaloHits(pPfo, TPC_VIEW_V, caloHitList);
83  LArPfoHelper::GetIsolatedCaloHits(pPfo, TPC_VIEW_W, caloHitList);
84 }
85 
86 //------------------------------------------------------------------------------------------------------------------------------------------
87 
88 void LArPfoHelper::GetClusters(const PfoList &pfoList, const HitType &hitType, ClusterList &clusterList)
89 {
90  for (const ParticleFlowObject *const pPfo : pfoList)
91  LArPfoHelper::GetClusters(pPfo, hitType, clusterList);
92 }
93 
94 //------------------------------------------------------------------------------------------------------------------------------------------
95 
96 void LArPfoHelper::GetClusters(const ParticleFlowObject *const pPfo, const HitType &hitType, ClusterList &clusterList)
97 {
98  for (const Cluster *const pCluster : pPfo->GetClusterList())
99  {
100  if (hitType != LArClusterHelper::GetClusterHitType(pCluster))
101  continue;
102 
103  clusterList.push_back(pCluster);
104  }
105 }
106 
107 //------------------------------------------------------------------------------------------------------------------------------------------
108 
109 unsigned int LArPfoHelper::GetNumberOfTwoDHits(const ParticleFlowObject *const pPfo)
110 {
111  unsigned int totalHits(0);
112 
113  ClusterList clusterList;
114  LArPfoHelper::GetTwoDClusterList(pPfo, clusterList);
115  for (const Cluster *const pCluster : clusterList)
116  totalHits += pCluster->GetNCaloHits();
117 
118  return totalHits;
119 }
120 
121 //------------------------------------------------------------------------------------------------------------------------------------------
122 
123 unsigned int LArPfoHelper::GetNumberOfThreeDHits(const ParticleFlowObject *const pPfo)
124 {
125  ClusterList clusterList3D;
126  LArPfoHelper::GetThreeDClusterList(pPfo, clusterList3D);
127 
128  int total3DHits(0);
129 
130  for (const Cluster *const pCluster3D : clusterList3D)
131  total3DHits += pCluster3D->GetNCaloHits();
132 
133  return total3DHits;
134 }
135 
136 //------------------------------------------------------------------------------------------------------------------------------------------
137 
138 void LArPfoHelper::GetTwoDClusterList(const ParticleFlowObject *const pPfo, ClusterList &clusterList)
139 {
140  for (const Cluster *const pCluster : pPfo->GetClusterList())
141  {
142  if (TPC_3D == LArClusterHelper::GetClusterHitType(pCluster))
143  continue;
144 
145  clusterList.push_back(pCluster);
146  }
147 }
148 
149 //------------------------------------------------------------------------------------------------------------------------------------------
150 
151 void LArPfoHelper::GetThreeDClusterList(const ParticleFlowObject *const pPfo, ClusterList &clusterList)
152 {
153  for (const Cluster *const pCluster : pPfo->GetClusterList())
154  {
155  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster))
156  continue;
157 
158  clusterList.push_back(pCluster);
159  }
160 }
161 
162 //------------------------------------------------------------------------------------------------------------------------------------------
163 
164 void LArPfoHelper::GetAllConnectedPfos(const PfoList &inputPfoList, PfoList &outputPfoList)
165 {
166  for (const ParticleFlowObject *const pPfo : inputPfoList)
167  LArPfoHelper::GetAllConnectedPfos(pPfo, outputPfoList);
168 }
169 
170 //------------------------------------------------------------------------------------------------------------------------------------------
171 
172 void LArPfoHelper::GetAllConnectedPfos(const ParticleFlowObject *const pPfo, PfoList &outputPfoList)
173 {
174  if (outputPfoList.end() != std::find(outputPfoList.begin(), outputPfoList.end(), pPfo))
175  return;
176 
177  outputPfoList.push_back(pPfo);
178  LArPfoHelper::GetAllConnectedPfos(pPfo->GetParentPfoList(), outputPfoList);
179  LArPfoHelper::GetAllConnectedPfos(pPfo->GetDaughterPfoList(), outputPfoList);
180 }
181 
182 //------------------------------------------------------------------------------------------------------------------------------------------
183 
184 void LArPfoHelper::GetAllDownstreamPfos(const PfoList &inputPfoList, PfoList &outputPfoList)
185 {
186  for (const ParticleFlowObject *const pPfo : inputPfoList)
187  LArPfoHelper::GetAllDownstreamPfos(pPfo, outputPfoList);
188 }
189 
190 //------------------------------------------------------------------------------------------------------------------------------------------
191 
192 void LArPfoHelper::GetAllDownstreamPfos(const ParticleFlowObject *const pPfo, PfoList &outputPfoList)
193 {
194  if (outputPfoList.end() != std::find(outputPfoList.begin(), outputPfoList.end(), pPfo))
195  return;
196 
197  outputPfoList.push_back(pPfo);
198  LArPfoHelper::GetAllDownstreamPfos(pPfo->GetDaughterPfoList(), outputPfoList);
199 }
200 
201 //------------------------------------------------------------------------------------------------------------------------------------------
202 
203 void LArPfoHelper::GetAllDownstreamPfos(
204  const pandora::ParticleFlowObject *const pPfo, pandora::PfoList &outputTrackPfoList, pandora::PfoList &outputLeadingShowerPfoList)
205 {
206  if (LArPfoHelper::IsTrack(pPfo))
207  {
208  outputTrackPfoList.emplace_back(pPfo);
209  for (const ParticleFlowObject *pChild : pPfo->GetDaughterPfoList())
210  {
211  if (std::find(outputTrackPfoList.begin(), outputTrackPfoList.end(), pChild) == outputTrackPfoList.end())
212  {
213  const int pdg{std::abs(pChild->GetParticleId())};
214  if (pdg == E_MINUS)
215  {
216  outputLeadingShowerPfoList.emplace_back(pChild);
217  }
218  else
219  {
220  outputTrackPfoList.emplace_back(pChild);
221  LArPfoHelper::GetAllDownstreamPfos(pChild, outputTrackPfoList, outputLeadingShowerPfoList);
222  }
223  }
224  }
225  }
226  else
227  {
228  outputLeadingShowerPfoList.emplace_back(pPfo);
229  }
230 }
231 
232 //------------------------------------------------------------------------------------------------------------------------------------------
233 
234 int LArPfoHelper::GetHierarchyTier(const ParticleFlowObject *const pPfo)
235 {
236  const ParticleFlowObject *pParentPfo = pPfo;
237  int tier(0);
238 
239  while (pParentPfo->GetParentPfoList().empty() == false)
240  {
241  if (1 != pParentPfo->GetParentPfoList().size())
242  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
243 
244  pParentPfo = *(pParentPfo->GetParentPfoList().begin());
245  ++tier;
246  }
247 
248  return tier;
249 }
250 
251 //------------------------------------------------------------------------------------------------------------------------------------------
252 
253 float LArPfoHelper::GetTwoDLengthSquared(const ParticleFlowObject *const pPfo)
254 {
255  if (!LArPfoHelper::IsTwoD(pPfo))
256  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
257 
258  float lengthSquared(0.f);
259 
260  for (const Cluster *const pCluster : pPfo->GetClusterList())
261  {
262  if (TPC_3D == LArClusterHelper::GetClusterHitType(pCluster))
263  continue;
264 
265  lengthSquared += LArClusterHelper::GetLengthSquared(pCluster);
266  }
267 
268  return lengthSquared;
269 }
270 
271 //------------------------------------------------------------------------------------------------------------------------------------------
272 
273 float LArPfoHelper::GetThreeDLengthSquared(const ParticleFlowObject *const pPfo)
274 {
275  if (!LArPfoHelper::IsThreeD(pPfo))
276  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
277 
278  float lengthSquared(0.f);
279 
280  for (const Cluster *const pCluster : pPfo->GetClusterList())
281  {
282  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster))
283  continue;
284 
285  lengthSquared += LArClusterHelper::GetLengthSquared(pCluster);
286  }
287 
288  return lengthSquared;
289 }
290 
291 //------------------------------------------------------------------------------------------------------------------------------------------
292 
293 float LArPfoHelper::GetClosestDistance(const ParticleFlowObject *const pPfo, const Cluster *const pCluster)
294 {
295  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
296 
297  ClusterList clusterList;
298  LArPfoHelper::GetClusters(pPfo, hitType, clusterList);
299 
300  if (clusterList.empty())
301  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
302 
303  float bestDistance(std::numeric_limits<float>::max());
304 
305  for (const Cluster *const pPfoCluster : clusterList)
306  {
307  const float thisDistance(LArClusterHelper::GetClosestDistance(pCluster, pPfoCluster));
308 
309  if (thisDistance < bestDistance)
310  bestDistance = thisDistance;
311  }
312 
313  return bestDistance;
314 }
315 
316 //------------------------------------------------------------------------------------------------------------------------------------------
317 
318 float LArPfoHelper::GetThreeDSeparation(const ParticleFlowObject *const pPfo1, const ParticleFlowObject *const pPfo2)
319 {
320  ClusterList clusterList1, clusterList2;
321 
322  LArPfoHelper::GetClusters(pPfo1, TPC_3D, clusterList1);
323  LArPfoHelper::GetClusters(pPfo2, TPC_3D, clusterList2);
324 
325  if (clusterList1.empty() || clusterList2.empty())
326  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
327 
328  return LArClusterHelper::GetClosestDistance(clusterList1, clusterList2);
329 }
330 
331 //------------------------------------------------------------------------------------------------------------------------------------------
332 
333 bool LArPfoHelper::IsTwoD(const ParticleFlowObject *const pPfo)
334 {
335  for (const Cluster *const pCluster : pPfo->GetClusterList())
336  {
337  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster))
338  return true;
339  }
340 
341  return false;
342 }
343 
344 //------------------------------------------------------------------------------------------------------------------------------------------
345 
346 bool LArPfoHelper::IsThreeD(const ParticleFlowObject *const pPfo)
347 {
348  for (const Cluster *const pCluster : pPfo->GetClusterList())
349  {
350  if (TPC_3D == LArClusterHelper::GetClusterHitType(pCluster))
351  return true;
352  }
353 
354  return false;
355 }
356 
357 //------------------------------------------------------------------------------------------------------------------------------------------
358 
359 bool LArPfoHelper::IsTrack(const ParticleFlowObject *const pPfo)
360 {
361  const int pdg(pPfo->GetParticleId());
362 
363  // muon, pion, proton, kaon
364  return ((MU_MINUS == std::abs(pdg)) || (PI_PLUS == std::abs(pdg)) || (PROTON == std::abs(pdg)) || (K_PLUS == std::abs(pdg)));
365 }
366 
367 //------------------------------------------------------------------------------------------------------------------------------------------
368 
369 bool LArPfoHelper::IsShower(const ParticleFlowObject *const pPfo)
370 {
371  const int pdg(pPfo->GetParticleId());
372 
373  // electron, photon
374  return ((E_MINUS == std::abs(pdg)) || (PHOTON == std::abs(pdg)));
375 }
376 
377 //------------------------------------------------------------------------------------------------------------------------------------------
378 
379 float LArPfoHelper::GetTrackScore(const ParticleFlowObject *const pPfo)
380 {
381  float trackScore(-999.f);
382 
383  const PropertiesMap &metadata(pPfo->GetPropertiesMap());
384 
385  if (metadata.find("TrackScore") != metadata.end())
386  trackScore = metadata.at("TrackScore");
387 
388  return trackScore;
389 }
390 
391 //------------------------------------------------------------------------------------------------------------------------------------------
392 
393 int LArPfoHelper::GetPrimaryNeutrino(const ParticleFlowObject *const pPfo)
394 {
395  try
396  {
397  const ParticleFlowObject *const pParentPfo = LArPfoHelper::GetParentNeutrino(pPfo);
398  return pParentPfo->GetParticleId();
399  }
400  catch (const StatusCodeException &)
401  {
402  return 0;
403  }
404 }
405 
406 //------------------------------------------------------------------------------------------------------------------------------------------
407 
408 bool LArPfoHelper::IsFinalState(const ParticleFlowObject *const pPfo)
409 {
410  if (pPfo->GetParentPfoList().empty() && !LArPfoHelper::IsNeutrino(pPfo))
411  return true;
412 
413  if (LArPfoHelper::IsNeutrinoFinalState(pPfo))
414  return true;
415 
416  return false;
417 }
418 
419 //------------------------------------------------------------------------------------------------------------------------------------------
420 
421 bool LArPfoHelper::IsNeutrinoFinalState(const ParticleFlowObject *const pPfo)
422 {
423  return ((pPfo->GetParentPfoList().size() == 1) && (LArPfoHelper::IsNeutrino(*(pPfo->GetParentPfoList().begin()))));
424 }
425 
426 //------------------------------------------------------------------------------------------------------------------------------------------
427 
428 bool LArPfoHelper::IsNeutrino(const ParticleFlowObject *const pPfo)
429 {
430  const int absoluteParticleId(std::abs(pPfo->GetParticleId()));
431 
432  if ((NU_E == absoluteParticleId) || (NU_MU == absoluteParticleId) || (NU_TAU == absoluteParticleId))
433  return true;
434 
435  return false;
436 }
437 
438 //------------------------------------------------------------------------------------------------------------------------------------------
439 
440 bool LArPfoHelper::IsTestBeamFinalState(const ParticleFlowObject *const pPfo)
441 {
442  return LArPfoHelper::IsTestBeam(LArPfoHelper::GetParentPfo(pPfo));
443 }
444 
445 //------------------------------------------------------------------------------------------------------------------------------------------
446 
447 bool LArPfoHelper::IsTestBeam(const ParticleFlowObject *const pPfo)
448 {
449  const PropertiesMap &properties(pPfo->GetPropertiesMap());
450  const PropertiesMap::const_iterator iter(properties.find("IsTestBeam"));
451 
452  if (iter != properties.end())
453  return ((iter->second > 0.f) ? true : false);
454 
455  return false;
456 }
457 
458 //------------------------------------------------------------------------------------------------------------------------------------------
459 
460 void LArPfoHelper::GetRecoNeutrinos(const PfoList *const pPfoList, PfoList &recoNeutrinos)
461 {
462  if (!pPfoList)
463  return;
464 
465  for (const ParticleFlowObject *const pPfo : *pPfoList)
466  {
467  if (LArPfoHelper::IsNeutrino(pPfo))
468  recoNeutrinos.push_back(pPfo);
469  }
470 }
471 
472 //------------------------------------------------------------------------------------------------------------------------------------------
473 
474 const ParticleFlowObject *LArPfoHelper::GetParentPfo(const ParticleFlowObject *const pPfo)
475 {
476  const ParticleFlowObject *pParentPfo = pPfo;
477 
478  while (pParentPfo->GetParentPfoList().empty() == false)
479  {
480  pParentPfo = *(pParentPfo->GetParentPfoList().begin());
481  }
482 
483  return pParentPfo;
484 }
485 
486 //------------------------------------------------------------------------------------------------------------------------------------------
487 
488 const ParticleFlowObject *LArPfoHelper::GetParentNeutrino(const ParticleFlowObject *const pPfo)
489 {
490  const ParticleFlowObject *const pParentPfo = LArPfoHelper::GetParentPfo(pPfo);
491 
492  if (!LArPfoHelper::IsNeutrino(pParentPfo))
493  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
494 
495  return pParentPfo;
496 }
497 
498 //------------------------------------------------------------------------------------------------------------------------------------------
499 
500 const Vertex *LArPfoHelper::GetVertex(const ParticleFlowObject *const pPfo)
501 {
502  if (pPfo->GetVertexList().empty())
503  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
504 
505  const Vertex *pVertex(nullptr);
506 
507  // ATTN : Test beam parent pfos contain an interaction and start vertex
508  if (LArPfoHelper::IsTestBeam(pPfo) && pPfo->GetParentPfoList().empty())
509  {
510  pVertex = LArPfoHelper::GetVertexWithLabel(pPfo->GetVertexList(), VERTEX_START);
511  }
512  else
513  {
514  if (pPfo->GetVertexList().size() != 1)
515  throw StatusCodeException(STATUS_CODE_FAILURE);
516 
517  pVertex = *(pPfo->GetVertexList().begin());
518  }
519 
520  if (VERTEX_3D != pVertex->GetVertexType())
521  throw StatusCodeException(STATUS_CODE_FAILURE);
522 
523  return pVertex;
524 }
525 
526 //------------------------------------------------------------------------------------------------------------------------------------------
527 
528 const Vertex *LArPfoHelper::GetTestBeamInteractionVertex(const ParticleFlowObject *const pPfo)
529 {
530  if (pPfo->GetVertexList().empty() || !pPfo->GetParentPfoList().empty() || !LArPfoHelper::IsTestBeam(pPfo))
531  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
532 
533  const Vertex *pInteractionVertex(LArPfoHelper::GetVertexWithLabel(pPfo->GetVertexList(), VERTEX_INTERACTION));
534 
535  if (VERTEX_3D != pInteractionVertex->GetVertexType())
536  throw StatusCodeException(STATUS_CODE_FAILURE);
537 
538  return pInteractionVertex;
539 }
540 
541 //------------------------------------------------------------------------------------------------------------------------------------------
542 
543 const Vertex *LArPfoHelper::GetVertexWithLabel(const VertexList &vertexList, const VertexLabel vertexLabel)
544 {
545  const Vertex *pTargetVertex(nullptr);
546 
547  for (const Vertex *pCandidateVertex : vertexList)
548  {
549  if (pCandidateVertex->GetVertexLabel() == vertexLabel)
550  {
551  if (!pTargetVertex)
552  {
553  pTargetVertex = pCandidateVertex;
554  }
555  else
556  {
557  throw StatusCodeException(STATUS_CODE_FAILURE);
558  }
559  }
560  }
561 
562  if (!pTargetVertex)
563  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
564 
565  return pTargetVertex;
566 }
567 
568 //------------------------------------------------------------------------------------------------------------------------------------------
569 
570 void LArPfoHelper::GetSlidingFitTrajectory(const CartesianPointVector &pointVector, const CartesianVector &vertexPosition,
571  const unsigned int layerWindow, const float layerPitch, LArTrackStateVector &trackStateVector, IntVector *const pIndexVector)
572 {
573  LArPfoHelper::SlidingFitTrajectoryImpl(&pointVector, vertexPosition, layerWindow, layerPitch, trackStateVector, pIndexVector);
574 }
575 
576 //------------------------------------------------------------------------------------------------------------------------------------------
577 
578 void LArPfoHelper::GetSlidingFitTrajectory(const ParticleFlowObject *const pPfo, const Vertex *const pVertex,
579  const unsigned int layerWindow, const float layerPitch, LArTrackStateVector &trackStateVector)
580 {
581  CaloHitList caloHitList;
582  LArPfoHelper::GetCaloHits(pPfo, TPC_3D, caloHitList);
583  LArPfoHelper::SlidingFitTrajectoryImpl(&caloHitList, pVertex->GetPosition(), layerWindow, layerPitch, trackStateVector);
584 }
585 
586 //------------------------------------------------------------------------------------------------------------------------------------------
587 
588 LArShowerPCA LArPfoHelper::GetPrincipalComponents(const CartesianPointVector &pointVector, const CartesianVector &vertexPosition)
589 {
590  // Run the PCA analysis
591  CartesianVector centroid(0.f, 0.f, 0.f);
592  LArPcaHelper::EigenVectors eigenVecs;
593  LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
594  LArPcaHelper::RunPca(pointVector, centroid, eigenValues, eigenVecs);
595 
596  // Require that principal eigenvalue should always be positive
597  if (eigenValues.GetX() < std::numeric_limits<float>::epsilon())
598  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
599 
600  // By convention, principal axis should always point away from vertex
601  const float testProjection(eigenVecs.at(0).GetDotProduct(vertexPosition - centroid));
602  const float directionScaleFactor((testProjection > std::numeric_limits<float>::epsilon()) ? -1.f : 1.f);
603 
604  const CartesianVector primaryAxis(eigenVecs.at(0) * directionScaleFactor);
605  const CartesianVector secondaryAxis(eigenVecs.at(1) * directionScaleFactor);
606  const CartesianVector tertiaryAxis(eigenVecs.at(2) * directionScaleFactor);
607 
608  return LArShowerPCA(centroid, primaryAxis, secondaryAxis, tertiaryAxis, eigenValues);
609 }
610 
611 //------------------------------------------------------------------------------------------------------------------------------------------
612 
613 LArShowerPCA LArPfoHelper::GetPrincipalComponents(const ParticleFlowObject *const pPfo, const Vertex *const pVertex)
614 {
615  CartesianPointVector pointVector;
616  LArPfoHelper::GetCoordinateVector(pPfo, TPC_3D, pointVector);
617  return LArPfoHelper::GetPrincipalComponents(pointVector, pVertex->GetPosition());
618 }
619 
620 //------------------------------------------------------------------------------------------------------------------------------------------
621 
622 bool LArPfoHelper::SortByHitProjection(const LArTrackTrajectoryPoint &lhs, const LArTrackTrajectoryPoint &rhs)
623 {
624  if (lhs.first != rhs.first)
625  return (lhs.first < rhs.first);
626 
627  // ATTN Removed to support use with CartesianVector only (no CaloHit) input
628  // if (lhs.second.GetCaloHit() && rhs.second.GetCaloHit())
629  // return (lhs.second.GetCaloHit()->GetInputEnergy() > rhs.second.GetCaloHit()->GetInputEnergy());
630 
631  const float dx(lhs.second.GetPosition().GetX() - rhs.second.GetPosition().GetX());
632  const float dy(lhs.second.GetPosition().GetY() - rhs.second.GetPosition().GetY());
633  const float dz(lhs.second.GetPosition().GetZ() - rhs.second.GetPosition().GetZ());
634  return (dx + dy + dz > 0.f);
635 }
636 
637 //------------------------------------------------------------------------------------------------------------------------------------------
638 
639 bool LArPfoHelper::SortByNHits(const ParticleFlowObject *const pLhs, const ParticleFlowObject *const pRhs)
640 {
641  unsigned int nTwoDHitsLhs(0), nThreeDHitsLhs(0);
642  float energyLhs(0.f);
643  for (ClusterList::const_iterator iter = pLhs->GetClusterList().begin(), iterEnd = pLhs->GetClusterList().end(); iter != iterEnd; ++iter)
644  {
645  const Cluster *const pClusterLhs = *iter;
646 
647  if (TPC_3D != LArClusterHelper::GetClusterHitType(pClusterLhs))
648  nTwoDHitsLhs += pClusterLhs->GetNCaloHits();
649  else
650  nThreeDHitsLhs += pClusterLhs->GetNCaloHits();
651 
652  energyLhs += pClusterLhs->GetHadronicEnergy();
653  }
654 
655  unsigned int nTwoDHitsRhs(0), nThreeDHitsRhs(0);
656  float energyRhs(0.f);
657  for (ClusterList::const_iterator iter = pRhs->GetClusterList().begin(), iterEnd = pRhs->GetClusterList().end(); iter != iterEnd; ++iter)
658  {
659  const Cluster *const pClusterRhs = *iter;
660 
661  if (TPC_3D != LArClusterHelper::GetClusterHitType(pClusterRhs))
662  nTwoDHitsRhs += pClusterRhs->GetNCaloHits();
663  else
664  nThreeDHitsRhs += pClusterRhs->GetNCaloHits();
665 
666  energyRhs += pClusterRhs->GetHadronicEnergy();
667  }
668 
669  if (nTwoDHitsLhs != nTwoDHitsRhs)
670  return (nTwoDHitsLhs > nTwoDHitsRhs);
671 
672  if (nThreeDHitsLhs != nThreeDHitsRhs)
673  return (nThreeDHitsLhs > nThreeDHitsRhs);
674 
675  // ATTN Need an efficient (balance with well-motivated) tie-breaker here. Pfo length, for instance, is extremely slow.
676  return (energyLhs > energyRhs);
677 }
678 
679 //------------------------------------------------------------------------------------------------------------------------------------------
680 
681 void LArPfoHelper::GetBreadthFirstHierarchyRepresentation(const pandora::ParticleFlowObject *const pPfo, pandora::PfoList &pfoList)
682 {
683  const ParticleFlowObject *pRoot{pPfo};
684  PfoList parents{pRoot->GetParentPfoList()};
685  while (!parents.empty())
686  {
687  if (parents.size() > 1)
688  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
689  pRoot = parents.front();
690  parents = pRoot->GetParentPfoList();
691  }
692  PfoList queue;
693  pfoList.emplace_back(pRoot);
694  queue.emplace_back(pRoot);
695 
696  while (!queue.empty())
697  {
698  const PfoList &daughters{queue.front()->GetDaughterPfoList()};
699  queue.pop_front();
700  for (const ParticleFlowObject *pDaughter : daughters)
701  {
702  pfoList.emplace_back(pDaughter);
703  queue.emplace_back(pDaughter);
704  }
705  }
706 }
707 
708 //------------------------------------------------------------------------------------------------------------------------------------------
709 
710 template <typename T>
711 void LArPfoHelper::SlidingFitTrajectoryImpl(const T *const pT, const CartesianVector &vertexPosition, const unsigned int layerWindow,
712  const float layerPitch, LArTrackStateVector &trackStateVector, IntVector *const pIndexVector)
713 {
714  CartesianPointVector pointVector;
715 
716  for (const auto &nextPoint : *pT)
717  pointVector.push_back(LArObjectHelper::TypeAdaptor::GetPosition(nextPoint));
718 
719  if (pointVector.empty())
720  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
721 
722  std::sort(pointVector.begin(), pointVector.end(), LArClusterHelper::SortCoordinatesByPosition);
723 
724  LArTrackTrajectory trackTrajectory;
725  IntVector indicesWithoutSpacePoints;
726  if (pIndexVector)
727  pIndexVector->clear();
728 
729  try
730  {
731  const ThreeDSlidingFitResult slidingFitResult(&pointVector, layerWindow, layerPitch);
732  const CartesianVector minPosition(slidingFitResult.GetGlobalMinLayerPosition());
733  const CartesianVector maxPosition(slidingFitResult.GetGlobalMaxLayerPosition());
734 
735  if ((maxPosition - minPosition).GetMagnitudeSquared() < std::numeric_limits<float>::epsilon())
736  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
737 
738  const CartesianVector seedPosition((maxPosition + minPosition) * 0.5f);
739  const CartesianVector seedDirection((maxPosition - minPosition).GetUnitVector());
740 
741  const float scaleFactor((seedDirection.GetDotProduct(seedPosition - vertexPosition) > 0.f) ? +1.f : -1.f);
742 
743  int index(-1);
744  for (const auto &nextPoint : *pT)
745  {
746  ++index;
747 
748  try
749  {
750  const float rL(slidingFitResult.GetLongitudinalDisplacement(LArObjectHelper::TypeAdaptor::GetPosition(nextPoint)));
751 
752  CartesianVector position(0.f, 0.f, 0.f);
753  const StatusCode positionStatusCode(slidingFitResult.GetGlobalFitPosition(rL, position));
754 
755  if (positionStatusCode != STATUS_CODE_SUCCESS)
756  throw StatusCodeException(positionStatusCode);
757 
758  CartesianVector direction(0.f, 0.f, 0.f);
759  const StatusCode directionStatusCode(slidingFitResult.GetGlobalFitDirection(rL, direction));
760 
761  if (directionStatusCode != STATUS_CODE_SUCCESS)
762  throw StatusCodeException(directionStatusCode);
763 
764  const float projection(seedDirection.GetDotProduct(position - seedPosition));
765 
766  trackTrajectory.push_back(LArTrackTrajectoryPoint(projection * scaleFactor,
767  LArTrackState(position, direction * scaleFactor, LArObjectHelper::TypeAdaptor::GetCaloHit(nextPoint)), index));
768  }
769  catch (const StatusCodeException &statusCodeException1)
770  {
771  indicesWithoutSpacePoints.push_back(index);
772 
773  if (STATUS_CODE_FAILURE == statusCodeException1.GetStatusCode())
774  throw statusCodeException1;
775  }
776  }
777  }
778  catch (const StatusCodeException &statusCodeException2)
779  {
780  if (STATUS_CODE_FAILURE == statusCodeException2.GetStatusCode())
781  throw statusCodeException2;
782  }
783 
784  // Sort trajectory points by distance along track
785  std::sort(trackTrajectory.begin(), trackTrajectory.end(), LArPfoHelper::SortByHitProjection);
786 
787  for (const LArTrackTrajectoryPoint &larTrackTrajectoryPoint : trackTrajectory)
788  {
789  trackStateVector.push_back(larTrackTrajectoryPoint.second);
790  if (pIndexVector)
791  pIndexVector->push_back(larTrackTrajectoryPoint.GetIndex());
792  }
793 
794  // Store indices of spacepoints with no associated trajectory point at the end of pIndexVector
795  if (pIndexVector)
796  {
797  for (const int index : indicesWithoutSpacePoints)
798  pIndexVector->push_back(index);
799  }
800 }
801 
802 //------------------------------------------------------------------------------------------------------------------------------------------
803 
804 template void LArPfoHelper::SlidingFitTrajectoryImpl(
805  const CartesianPointVector *const, const CartesianVector &, const unsigned int, const float, LArTrackStateVector &, IntVector *const);
806 template void LArPfoHelper::SlidingFitTrajectoryImpl(
807  const CaloHitList *const, const CartesianVector &, const unsigned int, const float, LArTrackStateVector &, IntVector *const);
808 
809 } // namespace lar_content
Header file for the pfo helper class.
pandora::CartesianVector EigenValues
Definition: LArPcaHelper.h:24
LArTrackState class.
Definition: LArPfoObjects.h:29
constexpr auto abs(T v)
Returns the absolute value of the argument.
Header file for the principal curve analysis helper class.
intermediate_table::const_iterator const_iterator
std::vector< int > IntVector
float GetLongitudinalDisplacement(const pandora::CartesianVector &position) const
Get longitudinal projection onto primary axis.
std::vector< LArTrackTrajectoryPoint > LArTrackTrajectory
TFile f
Definition: plotHisto.C:6
Header file for the object helper class.
Header file for the cluster helper class.
pandora::StatusCode GetGlobalFitDirection(const float rL, pandora::CartesianVector &direction) const
Get global fit direction for a given longitudinal coordinate.
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
Header file for the lar three dimensional sliding fit result class.
std::vector< pandora::CartesianVector > EigenVectors
Definition: LArPcaHelper.h:25
HitType
Definition: HitType.h:12
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
std::vector< LArTrackState > LArTrackStateVector
Definition: LArPfoObjects.h:67
LArTrackTrajectoryPoint class.
Definition: LArPfoObjects.h:74
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
LArShowerPCA class.
std::list< Vertex > VertexList
Definition: DCEL.h:169
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.