LArSoft  v10_06_00
Liquid Argon Software toolkit - https://larsoft.org/
DLNeutrinoHierarchyAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
17 
22 
24 
25 using namespace pandora;
26 using namespace lar_content;
27 
28 namespace lar_dl_content
29 {
30 
31 DLNeutrinoHierarchyAlgorithm::DLNeutrinoHierarchyAlgorithm() :
32  m_eventID(0),
33  m_trainingMode(false),
34  m_trainingFileName("DLHierarchyTrainingFile.root"),
35  m_eventTreeName("EventTree"),
36  m_primaryTrackTreeName("PrimaryTrackTree"),
37  m_primaryShowerTreeName("PrimaryShowerTree"),
38  m_laterTierTrackTrackTreeName("LaterTierTrackTrackTree"),
39  m_laterTierTrackShowerTreeName("LaterTierTrackShowerTree"),
40  m_mcParticleListName("Input"),
41  m_trainingVertexAccuracy(5.f),
42  m_neutrinoPfoListName("NeutrinoParticles3D"),
43  m_pfoListNames({"TrackParticles3D", "ShowerParticles3D"}),
46  m_regionForDirFit(25.f),
47  m_nAngularBins(180),
48  m_primaryRegion(15.f),
57 {
58 }
59 
60 //------------------------------------------------------------------------------------------------------------------------------------------
61 
63 {
64  if (m_trainingMode)
65  {
66  try
67  {
68  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_eventTreeName.c_str(), m_trainingFileName.c_str(), "UPDATE"));
69  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_primaryTrackTreeName.c_str(), m_trainingFileName.c_str(), "UPDATE"));
70  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_primaryShowerTreeName.c_str(), m_trainingFileName.c_str(), "UPDATE"));
71  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_laterTierTrackTrackTreeName.c_str(), m_trainingFileName.c_str(), "UPDATE"));
72  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_laterTierTrackShowerTreeName.c_str(), m_trainingFileName.c_str(), "UPDATE"));
73  }
74  catch (...)
75  {
76  }
77  }
78 }
79 
80 //------------------------------------------------------------------------------------------------------------------------------------------
81 
83 {
84  ++m_eventID;
85 
86  // Get neutrino pfo
87  const ParticleFlowObject *pNeutrinoPfo(nullptr);
88  if (!this->GetNeutrinoPfo(pNeutrinoPfo))
89  return STATUS_CODE_SUCCESS;
90 
91  // Ensure neutrino has a vertex
92  if (pNeutrinoPfo->GetVertexList().empty())
93  return STATUS_CODE_NOT_INITIALIZED;
94 
95  // Fill the track/shower vectors
96  HierarchyPfoVector trackPfos, showerPfos;
97  this->FillTrackShowerVectors(pNeutrinoPfo, trackPfos, showerPfos);
98 
99 #ifdef MONITORING
100 
101  if (m_trainingMode)
102  {
103  if ((trackPfos.empty()) && (showerPfos.empty()))
104  return STATUS_CODE_SUCCESS;
105 
106  // Do ID
107  std::map<const pandora::ParticleFlowObject *, int> particleIDMap;
108  this->GetParticleIDMap(trackPfos, showerPfos, particleIDMap);
109 
110  // Get truth
111  PfoToMCParticleMap matchingMap;
112  ChildToParentPfoMap childToParentPfoMap;
113  m_cheatHierarchyTool->FillHierarchyMap(this, matchingMap, childToParentPfoMap);
114 
115  // Fill trees
116  int nPrimaryTrackLinks(0), nPrimaryShowerLinks(0);
117  int nLaterTierTrackTrackLinks(0), nLaterTierTrackShowerLinks(0);
118 
119  this->FillPrimaryTrees(matchingMap, childToParentPfoMap, pNeutrinoPfo, trackPfos, showerPfos, particleIDMap, nPrimaryTrackLinks, nPrimaryShowerLinks);
120  this->FillLaterTierTrees(matchingMap, childToParentPfoMap, pNeutrinoPfo, trackPfos, showerPfos, particleIDMap,
121  nLaterTierTrackTrackLinks, nLaterTierTrackShowerLinks);
122  this->FillEventTree(trackPfos, showerPfos, nPrimaryTrackLinks, nPrimaryShowerLinks, nLaterTierTrackTrackLinks, nLaterTierTrackShowerLinks);
123 
124  return STATUS_CODE_SUCCESS;
125  }
126 
127 #endif
128 
129  // Calculate primary scores
130  this->SetPrimaryScores(pNeutrinoPfo, trackPfos, showerPfos);
131 
132  // Build initial primary tier
133  Hierarchy hierarchy({PfoVector()});
134  this->UpdateHierarchy(pNeutrinoPfo, true, true, m_primaryThresholdTrackPass1, m_primaryThresholdShowerPass1, true, trackPfos, showerPfos, hierarchy);
135 
136  // Set later tier scores
137  this->SetLaterTierScores(pNeutrinoPfo, trackPfos, showerPfos);
138 
139  // Build the later tier
140  this->UpdateHierarchy(
141  pNeutrinoPfo, false, false, m_laterTierThresholdTrackPass1, m_laterTierThresholdShowerPass1, true, trackPfos, showerPfos, hierarchy);
142 
143  // Try to recover primaries using laterTierScore
144  this->UpdateHierarchy(pNeutrinoPfo, true, false, m_primaryThresholdTrackPass2, m_primaryThresholdShowerPass2, false, trackPfos, showerPfos, hierarchy);
145 
146  // Try to recover any children using laterTierScore
147  this->UpdateHierarchy(
148  pNeutrinoPfo, false, false, m_laterTierThresholdTrackPass2, m_laterTierThresholdShowerPass2, true, trackPfos, showerPfos, hierarchy);
149 
150  this->BuildPandoraHierarchy(pNeutrinoPfo, trackPfos, showerPfos);
151 
152  return STATUS_CODE_SUCCESS;
153 }
154 
155 //------------------------------------------------------------------------------------------------------------------------------------------
156 
157 bool DLNeutrinoHierarchyAlgorithm::GetNeutrinoPfo(const ParticleFlowObject *&pNeutrinoPfo) const
158 {
159  const PfoList *pPfoList(nullptr);
160 
161  PANDORA_THROW_RESULT_IF_AND_IF(
162  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, m_neutrinoPfoListName, pPfoList));
163 
164  if (!pPfoList || pPfoList->empty())
165  return false;
166 
167  // ATTN Enforces that only one pfo, of neutrino-type, be in the specified input list
168  pNeutrinoPfo = (1 == pPfoList->size()) ? *(pPfoList->begin()) : nullptr;
169 
170  if (!pNeutrinoPfo || !LArPfoHelper::IsNeutrino(pNeutrinoPfo))
171  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
172 
173  return true;
174 }
175 
176 //------------------------------------------------------------------------------------------------------------------------------------------
177 
179  const ParticleFlowObject *const pNeutrinoPfo, HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos) const
180 {
181  // Sliding fit shenanigans
182  const float pitchU{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_U)};
183  const float pitchV{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_V)};
184  const float pitchW{LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_W)};
185  const float slidingFitPitch(std::max({pitchU, pitchV, pitchW}));
186 
187  // Get All pfos
188  PfoVector pfoVector;
189  for (const std::string &pfoListName : m_pfoListNames)
190  {
191  const PfoList *pPfoList(nullptr);
192 
193  if (PandoraContentApi::GetList(*this, pfoListName, pPfoList) != STATUS_CODE_SUCCESS)
194  continue;
195 
196  for (const ParticleFlowObject *const pPfo : *pPfoList)
197  {
198  // Apply hit cut
199  if (LArPfoHelper::GetNumberOfThreeDHits(pPfo) >= m_minClusterSize)
200  pfoVector.emplace_back(pPfo);
201  }
202  }
203 
204  // Sort to maintain reproducibility
205  std::sort(pfoVector.begin(), pfoVector.end(), LArPfoHelper::SortByNHits);
206 
207  for (const ParticleFlowObject *const pPfo : pfoVector)
208  {
209  // Attempt sliding linear fit
210  try
211  {
212  ClusterList clusters3D;
213  LArPfoHelper::GetThreeDClusterList(pPfo, clusters3D);
214 
215  if (clusters3D.size() != 1)
216  continue;
217 
218  const ThreeDSlidingFitResult slidingFitResult(*clusters3D.begin(), m_slidingFitWindow, slidingFitPitch);
219 
220  // We need directions...
221  ExtremalPoint upstreamPoint, downstreamPoint;
222 
223  if (!this->GetExtremalVerticesAndDirections(pNeutrinoPfo, pPfo, slidingFitResult, upstreamPoint, downstreamPoint))
224  continue;
225 
226  // Create track/shower objects
227  if (pPfo->GetParticleId() == 13)
228  {
229  trackPfos.push_back(HierarchyPfo(pPfo, slidingFitResult, upstreamPoint, downstreamPoint));
230  }
231  else if (pPfo->GetParticleId() == 11)
232  {
233  showerPfos.push_back(HierarchyPfo(pPfo, slidingFitResult, upstreamPoint, downstreamPoint));
234  }
235  }
236  catch (...)
237  {
238  continue;
239  }
240  }
241 }
242 
243 //------------------------------------------------------------------------------------------------------------------------------------------
244 
245 bool DLNeutrinoHierarchyAlgorithm::GetExtremalVerticesAndDirections(const ParticleFlowObject *const pNeutrinoPfo, const ParticleFlowObject *const pPfo,
246  const ThreeDSlidingFitResult &slidingFitResult, ExtremalPoint &upstreamPoint, ExtremalPoint &downstreamPoint) const
247 {
248  // First, get the neutrino vertex
249  const Vertex *const pNeutrinoVertex(LArPfoHelper::GetVertex(pNeutrinoPfo));
250  const CartesianVector nuVertex(
251  pNeutrinoVertex->GetPosition().GetX(), pNeutrinoVertex->GetPosition().GetY(), pNeutrinoVertex->GetPosition().GetZ());
252 
253  if (pPfo->GetParticleId() == 13)
254  {
255  try
256  {
257  const LArPointingCluster pointingCluster(slidingFitResult); // this could throw an exception
258  const CartesianVector innerVertex(pointingCluster.GetInnerVertex().GetPosition().GetX(),
259  pointingCluster.GetInnerVertex().GetPosition().GetY(), pointingCluster.GetInnerVertex().GetPosition().GetZ());
260  CartesianVector innerDirection(pointingCluster.GetInnerVertex().GetDirection().GetX(),
261  pointingCluster.GetInnerVertex().GetDirection().GetY(), pointingCluster.GetInnerVertex().GetDirection().GetZ());
262  const CartesianVector outerVertex(pointingCluster.GetOuterVertex().GetPosition().GetX(),
263  pointingCluster.GetOuterVertex().GetPosition().GetY(), pointingCluster.GetOuterVertex().GetPosition().GetZ());
264  CartesianVector outerDirection(pointingCluster.GetOuterVertex().GetDirection().GetX(),
265  pointingCluster.GetOuterVertex().GetDirection().GetY(), pointingCluster.GetOuterVertex().GetDirection().GetZ());
266 
267  // want them to both point into the particle
268  if (innerDirection.GetDotProduct(outerVertex - innerVertex) < 0.f)
269  innerDirection *= (-1.f);
270 
271  if (outerDirection.GetDotProduct(innerVertex - outerVertex) < 0.f)
272  outerDirection *= (-1.f);
273 
274  // determine upstream/downstream
275  if ((innerVertex - nuVertex).GetMagnitudeSquared() < (outerVertex - nuVertex).GetMagnitudeSquared())
276  {
277  upstreamPoint.Set(innerVertex, innerDirection);
278  downstreamPoint.Set(outerVertex, outerDirection);
279  }
280  else
281  {
282  upstreamPoint.Set(outerVertex, outerDirection);
283  downstreamPoint.Set(innerVertex, innerDirection);
284  }
285  }
286  catch (...)
287  {
288  return false;
289  }
290  }
291  else
292  {
293  // find directions, demand that we have at least one
294  CartesianVector minLayerDir(0.f, 0.f, 0.f), maxLayerDir(0.f, 0.f, 0.f);
295  const bool minLayerDirSet(this->GetShowerDirection(pPfo, slidingFitResult.GetGlobalMinLayerPosition(), minLayerDir));
296  const bool maxLayerDirSet(this->GetShowerDirection(pPfo, slidingFitResult.GetGlobalMaxLayerPosition(), maxLayerDir));
297 
298  if (!minLayerDirSet && !maxLayerDirSet)
299  return false;
300 
301  const float minSepSq((slidingFitResult.GetGlobalMinLayerPosition() - nuVertex).GetMagnitudeSquared());
302  const float maxSepSq((slidingFitResult.GetGlobalMaxLayerPosition() - nuVertex).GetMagnitudeSquared());
303 
304  if (minLayerDirSet)
305  {
306  ExtremalPoint &toChange = (minSepSq < maxSepSq) ? upstreamPoint : downstreamPoint;
307  toChange.Set(slidingFitResult.GetGlobalMinLayerPosition(), minLayerDir);
308  }
309 
310  if (maxLayerDirSet)
311  {
312  ExtremalPoint &toChange = (minSepSq < maxSepSq) ? downstreamPoint : upstreamPoint;
313  toChange.Set(slidingFitResult.GetGlobalMaxLayerPosition(), maxLayerDir);
314  }
315  }
316 
317  return true;
318 }
319 
320 //------------------------------------------------------------------------------------------------------------------------------------------
321 
322 bool DLNeutrinoHierarchyAlgorithm::GetShowerDirection(const ParticleFlowObject *const pPfo, const CartesianVector &vertex, CartesianVector &direction) const
323 {
324  CartesianPointVector pointVector;
325  LArPfoHelper::GetCoordinateVector(pPfo, TPC_3D, pointVector);
326 
327  if (pointVector.empty())
328  return false;
329 
330  // set direction by angular distribution
331  const float angleMin(0.f), angleMax(2.f * M_PI);
332  const float binWidth((angleMax - angleMin) / static_cast<float>(m_nAngularBins));
333 
334  std::vector<std::vector<int>> spatialDist(m_nAngularBins, std::vector<int>(m_nAngularBins, 0));
335  std::vector<std::vector<float>> tieBreakerDist(m_nAngularBins, std::vector<float>(m_nAngularBins, 0.f));
336 
337  int highestSP(0), bestTheta0YZBin(-1), bestTheta0XZBin(-1);
338  float tieBreaker(std::numeric_limits<float>::max());
339 
340  for (const CartesianVector &position3D : pointVector)
341  {
342  const CartesianVector displacement(position3D - vertex);
343  const float mag(displacement.GetMagnitude());
344 
345  if (mag > m_regionForDirFit)
346  continue;
347 
348  const float magXZ(sqrt((displacement.GetX() * displacement.GetX()) + (displacement.GetZ() * displacement.GetZ())));
349 
350  float theta0YZ((mag < std::numeric_limits<float>::epsilon()) ? 0.f
351  : (std::fabs(std::fabs(displacement.GetY() / mag) - 1.f) < std::numeric_limits<float>::epsilon())
352  ? 0.f
353  : std::acos(displacement.GetY() / mag));
354 
355  float theta0XZ((magXZ < std::numeric_limits<float>::epsilon()) ? 0.f
356  : (std::fabs(std::fabs(displacement.GetX() / magXZ) - 1.f) < std::numeric_limits<float>::epsilon())
357  ? 0.f
358  : std::acos(displacement.GetX() / magXZ));
359 
360  // try do signed-ness
361  if (displacement.GetZ() < 0.f)
362  theta0XZ = (2.0 * M_PI) - theta0XZ;
363 
364  const int bin0YZ(std::floor(theta0YZ / binWidth));
365  const int bin0XZ(std::floor(theta0XZ / binWidth));
366 
367  spatialDist[bin0YZ][bin0XZ] += 1;
368  tieBreakerDist[bin0YZ][bin0XZ] += (1.f / mag); // tie-breaker
369 
370  if (((spatialDist[bin0YZ][bin0XZ] == highestSP) && (tieBreakerDist[bin0YZ][bin0XZ] < tieBreaker)) || (spatialDist[bin0YZ][bin0XZ] > highestSP))
371  {
372  highestSP = spatialDist[bin0YZ][bin0XZ];
373  tieBreaker = tieBreakerDist[bin0YZ][bin0XZ];
374  bestTheta0YZBin = bin0YZ;
375  bestTheta0XZBin = bin0XZ;
376  }
377  }
378 
379  if ((bestTheta0YZBin < 0) || (bestTheta0XZBin < 0))
380  return false;
381 
382  const float bestTheta0YZ(angleMin + ((static_cast<float>(bestTheta0YZBin) + 0.5f) * binWidth));
383  const float bestTheta0XZ(angleMin + ((static_cast<float>(bestTheta0XZBin) + 0.5f) * binWidth));
384 
385  direction = CartesianVector(std::sin(bestTheta0YZ) * std::cos(bestTheta0XZ), std::cos(bestTheta0YZ), std::sin(bestTheta0YZ) * std::sin(bestTheta0XZ));
386 
387  return true;
388 }
389 
390 //------------------------------------------------------------------------------------------------------------------------------------------
391 
393  const ParticleFlowObject *const pNeutrinoPfo, HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos) const
394 {
395  for (HierarchyPfo &hierarchyPfo : trackPfos)
396  hierarchyPfo.SetPrimaryScore(this->GetPrimaryScore(pNeutrinoPfo, trackPfos, hierarchyPfo));
397 
398  for (HierarchyPfo &hierarchyPfo : showerPfos)
399  hierarchyPfo.SetPrimaryScore(this->GetPrimaryScore(pNeutrinoPfo, trackPfos, hierarchyPfo));
400 }
401 
402 //------------------------------------------------------------------------------------------------------------------------------------------
403 
405  const ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfo &hierarchyPfo) const
406 {
407  std::vector<DLPrimaryHierarchyTool::DLPrimaryNetworkParams> networkParamVector;
408  float primaryScore(std::numeric_limits<float>::lowest());
409 
410  if (m_primaryHierarchyTool->Run(this, pNeutrinoPfo, trackPfos, hierarchyPfo, networkParamVector, primaryScore) != STATUS_CODE_SUCCESS)
411  return std::numeric_limits<float>::lowest();
412 
413  return primaryScore;
414 }
415 
416 //------------------------------------------------------------------------------------------------------------------------------------------
417 
418 void DLNeutrinoHierarchyAlgorithm::UpdateHierarchy(const ParticleFlowObject *const pNeutrinoPfo, const bool buildPrimaryTier,
419  const bool usePrimaryScore, const float trackThreshold, const float showerThreshold, const bool isLowerThreshold,
420  HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos, Hierarchy &hierarchy) const
421 {
422  bool found(true);
423  unsigned int tierIndex(buildPrimaryTier ? 0 : 1);
424 
425  while (found)
426  {
427  found = false;
428 
429  // If building later tiers, check that we do have primaries
430  if (!buildPrimaryTier && hierarchy.at(0).empty())
431  return;
432 
433  PfoVector &thisTier(hierarchy.at(tierIndex));
434 
435  for (bool isTrack : {true, false})
436  {
437  HierarchyPfoVector &hierarchyPfoVector(isTrack ? trackPfos : showerPfos);
438 
439  for (HierarchyPfo &childHierarchyPfo : hierarchyPfoVector)
440  {
441  const ParticleFlowObject *const pChildPfo(childHierarchyPfo.GetPfo());
442 
443  // Continue if parent already found
444  if (childHierarchyPfo.GetIsInHierarchy())
445  continue;
446 
447  const ParticleFlowObject *pPredictedParent(pNeutrinoPfo);
448 
449  // If not buildPrimaryTier correct pPredictedParent
450  if (!buildPrimaryTier)
451  {
452  // Do we have a predicted parent
453  if (!childHierarchyPfo.GetPredictedParentPfo())
454  continue;
455 
456  // Is predicted parent in preceeding tier?
457  const PfoVector &preceedingTier(hierarchy.at(tierIndex - 1));
458 
459  pPredictedParent = childHierarchyPfo.GetPredictedParentPfo();
460 
461  if (std::find(preceedingTier.begin(), preceedingTier.end(), pPredictedParent) == preceedingTier.end())
462  continue;
463  }
464 
465  // Does it pass tier cut?
466  const float networkScore(usePrimaryScore ? childHierarchyPfo.GetPrimaryScore() : childHierarchyPfo.GetLaterTierScore());
467  const float thresholdScore(isTrack ? trackThreshold : showerThreshold);
468 
469  if ((isLowerThreshold && (networkScore > thresholdScore)) || (!isLowerThreshold && (networkScore < thresholdScore)))
470  {
471  found = true;
472 
473  // Add child to hierarchy tier
474  thisTier.emplace_back(pChildPfo);
475 
476  // Add info to childHierarchyPfo
477  childHierarchyPfo.SetIsInHierarchy(true);
478  childHierarchyPfo.SetParentPfo(pPredictedParent);
479 
480  // Add info to parentPfo
481  if (!buildPrimaryTier)
482  {
483  const auto iter(std::find(trackPfos.begin(), trackPfos.end(), pPredictedParent));
484 
485  if (iter == trackPfos.end())
486  throw StatusCodeException(STATUS_CODE_FAILURE);
487 
488  iter->AddChildPfo(pChildPfo);
489  }
490  }
491  }
492  }
493 
494  // Make sure to add the next tier
495  if (hierarchy.size() == (tierIndex + 1))
496  hierarchy.push_back(PfoVector());
497 
498  // If buildPrimaryTier, our work is done!
499  if (buildPrimaryTier)
500  break;
501 
502  ++tierIndex;
503  }
504 }
505 
506 //------------------------------------------------------------------------------------------------------------------------------------------
507 
509  const ParticleFlowObject *const pNeutrinoPfo, HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos) const
510 {
511  for (bool isTrack : {true, false})
512  {
513  HierarchyPfoVector &hierarchyPfoVector(isTrack ? trackPfos : showerPfos);
514 
515  for (HierarchyPfo &childHierarchyPfo : hierarchyPfoVector)
516  {
517  // Continue if parent already found
518  if (childHierarchyPfo.GetIsInHierarchy())
519  continue;
520 
521  // Only consider for later tier if far away from nu vertex
522  const Vertex *const pNeutrinoVertex(LArPfoHelper::GetVertex(pNeutrinoPfo));
523  const CartesianVector nuVertex(
524  pNeutrinoVertex->GetPosition().GetX(), pNeutrinoVertex->GetPosition().GetY(), pNeutrinoVertex->GetPosition().GetZ());
525 
526  if ((childHierarchyPfo.GetUpstreamPoint().GetPosition() - nuVertex).GetMagnitudeSquared() < (m_primaryRegion * m_primaryRegion))
527  continue;
528 
529  float highestScore(std::numeric_limits<float>::lowest());
530 
531  for (const HierarchyPfo &parentHierarchyPfo : trackPfos)
532  {
533  if (childHierarchyPfo == parentHierarchyPfo)
534  continue;
535 
536  const float thisScore(this->GetLaterTierScore(pNeutrinoPfo, parentHierarchyPfo, childHierarchyPfo));
537 
538  if ((childHierarchyPfo.GetPredictedParentPfo()) && (std::fabs(thisScore - highestScore) < std::numeric_limits<float>::epsilon()))
539  {
540  // If tie, pick closest
541  const float currentSep(LArPfoHelper::GetThreeDSeparation(childHierarchyPfo.GetPredictedParentPfo(), childHierarchyPfo.GetPfo()));
542  const float thisSep(LArPfoHelper::GetThreeDSeparation(parentHierarchyPfo.GetPfo(), childHierarchyPfo.GetPfo()));
543 
544  if (thisSep > currentSep)
545  continue;
546  }
547  else if (thisScore < highestScore)
548  {
549  continue;
550  }
551 
552  highestScore = thisScore;
553  childHierarchyPfo.SetLaterTierScore(thisScore);
554  childHierarchyPfo.SetPredictedParentPfo(parentHierarchyPfo.GetPfo());
555  }
556  }
557  }
558 }
559 
560 //------------------------------------------------------------------------------------------------------------------------------------------
561 
563  const ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfo &parentPfo, const HierarchyPfo &childPfo) const
564 {
565  std::vector<DLLaterTierHierarchyTool::DLLaterTierNetworkParams> networkParamVector;
566  float laterTierScore(std::numeric_limits<float>::lowest());
567 
568  if (m_laterTierHierarchyTool->Run(this, pNeutrinoPfo, parentPfo, childPfo, networkParamVector, laterTierScore) != STATUS_CODE_SUCCESS)
569  return std::numeric_limits<float>::lowest();
570 
571  return laterTierScore;
572 }
573 
574 //------------------------------------------------------------------------------------------------------------------------------------------
575 
577  const ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos) const
578 {
579  PfoVector pfoVector;
580 
581  // Get All pfos
582  for (const std::string &pfoListName : m_pfoListNames)
583  {
584  const PfoList *pPfoList(nullptr);
585 
586  if (PandoraContentApi::GetList(*this, pfoListName, pPfoList) != STATUS_CODE_SUCCESS)
587  continue;
588 
589  for (const ParticleFlowObject *const pPfo : *pPfoList)
590  pfoVector.emplace_back(pPfo);
591  }
592 
593  // Sort to maintain reproducibility
594  std::sort(pfoVector.begin(), pfoVector.end(), LArPfoHelper::SortByNHits);
595 
596  // Build known hierarchy
597  for (const ParticleFlowObject *const pPfo : pfoVector)
598  {
599  const HierarchyPfo *hierarchyPfo(nullptr);
600 
601  const auto trackIter(std::find(trackPfos.begin(), trackPfos.end(), pPfo));
602  const auto showerIter(std::find(showerPfos.begin(), showerPfos.end(), pPfo));
603 
604  if (trackIter != trackPfos.end())
605  {
606  hierarchyPfo = &(*trackIter);
607  }
608  else if (showerIter != showerPfos.end())
609  {
610  hierarchyPfo = &(*showerIter);
611  }
612  else
613  {
614  // If alg never handled the pfo, assign as primary
615  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pNeutrinoPfo, pPfo));
616  continue;
617  }
618 
619  // If pfo was never assigned to hierarchy, add as primary
620  if (!hierarchyPfo->GetIsInHierarchy())
621  {
622  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pNeutrinoPfo, pPfo));
623  continue;
624  }
625 
626  // If parent is a neutrino we have to assign its parent
627  if (hierarchyPfo->GetParentPfo() == pNeutrinoPfo)
628  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pNeutrinoPfo, pPfo));
629 
630  // Assign parent-child links of its children
631  PfoVector childPfos(hierarchyPfo->GetChildPfoVector());
632  std::sort(childPfos.begin(), childPfos.end(), LArPfoHelper::SortByNHits);
633 
634  // Demand that showers do not have children
635  if ((!childPfos.empty()) && (showerIter != showerPfos.end()))
636  throw StatusCodeException(STATUS_CODE_FAILURE);
637 
638  for (const ParticleFlowObject *const pChildPfo : childPfos)
639  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SetPfoParentDaughterRelationship(*this, pPfo, pChildPfo));
640  }
641 }
642 
643 //------------------------------------------------------------------------------------------------------------------------------------------
644 // Training functions
645 //------------------------------------------------------------------------------------------------------------------------------------------
646 
647 #ifdef MONITORING
648 
649 bool DLNeutrinoHierarchyAlgorithm::ShouldTrainOnEvent(const ParticleFlowObject *const pNeutrinoPfo) const
650 {
651  const MCParticleList *pMCParticleList(nullptr);
652  if (PandoraContentApi::GetList(*this, m_mcParticleListName, pMCParticleList) != STATUS_CODE_SUCCESS)
653  return false;
654 
655  if (!pMCParticleList || pMCParticleList->empty())
656  return false;
657 
658  // Apply nu vertex accuracy requirement
659  MCParticleVector mcNeutrinoVector;
660  LArMCParticleHelper::GetTrueNeutrinos(pMCParticleList, mcNeutrinoVector);
661 
662  if (mcNeutrinoVector.size() != 1)
663  return false;
664 
665  const CartesianVector &trueNuVertex(mcNeutrinoVector.front()->GetVertex());
666  const Vertex *const pNeutrinoVertex(LArPfoHelper::GetVertex(pNeutrinoPfo));
667  const CartesianVector recoNuVertex(
668  pNeutrinoVertex->GetPosition().GetX(), pNeutrinoVertex->GetPosition().GetY(), pNeutrinoVertex->GetPosition().GetZ());
669 
670  if ((trueNuVertex - recoNuVertex).GetMagnitudeSquared() > (m_trainingVertexAccuracy * m_trainingVertexAccuracy))
671  return false;
672 
673  return true;
674 }
675 
676 //------------------------------------------------------------------------------------------------------------------------------------------
677 
679  std::map<const ParticleFlowObject *, int> &particleIDMap) const
680 {
681  PfoVector pfoVector;
682 
683  for (const HierarchyPfo &hierarchyPfo : trackPfos)
684  pfoVector.push_back(hierarchyPfo.GetPfo());
685 
686  for (const HierarchyPfo &hierarchyPfo : showerPfos)
687  pfoVector.push_back(hierarchyPfo.GetPfo());
688 
689  std::sort(pfoVector.begin(), pfoVector.end(), LArPfoHelper::SortByNHits);
690 
691  for (const ParticleFlowObject *const pPfo : pfoVector)
692  particleIDMap[pPfo] = particleIDMap.size();
693 }
694 
695 //------------------------------------------------------------------------------------------------------------------------------------------
696 
698  const int nPrimaryTrackLinks, const int nPrimaryShowerLinks, const int nLaterTierTrackTrackLinks, const int nLaterTierTrackShowerLinks) const
699 {
700  const int nParticles(trackPfos.size() + showerPfos.size());
701 
702  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_eventTreeName.c_str(), "NRecoParticles", nParticles));
703  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_eventTreeName.c_str(), "EventID", m_eventID));
704  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_eventTreeName.c_str(), "NPrimaryTrackLinks", nPrimaryTrackLinks));
705  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_eventTreeName.c_str(), "NPrimaryShowerLinks", nPrimaryShowerLinks));
706  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_eventTreeName.c_str(), "NLaterTierTrackTrackLinks", nLaterTierTrackTrackLinks));
707  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_eventTreeName.c_str(), "NLaterTierTrackShowerLinks", nLaterTierTrackShowerLinks));
708  PANDORA_MONITORING_API(FillTree(this->GetPandora(), m_eventTreeName.c_str()));
709 }
710 
711 //------------------------------------------------------------------------------------------------------------------------------------------
712 
713 void DLNeutrinoHierarchyAlgorithm::FillPrimaryTrees(const PfoToMCParticleMap &matchingMap, const ChildToParentPfoMap &childToParentPfoMap,
714  const ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos,
715  const std::map<const ParticleFlowObject *, int> &particleIDMap, int &nPrimaryTrackLinks, int &nPrimaryShowerLinks) const
716 {
717  const bool isTrainingEvent(this->ShouldTrainOnEvent(pNeutrinoPfo));
718 
719  for (const bool isTrack : {true, false})
720  {
721  const std::string treeName(isTrack ? m_primaryTrackTreeName : m_primaryShowerTreeName);
722  const HierarchyPfoVector &hierarchyPfoVector(isTrack ? trackPfos : showerPfos);
723 
724  for (const HierarchyPfo &hierarchyPfo : hierarchyPfoVector)
725  {
726  const ParticleFlowObject *const pPfo(hierarchyPfo.GetPfo());
727 
728  // Get particle ID
729  if (particleIDMap.find(pPfo) == particleIDMap.end())
730  continue;
731 
732  const int particleID(particleIDMap.at(pPfo));
733 
734  // Is training link?
735  bool isNeutronChild(false);
736  bool isTrainingLink(isTrainingEvent &&
737  !((m_cheatHierarchyTool->IsNeutronChild(pPfo, matchingMap, isNeutronChild) != STATUS_CODE_SUCCESS) || isNeutronChild));
738 
739  // Get the true info
740  // Orientation == true if true start point is at upstream position
741  bool isTrueLink(false), trueChildOrientation(false);
742  if (m_cheatHierarchyTool->Run(matchingMap, childToParentPfoMap, pNeutrinoPfo, hierarchyPfo, isTrueLink, trueChildOrientation) != STATUS_CODE_SUCCESS)
743  {
744  continue;
745  }
746 
747  // Get true hierarchy info
748  const MCParticle *const pMCParticle(matchingMap.at(pPfo));
749  const int matchedPDG(pMCParticle->GetParticleId());
750  const ParticleFlowObject *const pTrueParentPfo(childToParentPfoMap.at(pPfo).first);
751  const int trueVisibleGen(childToParentPfoMap.at(pPfo).second);
752 
753  int trueParentID(-1); // default neutrino
754  if (pTrueParentPfo != pNeutrinoPfo)
755  {
756  if (particleIDMap.find(pTrueParentPfo) == particleIDMap.end())
757  continue;
758 
759  trueParentID = particleIDMap.at(pTrueParentPfo);
760  }
761 
762  // Get reco info
763  std::vector<DLPrimaryHierarchyTool::DLPrimaryNetworkParams> networkParamVector;
764  float primaryScore(std::numeric_limits<float>::lowest());
765 
766  if (m_primaryHierarchyTool->Run(this, pNeutrinoPfo, trackPfos, hierarchyPfo, networkParamVector, primaryScore) != STATUS_CODE_SUCCESS)
767  continue;
768 
769  for (const DLPrimaryHierarchyTool::DLPrimaryNetworkParams &networkParams : networkParamVector)
770  {
771  const bool useChildUpstream(std::fabs(networkParams.m_isPOIClosestToNu - 1.f) < std::numeric_limits<float>::epsilon());
772 
773  this->FillPrimaryTree(treeName, isTrainingLink, isTrueLink, (useChildUpstream == trueChildOrientation), trueVisibleGen,
774  matchedPDG, trueParentID, particleID, networkParams);
775 
776  isTrack ? ++nPrimaryTrackLinks : ++nPrimaryShowerLinks;
777  }
778  }
779  }
780 }
781 
782 //------------------------------------------------------------------------------------------------------------------------------------------
783 
784 void DLNeutrinoHierarchyAlgorithm::FillPrimaryTree(const std::string &treeName, const bool isTrainingLink, const bool isTrueLink,
785  const bool isOrientationCorrect, const int trueVisibleGen, const int truePDG, const int trueParentID, const int particleID,
786  const DLPrimaryHierarchyTool::DLPrimaryNetworkParams &primaryNetworkParams) const
787 {
788  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "EventID", m_eventID));
789  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParticleID", particleID));
790  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "IsTrainingLink", (isTrainingLink ? 1 : 0)));
791  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "IsTrueLink", (isTrueLink ? 1 : 0)));
792  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "IsOrientationCorrect", (isOrientationCorrect ? 1 : 0)));
793  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "TrueVisibleGeneration", trueVisibleGen));
794  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "TruePDG", truePDG));
795  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "TrueVisibleParentID", trueParentID));
796  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "NSpacepoints", primaryNetworkParams.m_nSpacepoints));
797  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "NuSeparation", primaryNetworkParams.m_nuSeparation));
798  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "VertexRegionNHits", primaryNetworkParams.m_vertexRegionNHits));
799  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "VertexRegionNParticles", primaryNetworkParams.m_vertexRegionNParticles));
800  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "DCA", primaryNetworkParams.m_dca));
801  PANDORA_MONITORING_API(
802  SetTreeVariable(this->GetPandora(), treeName.c_str(), "ConnectionExtrapDistance", primaryNetworkParams.m_connectionExtrapDistance));
803  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "IsPOIClosestToNu", primaryNetworkParams.m_isPOIClosestToNu));
804  PANDORA_MONITORING_API(
805  SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentConnectionDistance", primaryNetworkParams.m_parentConnectionDistance));
806  PANDORA_MONITORING_API(
807  SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildConnectionDistance", primaryNetworkParams.m_childConnectionDistance));
808  PANDORA_MONITORING_API(FillTree(this->GetPandora(), treeName.c_str()));
809 }
810 
811 //------------------------------------------------------------------------------------------------------------------------------------------
812 
813 void DLNeutrinoHierarchyAlgorithm::FillLaterTierTrees(const PfoToMCParticleMap &matchingMap, const ChildToParentPfoMap &childToParentPfoMap,
814  const ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos,
815  const std::map<const ParticleFlowObject *, int> &particleIDMap, int &nTrackLinks, int &nShowerLinks) const
816 {
817  const bool isTrainingEvent(this->ShouldTrainOnEvent(pNeutrinoPfo));
818 
819  for (const HierarchyPfo &hierarchyParentPfo : trackPfos)
820  {
821  const ParticleFlowObject *const pParentPfo(hierarchyParentPfo.GetPfo());
822 
823  for (const bool isTrack : {true, false})
824  {
825  const std::string treeName(isTrack ? m_laterTierTrackTrackTreeName : m_laterTierTrackShowerTreeName);
826  const HierarchyPfoVector &hierarchyPfoVector(isTrack ? trackPfos : showerPfos);
827 
828  for (const HierarchyPfo &hierarchyChildPfo : hierarchyPfoVector)
829  {
830  const ParticleFlowObject *const pChildPfo(hierarchyChildPfo.GetPfo());
831 
832  if (pParentPfo == pChildPfo)
833  continue;
834 
835  // Get particle IDs
836  if ((particleIDMap.find(pParentPfo) == particleIDMap.end()) || (particleIDMap.find(pChildPfo) == particleIDMap.end()))
837  {
838  continue;
839  }
840 
841  const int parentID(particleIDMap.at(pParentPfo));
842  const int childID(particleIDMap.at(pChildPfo));
843 
844  // Get true primary info
845  bool isTruePrimaryLink(false), tempBool(false);
846  if (m_cheatHierarchyTool->Run(matchingMap, childToParentPfoMap, pNeutrinoPfo, hierarchyChildPfo, isTruePrimaryLink, tempBool) != STATUS_CODE_SUCCESS)
847  {
848  continue;
849  }
850 
851  // Do not train on child primaries
852  bool isTrainingLink(isTrainingEvent && !isTruePrimaryLink);
853 
854  // Get the true info
855  // Orientation == true if true start point is at upstream position
856  bool isTrueLink(false), trueParentOrientation(false), trueChildOrientation(false);
857  if (m_cheatHierarchyTool->Run(matchingMap, childToParentPfoMap, hierarchyParentPfo, hierarchyChildPfo, isTrueLink,
858  trueParentOrientation, trueChildOrientation) != STATUS_CODE_SUCCESS)
859  {
860  continue;
861  }
862 
863  // Get true hierarchy info
864  const int trueVisibleGen(childToParentPfoMap.at(pChildPfo).second);
865 
866  // For parent we care about the endpoint orientation
867  trueParentOrientation = !trueParentOrientation;
868 
869  // Now get DL info for ALL orientations
870  float laterTierScore(std::numeric_limits<float>::lowest());
871  std::vector<DLLaterTierHierarchyTool::DLLaterTierNetworkParams> networkParamVector;
872 
873  if (m_laterTierHierarchyTool->Run(this, pNeutrinoPfo, hierarchyParentPfo, hierarchyChildPfo, networkParamVector, laterTierScore) != STATUS_CODE_SUCCESS)
874  continue;
875 
876  // Check that we have an edge with correctLinkOrientation
877  int nCorrectLinkOrientation(0);
878  for (const DLLaterTierHierarchyTool::DLLaterTierNetworkParams &networkParams : networkParamVector)
879  {
880  const bool useParentUpstream(std::fabs(networkParams.m_parentIsPOIClosestToNu - 1.f) < std::numeric_limits<float>::epsilon());
881  const bool useChildUpstream(std::fabs(networkParams.m_childIsPOIClosestToNu - 1.f) < std::numeric_limits<float>::epsilon());
882  const bool isOrientationCorrect((useParentUpstream == trueParentOrientation) && (useChildUpstream == trueChildOrientation));
883 
884  if (isOrientationCorrect)
885  ++nCorrectLinkOrientation;
886  }
887 
888  // For training, make sure we have one correct orientation link
889  isTrainingLink = (isTrainingLink && (nCorrectLinkOrientation == 1));
890 
891  // Get training cut info
892  std::pair<float, float> trainingCuts({std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest()});
893 
894  if (isTrainingLink)
895  trainingCuts = this->GetTrainingCuts(hierarchyParentPfo, hierarchyChildPfo, trueParentOrientation, trueChildOrientation);
896 
897  for (const DLLaterTierHierarchyTool::DLLaterTierNetworkParams &networkParams : networkParamVector)
898  {
899  const bool useParentUpstream(std::fabs(networkParams.m_parentIsPOIClosestToNu - 1.f) < std::numeric_limits<float>::epsilon());
900  const bool useChildUpstream(std::fabs(networkParams.m_childIsPOIClosestToNu - 1.f) < std::numeric_limits<float>::epsilon());
901  const bool isOrientationCorrect((useParentUpstream == trueParentOrientation) && (useChildUpstream == trueChildOrientation));
902 
903  this->FillLaterTierTree(treeName, isTrainingLink, isTrueLink, isOrientationCorrect, trueVisibleGen, trainingCuts,
904  parentID, childID, networkParams);
905 
906  isTrack ? ++nTrackLinks : ++nShowerLinks;
907  }
908  }
909  }
910  }
911 }
912 
913 //------------------------------------------------------------------------------------------------------------------------------------------
914 
915 std::pair<float, float> DLNeutrinoHierarchyAlgorithm::GetTrainingCuts(const HierarchyPfo &parentHierarchyPfo,
916  const HierarchyPfo &childHierarchyPfo, const bool trueParentOrientation, const bool trueChildOrientation) const
917 {
918  std::pair<float, float> trainingCuts({std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest()});
919  const ExtremalPoint &parentEnd(trueParentOrientation ? parentHierarchyPfo.GetUpstreamPoint() : parentHierarchyPfo.GetDownstreamPoint());
920  const ExtremalPoint &childStart(trueChildOrientation ? childHierarchyPfo.GetUpstreamPoint() : childHierarchyPfo.GetDownstreamPoint());
921 
922  m_primaryHierarchyTool->CalculateConnectionDistances(parentEnd, childStart, trainingCuts.first, trainingCuts.second);
923 
924  return trainingCuts;
925 }
926 
927 //------------------------------------------------------------------------------------------------------------------------------------------
928 
929 void DLNeutrinoHierarchyAlgorithm::FillLaterTierTree(const std::string &treeName, const bool isTrainingLink, const bool isTrueLink,
930  const bool isOrientationCorrect, const int childTrueGen, const std::pair<float, float> &trainingCuts, const int parentID,
931  const int childID, const DLLaterTierHierarchyTool::DLLaterTierNetworkParams &networkParams) const
932 {
933  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "EventID", m_eventID));
934  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentParticleID", parentID));
935  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildParticleID", childID));
936  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "IsTrainingLink", (isTrainingLink ? 1 : 0)));
937  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "IsTrueLink", (isTrueLink ? 1 : 0)));
938  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "IsOrientationCorrect", (isOrientationCorrect ? 1 : 0)));
939  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildTrueVisibleGeneration", childTrueGen));
940  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "TrainingCutL", trainingCuts.first));
941  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "TrainingCutT", trainingCuts.second));
942  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentTrackScore", networkParams.m_parentTrackScore));
943  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildTrackScore", networkParams.m_childTrackScore));
944  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentNSpacepoints", networkParams.m_parentNSpacepoints));
945  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildNSpacepoints", networkParams.m_childNSpacepoints));
946  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "Separation3D", networkParams.m_separation3D));
947  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentNuVertexSep", networkParams.m_parentNuVertexSep));
948  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildNuVertexSep", networkParams.m_childNuVertexSep));
949  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentEndRegionNHits", networkParams.m_parentEndRegionNHits));
950  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentEndRegionNParticles", networkParams.m_parentEndRegionNParticles));
951  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentEndRegionRToWall", networkParams.m_parentEndRegionRToWall));
952  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "VertexSeparation", networkParams.m_vertexSeparation));
953  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "DoesChildConnect", networkParams.m_doesChildConnect));
954  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "OvershootStartDCA", networkParams.m_overshootStartDCA));
955  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "OvershootStartL", networkParams.m_overshootStartL));
956  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "OvershootEndDCA", networkParams.m_overshootEndDCA));
957  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "OvershootEndL", networkParams.m_overshootEndL));
958  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildCPDCA", networkParams.m_childCPDCA));
959  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildCPExtrapDistance", networkParams.m_childCPExtrapDistance));
960  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildCPLRatio", networkParams.m_childCPLRatio));
961  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentCPNUpstreamHits", networkParams.m_parentCPNUpstreamHits));
962  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentCPNDownstreamHits", networkParams.m_parentCPNDownstreamHits));
963  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentCPNHitRatio", networkParams.m_parentCPNHitRatio));
964  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentCPEigenvalueRatio", networkParams.m_parentCPEigenvalueRatio));
965  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentCPOpeningAngle", networkParams.m_parentCPOpeningAngle));
966  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ParentIsPOIClosestToNu", networkParams.m_parentIsPOIClosestToNu));
967  PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), treeName.c_str(), "ChildIsPOIClosestToNu", networkParams.m_childIsPOIClosestToNu));
968  PANDORA_MONITORING_API(FillTree(this->GetPandora(), treeName.c_str()));
969 }
970 
971 #endif
972 
973 //------------------------------------------------------------------------------------------------------------------------------------------
974 
975 StatusCode DLNeutrinoHierarchyAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
976 {
977  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "EventID", m_eventID));
978  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingMode", m_trainingMode));
979  PANDORA_RETURN_RESULT_IF_AND_IF(
980  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MCParticleListName", m_mcParticleListName));
981  PANDORA_RETURN_RESULT_IF_AND_IF(
982  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingVertexAccuracy", m_trainingVertexAccuracy));
983  PANDORA_RETURN_RESULT_IF_AND_IF(
984  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingFileName", m_trainingFileName));
985  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "EventTreeName", m_eventTreeName));
986  PANDORA_RETURN_RESULT_IF_AND_IF(
987  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PrimaryTrackTreeName", m_primaryTrackTreeName));
988  PANDORA_RETURN_RESULT_IF_AND_IF(
989  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PrimaryShowerTreeName", m_primaryShowerTreeName));
990  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
991  XmlHelper::ReadValue(xmlHandle, "LaterTierTrackTrackTreeName", m_laterTierTrackTrackTreeName));
992  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
993  XmlHelper::ReadValue(xmlHandle, "LaterTierTrackShowerTreeName", m_laterTierTrackShowerTreeName));
994  PANDORA_RETURN_RESULT_IF_AND_IF(
995  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NeutrinoPfoListName", m_neutrinoPfoListName));
996  PANDORA_RETURN_RESULT_IF_AND_IF(
997  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "PfoListNames", m_pfoListNames));
998  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterSize", m_minClusterSize));
999  PANDORA_RETURN_RESULT_IF_AND_IF(
1000  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
1001  PANDORA_RETURN_RESULT_IF_AND_IF(
1002  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "RegionForDirectionFit", m_regionForDirFit));
1003  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NAngularBins", m_nAngularBins));
1004  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PrimaryRegion", m_primaryRegion));
1005  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1006  XmlHelper::ReadValue(xmlHandle, "PrimaryThresholdTrackPass1", m_primaryThresholdTrackPass1));
1007  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1008  XmlHelper::ReadValue(xmlHandle, "PrimaryThresholdShowerPass1", m_primaryThresholdShowerPass1));
1009  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1010  XmlHelper::ReadValue(xmlHandle, "LaterTierThresholdTrackPass1", m_laterTierThresholdTrackPass1));
1011  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1012  XmlHelper::ReadValue(xmlHandle, "LaterTierThresholdShowerPass1", m_laterTierThresholdShowerPass1));
1013  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1014  XmlHelper::ReadValue(xmlHandle, "PrimaryThresholdTrackPass2", m_primaryThresholdTrackPass2));
1015  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1016  XmlHelper::ReadValue(xmlHandle, "PrimaryThresholdShowerPass2", m_primaryThresholdShowerPass2));
1017  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1018  XmlHelper::ReadValue(xmlHandle, "LaterTierThresholdTrackPass2", m_laterTierThresholdTrackPass2));
1019  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
1020  XmlHelper::ReadValue(xmlHandle, "LaterTierThresholdShowerPass2", m_laterTierThresholdShowerPass2));
1021 
1022  AlgorithmTool *pAlgorithmTool(nullptr);
1023  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "DLPrimaryHierarchyTool", pAlgorithmTool));
1024  m_primaryHierarchyTool = dynamic_cast<DLPrimaryHierarchyTool *>(pAlgorithmTool);
1025 
1027  return STATUS_CODE_INVALID_PARAMETER;
1028 
1029  pAlgorithmTool = nullptr;
1030  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "DLLaterTierHierarchyTool", pAlgorithmTool));
1031  m_laterTierHierarchyTool = dynamic_cast<DLLaterTierHierarchyTool *>(pAlgorithmTool);
1032 
1034  return STATUS_CODE_INVALID_PARAMETER;
1035 
1036  if (m_trainingMode)
1037  {
1038  pAlgorithmTool = nullptr;
1039  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "DLCheatHierarchyTool", pAlgorithmTool));
1040  m_cheatHierarchyTool = dynamic_cast<DLCheatHierarchyTool *>(pAlgorithmTool);
1041 
1042  if (!m_cheatHierarchyTool)
1043  return STATUS_CODE_INVALID_PARAMETER;
1044  }
1045 
1046  return STATUS_CODE_SUCCESS;
1047 }
1048 
1049 } // namespace lar_dl_content
float m_parentNuVertexSep
the separation between the neutrino vertex and assumed parent start point
void Set(const pandora::CartesianVector &position, const pandora::CartesianVector &direction)
Set the the extremal point&#39;s position and direction.
float m_primaryThresholdTrackPass2
The threshold applied to tracks in pass 2 primary tier building.
HierarchyPfo class.
float m_primaryThresholdShowerPass2
The threshold applied to showers in pass 2 primary tier building.
float m_parentCPEigenvalueRatio
the ratio of the second eigenvalues of the downstream and upstream 3D hit groups (set if the child co...
Header file for the pfo helper class.
void FillEventTree(const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos, const int nPrimaryTrackLinks, const int nPrimaryShowerLinks, const int nLaterTierTrackTrackLinks, const int nLaterTierTrackShowerLinks) const
Fill the output event tree (containing event-level info)
float m_overshootEndL
the extension distance of the child to the DCA point (set if the child doesn&#39;t connect) ...
Header file for the lar pointing cluster class.
float m_laterTierThresholdTrackPass2
The threshold applied to track-track links in pass 2 later tier building.
void FillHierarchyMap(const pandora::Algorithm *const pAlgorithm, PfoToMCParticleMap &pfoToMCParticleMap, ChildToParentPfoMap &childToParentPfoMap) const
Determine the true child -> parent pfo visible matches, filling the pfo->MCParticle matching map in t...
std::string m_primaryTrackTreeName
the name of the output primary track link tree
bool ShouldTrainOnEvent(const pandora::ParticleFlowObject *const pNeutrinoPfo) const
Whether the event should be trained on.
float m_overshootStartL
the extension distance of the child to the DCA point (set if the child doesn&#39;t connect) ...
void FillPrimaryTree(const std::string &treeName, const bool isTrainingLink, const bool isTrueLink, const bool isOrientationCorrect, const int trueVisibleGen, const int truePDG, const int trueParentID, const int particleID, const DLPrimaryHierarchyTool::DLPrimaryNetworkParams &primaryNetworkParams) const
Enter an entry into the specified primary tree.
Header file for lar pfo objects.
void FillPrimaryTrees(const PfoToMCParticleMap &matchingMap, const ChildToParentPfoMap &childToParentPfoMap, const pandora::ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos, const std::map< const pandora::ParticleFlowObject *, int > &particleIDMap, int &nPrimaryTrackLinks, int &nPrimaryShowerLinks) const
Fill the primary trees (containing primary link info)
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::StringVector m_pfoListNames
the name of the pfo lists
float m_childCPDCA
the DCA of the child to the connection point (set if the child connects)
float m_parentEndRegionNHits
the number of 3D hits &#39;close to&#39; the parent POI
void FillLaterTierTrees(const PfoToMCParticleMap &matchingMap, const ChildToParentPfoMap &childToParentPfoMap, const pandora::ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos, const std::map< const pandora::ParticleFlowObject *, int > &particleIDMap, int &nTrackLinks, int &nShowerLinks) const
Fill the later tier trees (containing later tier link info)
float m_parentEndRegionNParticles
the number of different particles &#39;close to&#39; the parent POI
std::string m_primaryShowerTreeName
the name of the output primary shower link tree
void FillTrackShowerVectors(const pandora::ParticleFlowObject *const pNeutrinoPfo, HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos) const
Fill the track and shower-like HierarchyPfoVector.
pandora::StatusCode Run(const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfo &parentHierarchyPfo, const HierarchyPfo &childHierarchyPfo, std::vector< DLLaterTierNetworkParams > &networkParamVector, float &laterTierScore)
float m_primaryThresholdTrackPass1
The threshold applied to tracks in pass 1 primary tier building.
std::string m_mcParticleListName
the name of the MCParticle list
Header file for the HierarchyPfo class.
float m_parentCPNHitRatio
the ratio of the number of downstream hits and upstream 3D hits (set if the child connects) ...
pandora::StatusCode Run(const PfoToMCParticleMap &pfoToMCParticleMap, const ChildToParentPfoMap &childToParentPfoMap, const HierarchyPfo &parentPfo, const HierarchyPfo &childPfo, bool &isTrueLink, bool &trueParentOrientation, bool &trueChildOrientation)
float m_overshootStartDCA
the DCA of the child to the parent startpoint (set if the child doesn&#39;t connect)
Header file for the DL primary hierarchy tool.
float m_separation3D
the smallest 3D distance between the parent and child 3D hits
std::string m_laterTierTrackTrackTreeName
the name of the output track-track later tier link tree
void BuildPandoraHierarchy(const pandora::ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos) const
Register the parent-child relationships in Pandora.
float m_vertexSeparation
the separation between the parent and child POIs
std::map< const pandora::ParticleFlowObject *, std::pair< const pandora::ParticleFlowObject *, int > > ChildToParentPfoMap
LArPointingCluster class.
std::vector< HierarchyPfo > HierarchyPfoVector
DLCheatHierarchyTool to calculate variables related to the initial shower region. ...
void GetParticleIDMap(const HierarchyPfoVector &trackPfos, const HierarchyPfoVector &showerPfos, std::map< const pandora::ParticleFlowObject *, int > &particleIDMap) const
Obtain the [pfo -> unique ID] map.
float GetLaterTierScore(const pandora::ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfo &parentPfo, const HierarchyPfo &childPfo) const
Call the later tier network tool to obtain the later tier score of a parent-child link...
float m_overshootEndDCA
the DCA of the child to the parent endpoint (set if the child doesn&#39;t connect)
float m_vertexRegionNHits
the number of 3D hits &#39;close to&#39; the POI
float m_parentCPNUpstreamHits
the number of 3D parent hits upstream of the connection point (set if the child connects) ...
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
Header file for the cheat hierarchy tool.
float m_parentCPOpeningAngle
the opening angle between the first eigenvectors of the downstream and upstream 3D hit groups (set if...
float m_dca
the distance of closest approach from the POI to the nu vertex
const pandora::ParticleFlowObject * GetParentPfo() const
Get the parent pfo.
const ExtremalPoint & GetUpstreamPoint() const
Get the upstream extremal point.
Header file for the lar monte carlo particle helper helper class.
ExtremalPoint class.
const ExtremalPoint & GetDownstreamPoint() const
Get the downstream extremal point.
const Vertex & GetOuterVertex() const
Get the outer vertex.
std::string m_neutrinoPfoListName
the name of the neutrino pfo list
bool GetExtremalVerticesAndDirections(const pandora::ParticleFlowObject *const pNeutrinoPfo, const pandora::ParticleFlowObject *const pPfo, const ThreeDSlidingFitResult &slidingFitResult, ExtremalPoint &upstreamPoint, ExtremalPoint &downstreamPoint) const
Identify the upstream (closest to the nu vertex) and downstream (furthest from the nu vertex) endpoin...
pandora::StatusCode IsNeutronChild(const pandora::ParticleFlowObject *const pPfo, const PfoToMCParticleMap &pfoToMCParticleMap, bool &isNeutronChild) const
Whether the true invisible parent of a particle is a neutron.
const Vertex & GetInnerVertex() const
Get the inner vertex.
float m_parentCPNDownstreamHits
the number of 3D parent hits downstream of the connection point (set if the child connects) ...
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
std::string m_laterTierTrackShowerTreeName
the name of the output track-shower later tier link tree
std::string m_trainingFileName
the name of the output training file
DLLaterTierHierarchyTool to apply the later-tier hierarchy DL networks.
float m_parentEndRegionRToWall
the smallest parent POI to detector boundary separation
pandora::StatusCode Run(const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfo &hierarchyPfo, std::vector< DLPrimaryNetworkParams > &networkParamVector, float &primaryScore)
const pandora::CartesianVector & GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
bool GetNeutrinoPfo(const pandora::ParticleFlowObject *&pNeutrinoPfo) const
Return the neutrino pfo.
float m_parentTrackScore
the track/shower score of the parent pfo
bool m_trainingMode
whether to run in training mode
Header file for the lar three dimensional sliding fit result class.
float m_primaryRegion
the radius of the nu vertex region where particles are assumed to be primaries
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
float m_primaryThresholdShowerPass1
The threshold applied to showers in pass 1 primary tier building.
float m_nuSeparation
the sep. between the POI and the nu vertex
Header file for the DL neutrino hierarchy algorithm class.
float m_doesChildConnect
whether the backwards trace of the child&#39;s path connects to the parent
void FillLaterTierTree(const std::string &treeName, const bool isTrainingLink, const bool isTrueLink, const bool isOrientationCorrect, const int childTrueGen, const std::pair< float, float > &trainingCuts, const int parentID, const int childID, const DLLaterTierHierarchyTool::DLLaterTierNetworkParams &networkParams) const
Enter an entry into the specified later tier tree.
float m_isPOIClosestToNu
whether the POI is that closest to the nu vertex
std::pair< float, float > GetTrainingCuts(const HierarchyPfo &parentHierarchyPfo, const HierarchyPfo &childHierarchyPfo, const bool trueParentOrientation, const bool trueChildOrientation) const
Get the training cuts for the later tier parent-child link these describe how well the child points b...
float m_connectionExtrapDistance
the sep. between the POI and the DCA point
int m_slidingFitWindow
the sliding fit window to use in pfo sliding linear fits
DLLaterTierHierarchyTool * m_laterTierHierarchyTool
The tool used to build the later tiers.
void CalculateConnectionDistances(const ExtremalPoint &parentPoint, const ExtremalPoint &childPoint, float &parentConnectionDistance, float &childConnectionDistance) const
Calculate the variables describing the extension of a child particle to a given parent (m_parentConne...
float m_childConnectionDistance
the sep. between the POI and the extension point for m_parentConnectionDistance
float m_regionForDirFit
the radius of the region used in shower direction fits
float m_laterTierThresholdTrackPass1
The threshold applied to track-track links in pass 1 later tier building.
void SetLaterTierScores(const pandora::ParticleFlowObject *const pNeutrinoPfo, HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos) const
Set the predicted parent and later tier score of the HierarchyPfos to be considered for the later tie...
DLPrimaryHierarchyTool * m_primaryHierarchyTool
The tool used to build the primary tiers.
std::string m_eventTreeName
the name of the output event tree
float m_childCPLRatio
the ratio of the parent length at the connection point and the full parent length (set if the child c...
unsigned int m_minClusterSize
the minimum threshold of 3D hits of a considered pfo
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
float m_vertexRegionNParticles
the number of different particles &#39;close to&#39; the POI
DLPrimaryHierarchyTool to apply the primary hierarchy DL networks.
float m_laterTierThresholdShowerPass2
The threshold applied to track-shower links in pass 2 later tier building.
DLCheatHierarchyTool * m_cheatHierarchyTool
The tool used to obtain the true hierarchy.
bool GetShowerDirection(const pandora::ParticleFlowObject *const pPfo, const pandora::CartesianVector &vertex, pandora::CartesianVector &direction) const
Obtain the direction of a shower at a given endpoint from the angular decomposition of the shower&#39;s &#39;...
float m_childCPExtrapDistance
the extension distance of the child to the DCA point (set if the child connects)
bool GetIsInHierarchy() const
Get whether the pfo has been assigned to a particle hierarchy.
float m_parentIsPOIClosestToNu
whether the parent POI is that closest to the neutrino vertex
int m_nAngularBins
the number of angle bins used by the shower direction fitter
Header file for the DL later hierarchy tool.
std::map< const pandora::ParticleFlowObject *, const pandora::MCParticle * > PfoToMCParticleMap
float GetPrimaryScore(const pandora::ParticleFlowObject *const pNeutrinoPfo, const HierarchyPfoVector &trackPfos, const HierarchyPfo &hierarchyPfo) const
Call the primary network tool to obtain the primary score of a HierarchyPfo.
float m_trainingVertexAccuracy
the maximum true-reco nu vertex displacement allowed for training
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
void SetPrimaryScores(const pandora::ParticleFlowObject *const pNeutrinoPfo, HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos) const
Set the primary network scores of the HierarchyPfos.
float m_parentNSpacepoints
the number of 3D hits in the parent pfo
float m_childIsPOIClosestToNu
whether the child POI is that closest to the neutrino vertex
float m_childNuVertexSep
the separation between the neutrino vertex and assumed child start point
float m_parentConnectionDistance
the DCA to the most likely parent pfo endpoint
void UpdateHierarchy(const pandora::ParticleFlowObject *const pNeutrinoPfo, const bool buildPrimaryTier, const bool usePrimaryScore, const float trackThreshold, const float showerThreshold, const bool isLowerThreshold, HierarchyPfoVector &trackPfos, HierarchyPfoVector &showerPfos, Hierarchy &hierarchy) const
Add particles to the hierarchy if they satisfy a criteria.
const pandora::PfoVector & GetChildPfoVector() const
Get the vector of child pfos.
float m_laterTierThresholdShowerPass1
The threshold applied to track-shower links in pass 1 later tier building.
const pandora::CartesianVector & GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
vertex reconstruction