LArSoft  v07_13_02
Liquid Argon Software toolkit - http://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::GetClusters(const PfoList &pfoList, const HitType &hitType, ClusterList &clusterList)
77 {
78  for (const ParticleFlowObject *const pPfo : pfoList)
79  LArPfoHelper::GetClusters(pPfo, hitType, clusterList);
80 }
81 
82 //------------------------------------------------------------------------------------------------------------------------------------------
83 
84 void LArPfoHelper::GetClusters(const ParticleFlowObject *const pPfo, const HitType &hitType, ClusterList &clusterList)
85 {
86  for (const Cluster *const pCluster : pPfo->GetClusterList())
87  {
88  if (hitType != LArClusterHelper::GetClusterHitType(pCluster))
89  continue;
90 
91  clusterList.push_back(pCluster);
92  }
93 }
94 
95 //------------------------------------------------------------------------------------------------------------------------------------------
96 
97 void LArPfoHelper::GetTwoDClusterList(const ParticleFlowObject *const pPfo, ClusterList &clusterList)
98 {
99  for (const Cluster *const pCluster : pPfo->GetClusterList())
100  {
101  if (TPC_3D == LArClusterHelper::GetClusterHitType(pCluster))
102  continue;
103 
104  clusterList.push_back(pCluster);
105  }
106 }
107 
108 //------------------------------------------------------------------------------------------------------------------------------------------
109 
110 void LArPfoHelper::GetThreeDClusterList(const ParticleFlowObject *const pPfo, ClusterList &clusterList)
111 {
112  for (const Cluster *const pCluster : pPfo->GetClusterList())
113  {
114  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster))
115  continue;
116 
117  clusterList.push_back(pCluster);
118  }
119 }
120 
121 //------------------------------------------------------------------------------------------------------------------------------------------
122 
123 void LArPfoHelper::GetAllConnectedPfos(const PfoList &inputPfoList, PfoList &outputPfoList)
124 {
125  for (const ParticleFlowObject *const pPfo : inputPfoList)
126  LArPfoHelper::GetAllConnectedPfos(pPfo, outputPfoList);
127 }
128 
129 //------------------------------------------------------------------------------------------------------------------------------------------
130 
131 void LArPfoHelper::GetAllConnectedPfos(const ParticleFlowObject *const pPfo, PfoList &outputPfoList)
132 {
133  if (outputPfoList.end() != std::find(outputPfoList.begin(), outputPfoList.end(), pPfo))
134  return;
135 
136  outputPfoList.push_back(pPfo);
137  LArPfoHelper::GetAllConnectedPfos(pPfo->GetParentPfoList(), outputPfoList);
138  LArPfoHelper::GetAllConnectedPfos(pPfo->GetDaughterPfoList(), outputPfoList);
139 }
140 
141 //------------------------------------------------------------------------------------------------------------------------------------------
142 
143 void LArPfoHelper::GetAllDownstreamPfos(const PfoList &inputPfoList, PfoList &outputPfoList)
144 {
145  for (const ParticleFlowObject *const pPfo : inputPfoList)
146  LArPfoHelper::GetAllDownstreamPfos(pPfo, outputPfoList);
147 }
148 
149 //------------------------------------------------------------------------------------------------------------------------------------------
150 
151 void LArPfoHelper::GetAllDownstreamPfos(const ParticleFlowObject *const pPfo, PfoList &outputPfoList)
152 {
153  if (outputPfoList.end() != std::find(outputPfoList.begin(), outputPfoList.end(), pPfo))
154  return;
155 
156  outputPfoList.push_back(pPfo);
157  LArPfoHelper::GetAllDownstreamPfos(pPfo->GetDaughterPfoList(), outputPfoList);
158 }
159 
160 //------------------------------------------------------------------------------------------------------------------------------------------
161 
162 float LArPfoHelper::GetTwoDLengthSquared(const ParticleFlowObject *const pPfo)
163 {
164  if (!LArPfoHelper::IsTwoD(pPfo))
165  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
166 
167  float lengthSquared(0.f);
168 
169  for (const Cluster *const pCluster : pPfo->GetClusterList())
170  {
171  if (TPC_3D == LArClusterHelper::GetClusterHitType(pCluster))
172  continue;
173 
174  lengthSquared += LArClusterHelper::GetLengthSquared(pCluster);
175  }
176 
177  return lengthSquared;
178 }
179 
180 //------------------------------------------------------------------------------------------------------------------------------------------
181 
182 float LArPfoHelper::GetThreeDLengthSquared(const ParticleFlowObject *const pPfo)
183 {
184  if (!LArPfoHelper::IsThreeD(pPfo))
185  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
186 
187  float lengthSquared(0.f);
188 
189  for (const Cluster *const pCluster : pPfo->GetClusterList())
190  {
191  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster))
192  continue;
193 
194  lengthSquared += LArClusterHelper::GetLengthSquared(pCluster);
195  }
196 
197  return lengthSquared;
198 }
199 
200 //------------------------------------------------------------------------------------------------------------------------------------------
201 
202 float LArPfoHelper::GetClosestDistance(const ParticleFlowObject *const pPfo, const Cluster *const pCluster)
203 {
204  const HitType hitType(LArClusterHelper::GetClusterHitType(pCluster));
205 
206  ClusterList clusterList;
207  LArPfoHelper::GetClusters(pPfo, hitType, clusterList);
208 
209  if (clusterList.empty())
210  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
211 
212  float bestDistance(std::numeric_limits<float>::max());
213 
214  for (const Cluster *const pPfoCluster : clusterList)
215  {
216  const float thisDistance(LArClusterHelper::GetClosestDistance(pCluster, pPfoCluster));
217 
218  if (thisDistance < bestDistance)
219  bestDistance = thisDistance;
220  }
221 
222  return bestDistance;
223 }
224 
225 //------------------------------------------------------------------------------------------------------------------------------------------
226 
227 float LArPfoHelper::GetTwoDSeparation(const ParticleFlowObject *const pPfo1, const ParticleFlowObject *const pPfo2)
228 {
229  ClusterList clusterListU1, clusterListV1, clusterListW1;
230  ClusterList clusterListU2, clusterListV2, clusterListW2;
231 
232  LArPfoHelper::GetClusters(pPfo1, TPC_VIEW_U, clusterListU1);
233  LArPfoHelper::GetClusters(pPfo1, TPC_VIEW_V, clusterListV1);
234  LArPfoHelper::GetClusters(pPfo1, TPC_VIEW_W, clusterListW1);
235 
236  LArPfoHelper::GetClusters(pPfo2, TPC_VIEW_U, clusterListU2);
237  LArPfoHelper::GetClusters(pPfo2, TPC_VIEW_V, clusterListV2);
238  LArPfoHelper::GetClusters(pPfo2, TPC_VIEW_W, clusterListW2);
239 
240  float numViews(0.f);
241  float distanceSquared(0.f);
242 
243  if (!clusterListU1.empty() && !clusterListU2.empty())
244  {
245  distanceSquared += LArClusterHelper::GetClosestDistance(clusterListU1, clusterListU2);
246  numViews += 1.f;
247  }
248 
249  if (!clusterListV1.empty() && !clusterListV2.empty())
250  {
251  distanceSquared += LArClusterHelper::GetClosestDistance(clusterListV1, clusterListV2);
252  numViews += 1.f;
253  }
254 
255  if (!clusterListW1.empty() && !clusterListW2.empty())
256  {
257  distanceSquared += LArClusterHelper::GetClosestDistance(clusterListW1, clusterListW2);
258  numViews += 1.f;
259  }
260 
261  if (numViews < std::numeric_limits<float>::epsilon())
262  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
263 
264  return std::sqrt(distanceSquared / numViews);
265 }
266 
267 //------------------------------------------------------------------------------------------------------------------------------------------
268 
269 float LArPfoHelper::GetThreeDSeparation(const ParticleFlowObject *const pPfo1, const ParticleFlowObject *const pPfo2)
270 {
271  ClusterList clusterList1, clusterList2;
272 
273  LArPfoHelper::GetClusters(pPfo1, TPC_3D, clusterList1);
274  LArPfoHelper::GetClusters(pPfo2, TPC_3D, clusterList2);
275 
276  if (clusterList1.empty() || clusterList2.empty())
277  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
278 
279  return LArClusterHelper::GetClosestDistance(clusterList1, clusterList2);
280 }
281 
282 //------------------------------------------------------------------------------------------------------------------------------------------
283 
284 bool LArPfoHelper::IsTwoD(const ParticleFlowObject *const pPfo)
285 {
286  for (const Cluster *const pCluster : pPfo->GetClusterList())
287  {
288  if (TPC_3D != LArClusterHelper::GetClusterHitType(pCluster))
289  return true;
290  }
291 
292  return false;
293 }
294 
295 //------------------------------------------------------------------------------------------------------------------------------------------
296 
297 bool LArPfoHelper::IsThreeD(const ParticleFlowObject *const pPfo)
298 {
299  for (const Cluster *const pCluster : pPfo->GetClusterList())
300  {
301  if (TPC_3D == LArClusterHelper::GetClusterHitType(pCluster))
302  return true;
303  }
304 
305  return false;
306 }
307 
308 //------------------------------------------------------------------------------------------------------------------------------------------
309 
310 bool LArPfoHelper::IsTrack(const ParticleFlowObject *const pPfo)
311 {
312  const int pdg(pPfo->GetParticleId());
313 
314  // muon, pion, proton, kaon
315  return ((MU_MINUS == std::abs(pdg)) || (PI_PLUS == std::abs(pdg)) || (PROTON == std::abs(pdg)) || (K_PLUS == std::abs(pdg)));
316 }
317 
318 //------------------------------------------------------------------------------------------------------------------------------------------
319 
320 bool LArPfoHelper::IsShower(const ParticleFlowObject *const pPfo)
321 {
322  const int pdg(pPfo->GetParticleId());
323 
324  // electron, photon
325  return ((E_MINUS == std::abs(pdg)) || (PHOTON == std::abs(pdg)));
326 }
327 
328 //------------------------------------------------------------------------------------------------------------------------------------------
329 
330 int LArPfoHelper::GetPrimaryNeutrino(const ParticleFlowObject *const pPfo)
331 {
332  try
333  {
334  const ParticleFlowObject *const pParentPfo = LArPfoHelper::GetParentNeutrino(pPfo);
335  return pParentPfo->GetParticleId();
336  }
337  catch (const StatusCodeException &)
338  {
339  return 0;
340  }
341 }
342 
343 //------------------------------------------------------------------------------------------------------------------------------------------
344 
345 bool LArPfoHelper::IsFinalState(const ParticleFlowObject *const pPfo)
346 {
347  if (pPfo->GetParentPfoList().empty() && !LArPfoHelper::IsNeutrino(pPfo))
348  return true;
349 
350  if (LArPfoHelper::IsNeutrinoFinalState(pPfo))
351  return true;
352 
353  return false;
354 }
355 
356 //------------------------------------------------------------------------------------------------------------------------------------------
357 
358 bool LArPfoHelper::IsNeutrinoFinalState(const ParticleFlowObject *const pPfo)
359 {
360  return ((pPfo->GetParentPfoList().size() == 1) && (LArPfoHelper::IsNeutrino(*(pPfo->GetParentPfoList().begin()))));
361 }
362 
363 //------------------------------------------------------------------------------------------------------------------------------------------
364 
365 bool LArPfoHelper::IsNeutrino(const ParticleFlowObject *const pPfo)
366 {
367  const int absoluteParticleId(std::abs(pPfo->GetParticleId()));
368 
369  if ((NU_E == absoluteParticleId) || (NU_MU == absoluteParticleId) || (NU_TAU == absoluteParticleId))
370  return true;
371 
372  return false;
373 }
374 
375 //------------------------------------------------------------------------------------------------------------------------------------------
376 
377 bool LArPfoHelper::IsTestBeam(const ParticleFlowObject *const pPfo)
378 {
379  const PropertiesMap &properties(pPfo->GetPropertiesMap());
380  const PropertiesMap::const_iterator iter(properties.find("IsTestBeam"));
381 
382  if (iter != properties.end())
383  return ((iter->second > 0.f) ? true : false);
384 
385  return false;
386 }
387 
388 //------------------------------------------------------------------------------------------------------------------------------------------
389 
390 void LArPfoHelper::GetRecoNeutrinos(const PfoList *const pPfoList, PfoList &recoNeutrinos)
391 {
392  if (!pPfoList)
393  return;
394 
395  for (const ParticleFlowObject *const pPfo : *pPfoList)
396  {
397  if (LArPfoHelper::IsNeutrino(pPfo))
398  recoNeutrinos.push_back(pPfo);
399  }
400 }
401 
402 //------------------------------------------------------------------------------------------------------------------------------------------
403 
404 const ParticleFlowObject *LArPfoHelper::GetParentPfo(const ParticleFlowObject *const pPfo)
405 {
406  const ParticleFlowObject *pParentPfo = pPfo;
407 
408  while (pParentPfo->GetParentPfoList().empty() == false)
409  {
410  pParentPfo = *(pParentPfo->GetParentPfoList().begin());
411  }
412 
413  return pParentPfo;
414 }
415 
416 //------------------------------------------------------------------------------------------------------------------------------------------
417 
418 const ParticleFlowObject *LArPfoHelper::GetParentNeutrino(const ParticleFlowObject *const pPfo)
419 {
420  const ParticleFlowObject *const pParentPfo = LArPfoHelper::GetParentPfo(pPfo);
421 
422  if(!LArPfoHelper::IsNeutrino(pParentPfo))
423  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
424 
425  return pParentPfo;
426 }
427 
428 //------------------------------------------------------------------------------------------------------------------------------------------
429 
430 const Vertex *LArPfoHelper::GetVertex(const ParticleFlowObject *const pPfo)
431 {
432  if (pPfo->GetVertexList().empty())
433  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
434 
435  if (pPfo->GetVertexList().size() != 1)
436  throw StatusCodeException(STATUS_CODE_FAILURE);
437 
438  const Vertex *const pVertex = *(pPfo->GetVertexList().begin());
439 
440  if (VERTEX_3D != pVertex->GetVertexType())
441  throw StatusCodeException(STATUS_CODE_FAILURE);
442 
443  return pVertex;
444 }
445 
446 //------------------------------------------------------------------------------------------------------------------------------------------
447 
448 void LArPfoHelper::GetSlidingFitTrajectory(const CartesianPointVector &pointVector, const CartesianVector &vertexPosition,
449  const unsigned int layerWindow, const float layerPitch, LArTrackStateVector &trackStateVector, IntVector *const pIndexVector)
450 {
451  LArPfoHelper::SlidingFitTrajectoryImpl(&pointVector, vertexPosition, layerWindow, layerPitch, trackStateVector, pIndexVector);
452 }
453 
454 //------------------------------------------------------------------------------------------------------------------------------------------
455 
456 void LArPfoHelper::GetSlidingFitTrajectory(const ParticleFlowObject *const pPfo, const Vertex *const pVertex,
457  const unsigned int layerWindow, const float layerPitch, LArTrackStateVector &trackStateVector)
458 {
459  CaloHitList caloHitList;
460  LArPfoHelper::GetCaloHits(pPfo, TPC_3D, caloHitList);
461  LArPfoHelper::SlidingFitTrajectoryImpl(&caloHitList, pVertex->GetPosition(), layerWindow, layerPitch, trackStateVector);
462 }
463 
464 //------------------------------------------------------------------------------------------------------------------------------------------
465 
466 LArShowerPCA LArPfoHelper::GetPrincipalComponents(const CartesianPointVector &pointVector, const CartesianVector &vertexPosition)
467 {
468  // Run the PCA analysis
469  CartesianVector centroid(0.f, 0.f, 0.f);
470  LArPcaHelper::EigenVectors eigenVecs;
471  LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
472  LArPcaHelper::RunPca(pointVector, centroid, eigenValues, eigenVecs);
473 
474  // Require that principal eigenvalue should always be positive
475  if (eigenValues.GetX() < std::numeric_limits<float>::epsilon())
476  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
477 
478  // By convention, principal axis should always point away from vertex
479  const float testProjection(eigenVecs.at(0).GetDotProduct(vertexPosition - centroid));
480  const float directionScaleFactor((testProjection > std::numeric_limits<float>::epsilon()) ? -1.f : 1.f);
481 
482  const CartesianVector primaryAxis(eigenVecs.at(0) * directionScaleFactor);
483  const CartesianVector secondaryAxis(eigenVecs.at(1) * directionScaleFactor);
484  const CartesianVector tertiaryAxis(eigenVecs.at(2) * directionScaleFactor);
485 
486  return LArShowerPCA(centroid, primaryAxis, secondaryAxis, tertiaryAxis, eigenValues);
487 }
488 
489 //------------------------------------------------------------------------------------------------------------------------------------------
490 
491 LArShowerPCA LArPfoHelper::GetPrincipalComponents(const ParticleFlowObject *const pPfo, const Vertex *const pVertex)
492 {
493  CartesianPointVector pointVector;
494  LArPfoHelper::GetCoordinateVector(pPfo, TPC_3D, pointVector);
495  return LArPfoHelper::GetPrincipalComponents(pointVector, pVertex->GetPosition());
496 }
497 
498 //------------------------------------------------------------------------------------------------------------------------------------------
499 
500 bool LArPfoHelper::SortByHitProjection(const LArTrackTrajectoryPoint &lhs, const LArTrackTrajectoryPoint &rhs)
501 {
502  if (lhs.first != rhs.first)
503  return (lhs.first < rhs.first);
504 
505  // ATTN Removed to support use with CartesianVector only (no CaloHit) input
506  // if (lhs.second.GetCaloHit() && rhs.second.GetCaloHit())
507  // return (lhs.second.GetCaloHit()->GetInputEnergy() > rhs.second.GetCaloHit()->GetInputEnergy());
508 
509  const float dx(lhs.second.GetPosition().GetX() - rhs.second.GetPosition().GetX());
510  const float dy(lhs.second.GetPosition().GetY() - rhs.second.GetPosition().GetY());
511  const float dz(lhs.second.GetPosition().GetZ() - rhs.second.GetPosition().GetZ());
512  return (dx + dy + dz > 0.f);
513 }
514 
515 //------------------------------------------------------------------------------------------------------------------------------------------
516 
517 bool LArPfoHelper::SortByNHits(const ParticleFlowObject *const pLhs, const ParticleFlowObject *const pRhs)
518 {
519  unsigned int nTwoDHitsLhs(0), nThreeDHitsLhs(0); float energyLhs(0.f);
520  for (ClusterList::const_iterator iter = pLhs->GetClusterList().begin(), iterEnd = pLhs->GetClusterList().end(); iter != iterEnd; ++iter)
521  {
522  const Cluster *const pClusterLhs = *iter;
523 
524  if (TPC_3D != LArClusterHelper::GetClusterHitType(pClusterLhs))
525  nTwoDHitsLhs += pClusterLhs->GetNCaloHits();
526  else
527  nThreeDHitsLhs += pClusterLhs->GetNCaloHits();
528 
529  energyLhs += pClusterLhs->GetHadronicEnergy();
530  }
531 
532  unsigned int nTwoDHitsRhs(0), nThreeDHitsRhs(0); float energyRhs(0.f);
533  for (ClusterList::const_iterator iter = pRhs->GetClusterList().begin(), iterEnd = pRhs->GetClusterList().end(); iter != iterEnd; ++iter)
534  {
535  const Cluster *const pClusterRhs = *iter;
536 
537  if (TPC_3D != LArClusterHelper::GetClusterHitType(pClusterRhs))
538  nTwoDHitsRhs += pClusterRhs->GetNCaloHits();
539  else
540  nThreeDHitsRhs += pClusterRhs->GetNCaloHits();
541 
542  energyRhs += pClusterRhs->GetHadronicEnergy();
543  }
544 
545  if (nTwoDHitsLhs != nTwoDHitsRhs)
546  return (nTwoDHitsLhs > nTwoDHitsRhs);
547 
548  if (nThreeDHitsLhs != nThreeDHitsRhs)
549  return (nThreeDHitsLhs > nThreeDHitsRhs);
550 
551  // ATTN Need an efficient (balance with well-motivated) tie-breaker here. Pfo length, for instance, is extremely slow.
552  return (energyLhs > energyRhs);
553 }
554 
555 //------------------------------------------------------------------------------------------------------------------------------------------
556 
557 template <typename T>
558 void LArPfoHelper::SlidingFitTrajectoryImpl(const T *const pT, const CartesianVector &vertexPosition, const unsigned int layerWindow,
559  const float layerPitch, LArTrackStateVector &trackStateVector, IntVector *const pIndexVector)
560 {
561  CartesianPointVector pointVector;
562 
563  for (const auto &nextPoint : *pT)
564  pointVector.push_back(LArObjectHelper::TypeAdaptor::GetPosition(nextPoint));
565 
566  if (pointVector.empty())
567  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
568 
569  std::sort(pointVector.begin(), pointVector.end(), LArClusterHelper::SortCoordinatesByPosition);
570 
571  LArTrackTrajectory trackTrajectory;
572  IntVector indicesWithoutSpacePoints;
573  if (pIndexVector) pIndexVector->clear();
574 
575  try
576  {
577  const ThreeDSlidingFitResult slidingFitResult(&pointVector, layerWindow, layerPitch);
578  const CartesianVector minPosition(slidingFitResult.GetGlobalMinLayerPosition());
579  const CartesianVector maxPosition(slidingFitResult.GetGlobalMaxLayerPosition());
580 
581  if ((maxPosition - minPosition).GetMagnitudeSquared() < std::numeric_limits<float>::epsilon())
582  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
583 
584  const CartesianVector seedPosition((maxPosition + minPosition) * 0.5f);
585  const CartesianVector seedDirection((maxPosition - minPosition).GetUnitVector());
586 
587  const float scaleFactor((seedDirection.GetDotProduct(seedPosition - vertexPosition) > 0.f) ? +1.f : -1.f);
588 
589  int index(-1);
590  for (const auto &nextPoint : *pT)
591  {
592  ++index;
593 
594  try
595  {
596  const float rL(slidingFitResult.GetLongitudinalDisplacement(LArObjectHelper::TypeAdaptor::GetPosition(nextPoint)));
597 
598  CartesianVector position(0.f, 0.f, 0.f);
599  const StatusCode positionStatusCode(slidingFitResult.GetGlobalFitPosition(rL, position));
600 
601  if (positionStatusCode != STATUS_CODE_SUCCESS)
602  throw StatusCodeException(positionStatusCode);
603 
604  CartesianVector direction(0.f, 0.f, 0.f);
605  const StatusCode directionStatusCode(slidingFitResult.GetGlobalFitDirection(rL, direction));
606 
607  if (directionStatusCode != STATUS_CODE_SUCCESS)
608  throw StatusCodeException(directionStatusCode);
609 
610  const float projection(seedDirection.GetDotProduct(position - seedPosition));
611 
612  trackTrajectory.push_back(LArTrackTrajectoryPoint(projection * scaleFactor,
613  LArTrackState(position, direction * scaleFactor, LArObjectHelper::TypeAdaptor::GetCaloHit(nextPoint)), index));
614  }
615  catch (const StatusCodeException &statusCodeException1)
616  {
617  indicesWithoutSpacePoints.push_back(index);
618 
619  if (STATUS_CODE_FAILURE == statusCodeException1.GetStatusCode())
620  throw statusCodeException1;
621  }
622  }
623  }
624  catch (const StatusCodeException &statusCodeException2)
625  {
626  if (STATUS_CODE_FAILURE == statusCodeException2.GetStatusCode())
627  throw statusCodeException2;
628  }
629 
630  // Sort trajectory points by distance along track
631  std::sort(trackTrajectory.begin(), trackTrajectory.end(), LArPfoHelper::SortByHitProjection);
632 
633  for (const LArTrackTrajectoryPoint &larTrackTrajectoryPoint : trackTrajectory)
634  {
635  trackStateVector.push_back(larTrackTrajectoryPoint.second);
636  if (pIndexVector) pIndexVector->push_back(larTrackTrajectoryPoint.GetIndex());
637  }
638 
639  // Store indices of spacepoints with no associated trajectory point at the end of pIndexVector
640  if (pIndexVector)
641  {
642  for (const int index : indicesWithoutSpacePoints)
643  pIndexVector->push_back(index);
644  }
645 }
646 
647 //------------------------------------------------------------------------------------------------------------------------------------------
648 
649 template void LArPfoHelper::SlidingFitTrajectoryImpl(const CartesianPointVector *const, const CartesianVector &, const unsigned int, const float, LArTrackStateVector &, IntVector *const);
650 template void LArPfoHelper::SlidingFitTrajectoryImpl(const CaloHitList *const, const CartesianVector &, const unsigned int, const float, LArTrackStateVector &, IntVector *const);
651 
652 } // namespace lar_content
Header file for the pfo helper class.
pandora::CartesianVector EigenValues
Definition: LArPcaHelper.h:21
LArTrackState class.
Definition: LArPfoObjects.h:26
Header file for the principal curve analysis helper class.
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
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
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:22
std::vector< LArTrackState > LArTrackStateVector
Definition: LArPfoObjects.h:64
LArTrackTrajectoryPoint class.
Definition: LArPfoObjects.h:71
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
LArShowerPCA class.
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.