LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ElectronInitialRegionRefinementAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
19 
26 
27 using namespace pandora;
28 
29 namespace lar_content
30 {
31 
32 ElectronInitialRegionRefinementAlgorithm::ElectronInitialRegionRefinementAlgorithm() :
33  m_minShowerHits3D(50),
34  m_showerSlidingFitWindow(1000),
35  m_maxCoincidenceTransverseSeparation(5.f),
36  m_minSpinePurity(0.7f),
37  m_trainingMode(false),
38  m_trainingFileName("ConnectionPathwayTrain.txt"),
39  m_unambiguousThreshold(0.5f),
40  m_maxConnectionDistance(1.f),
41  m_minNConnectedHits(2),
42  m_minElectronCompleteness(0.33f),
43  m_minElectronPurity(0.5f),
44  m_maxSeparationFromHit(3.f),
45  m_maxProjectionSeparation(5.f),
46  m_maxXSeparation(0.5f)
47 {
48 }
49 
50 //------------------------------------------------------------------------------------------------------------------------------------------
51 
53 {
54  PfoVector showerPfoVector;
55  this->FillShowerPfoVector(showerPfoVector);
56 
57  if (showerPfoVector.empty())
58  return STATUS_CODE_SUCCESS;
59 
60  for (const ParticleFlowObject *const pShowerPfo : showerPfoVector)
61  {
62  // Only consider significant showers
63  CaloHitList caloHits3D;
64  LArPfoHelper::GetCaloHits(pShowerPfo, TPC_3D, caloHits3D);
65 
66  if (caloHits3D.size() < m_minShowerHits3D)
67  continue;
68 
69  this->RefineShower(pShowerPfo);
70  }
71 
72  return STATUS_CODE_SUCCESS;
73 }
74 
75 //------------------------------------------------------------------------------------------------------------------------------------------
76 
78 {
79  const PfoList *pPfoList(nullptr);
80 
81  if (PandoraContentApi::GetList(*this, m_showerPfoListName, pPfoList) != STATUS_CODE_SUCCESS)
82  return;
83 
84  if (!pPfoList || pPfoList->empty())
85  {
86  std::cout << "ElectronInitialRegionRefinementAlgorithm: unable to find shower pfo list " << m_showerPfoListName << std::endl;
87  return;
88  }
89 
90  showerPfoVector.insert(showerPfoVector.begin(), pPfoList->begin(), pPfoList->end());
91 
92  std::sort(showerPfoVector.begin(), showerPfoVector.end(), LArPfoHelper::SortByNHits);
93 }
94 
95 //------------------------------------------------------------------------------------------------------------------------------------------
96 
97 void ElectronInitialRegionRefinementAlgorithm::RefineShower(const ParticleFlowObject *const pShowerPfo) const
98 {
99  CartesianVector nuVertex3D(0.f, 0.f, 0.f);
100 
101  if (this->GetNeutrinoVertex(nuVertex3D) != STATUS_CODE_SUCCESS)
102  return;
103 
104  // Create the 2D connetion pathways
105  ProtoShowerVector protoShowerVectorU, protoShowerVectorV, protoShowerVectorW;
106 
107  this->BuildViewProtoShowers(pShowerPfo, nuVertex3D, TPC_VIEW_U, protoShowerVectorU);
108  this->BuildViewProtoShowers(pShowerPfo, nuVertex3D, TPC_VIEW_V, protoShowerVectorV);
109  this->BuildViewProtoShowers(pShowerPfo, nuVertex3D, TPC_VIEW_W, protoShowerVectorW);
110 
111  // 2D->3D connection pathway matching
112  ProtoShowerMatchVector protoShowerMatchVector;
113  m_pProtoShowerMatchingTool->Run(protoShowerVectorU, protoShowerVectorV, protoShowerVectorW, protoShowerMatchVector);
114 
115  if (protoShowerMatchVector.empty())
116  return;
117 
118  for (ProtoShowerMatch &protoShowerMatch : protoShowerMatchVector)
119  {
120  // Remove ambiguous hits from hits to add list
121  ConnectionPathwayVector viewPathwaysU, viewPathwaysV, viewPathwaysW;
122 
123  this->BuildViewPathways(pShowerPfo, protoShowerMatch.GetProtoShowerU().GetSpineHitList(), nuVertex3D, TPC_VIEW_U, viewPathwaysU);
124  this->BuildViewPathways(pShowerPfo, protoShowerMatch.GetProtoShowerV().GetSpineHitList(), nuVertex3D, TPC_VIEW_V, viewPathwaysV);
125  this->BuildViewPathways(pShowerPfo, protoShowerMatch.GetProtoShowerW().GetSpineHitList(), nuVertex3D, TPC_VIEW_W, viewPathwaysW);
126 
127  this->RefineHitsToAdd(nuVertex3D, TPC_VIEW_U, viewPathwaysU, protoShowerMatch.GetProtoShowerToModify(TPC_VIEW_U));
128  this->RefineHitsToAdd(nuVertex3D, TPC_VIEW_V, viewPathwaysV, protoShowerMatch.GetProtoShowerToModify(TPC_VIEW_V));
129  this->RefineHitsToAdd(nuVertex3D, TPC_VIEW_W, viewPathwaysW, protoShowerMatch.GetProtoShowerToModify(TPC_VIEW_W));
130 
131  // Determine the 3D shower vertex
132  CartesianPointVector showerStarts3D;
133  if (!LArConnectionPathwayHelper::FindShowerStarts3D(this, pShowerPfo, protoShowerMatch, nuVertex3D, m_maxSeparationFromHit,
135  {
136  continue;
137  }
138 
139  // Fill BDT information
140  StringVector featureOrder;
142  m_algorithmToolNames, m_featureToolMap, featureOrder, this, pShowerPfo, nuVertex3D, protoShowerMatch, showerStarts3D));
143 
144  this->SetMetadata(pShowerPfo, featureMap);
145 
146  if (m_trainingMode)
147  {
148  // To truth match electrons
149  HitOwnershipMap electronHitMap;
150  this->FillElectronHitMap(electronHitMap);
151 
152  if (this->IsElectron(pShowerPfo, electronHitMap))
153  {
154  LArMvaHelper::ProduceTrainingExample(m_trainingFileName, true, featureOrder, featureMap);
155  break;
156  }
157 
158  LArMvaHelper::ProduceTrainingExample(m_trainingFileName, false, featureOrder, featureMap);
159 
160  break;
161  }
162  }
163 }
164 
165 //------------------------------------------------------------------------------------------------------------------------------------------
166 
167 StatusCode ElectronInitialRegionRefinementAlgorithm::GetNeutrinoVertex(CartesianVector &nuVertex3D) const
168 {
169  const VertexList *pNuVertexList(nullptr);
170  const StatusCode statusCode(PandoraContentApi::GetList(*this, m_neutrinoVertexListName, pNuVertexList));
171 
172  if (statusCode != STATUS_CODE_SUCCESS)
173  return statusCode;
174 
175  if (!pNuVertexList || (pNuVertexList->size() != 1))
176  {
177  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
178  std::cout << "ElectronInitialRegionRefinementAlgorithm: unable to find vertex list " << m_neutrinoVertexListName
179  << " if it does exist, it may have more than one nu vertex" << std::endl;
180 
181  return STATUS_CODE_NOT_INITIALIZED;
182  }
183 
184  nuVertex3D = pNuVertexList->front()->GetPosition();
185 
186  return STATUS_CODE_SUCCESS;
187 }
188 
189 //------------------------------------------------------------------------------------------------------------------------------------------
190 
191 void ElectronInitialRegionRefinementAlgorithm::BuildViewProtoShowers(const ParticleFlowObject *const pShowerPfo,
192  const CartesianVector &nuVertex3D, HitType hitType, ProtoShowerVector &protoShowerVector) const
193 {
194  const CaloHitList *pViewHitList(nullptr);
195 
196  if (this->GetHitListOfType(hitType, pViewHitList) != STATUS_CODE_SUCCESS)
197  return;
198 
199  CartesianVector showerVertexPosition(0.f, 0.f, 0.f);
200  try
201  {
202  showerVertexPosition = this->GetShowerVertex(pShowerPfo, hitType, nuVertex3D);
203  }
204  catch (...)
205  {
206  return;
207  }
208 
209  // Determine directions of pathways out of neutrino vertex
210  CartesianPointVector peakDirectionVector;
211  if (m_pShowerPeakDirectionFinderTool->Run(pShowerPfo, nuVertex3D, pViewHitList, hitType, peakDirectionVector) != STATUS_CODE_SUCCESS)
212  return;
213 
214  // Investigate each direction
215  CaloHitList unavailableHitList;
216  for (CartesianVector &peakDirection : peakDirectionVector)
217  {
218  // Collect the hits associated with the pathway (the shower spine)
219  CaloHitList showerSpineHitList;
220  if (m_pShowerSpineFinderTool->Run(nuVertex3D, pViewHitList, hitType, peakDirection, unavailableHitList, showerSpineHitList) != STATUS_CODE_SUCCESS)
221  continue;
222 
223  this->RefineShowerVertex(pShowerPfo, hitType, nuVertex3D, peakDirection, showerVertexPosition);
224 
225  // Quality check: If the spine passes the shower vertex, does it live inside the shower?
226  if (!this->IsSpineCoincident(pShowerPfo, nuVertex3D, hitType, showerVertexPosition, showerSpineHitList))
227  continue;
228 
229  // Find the 2D shower start position
230  CartesianVector showerStartPosition(0.f, 0.f, 0.f);
231  CartesianVector showerStartDirection(0.f, 0.f, 0.f);
232 
233  if (m_pShowerStartFinderTool->Run(pShowerPfo, peakDirection, hitType, showerSpineHitList, showerStartPosition, showerStartDirection) != STATUS_CODE_SUCCESS)
234  continue;
235 
236  // Create the ProtoShower object
237  const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
238 
239  ProtoShower protoShower(ShowerCore(showerStartPosition, showerStartDirection), ConnectionPathway(nuVertex2D, peakDirection),
240  showerSpineHitList, CaloHitList(), CartesianPointVector(), CaloHitList());
241 
242  // Now determine the hits to be added to the shower from the found spine
243  CaloHitList viewShowerHitList;
244  LArPfoHelper::GetCaloHits(pShowerPfo, hitType, viewShowerHitList);
245 
246  const float showerVertexL(std::max(
247  peakDirection.GetDotProduct(showerStartPosition - nuVertex2D), peakDirection.GetDotProduct(showerVertexPosition - nuVertex2D)));
248 
249  for (const CaloHit *const pCaloHit : showerSpineHitList)
250  {
251  if (std::find(viewShowerHitList.begin(), viewShowerHitList.end(), pCaloHit) != viewShowerHitList.end())
252  continue;
253 
254  const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
255  const float showerL(peakDirection.GetDotProduct(hitPosition - nuVertex2D));
256 
257  if ((showerL > 0.f) && (showerL < showerVertexL))
258  protoShower.AddHitToAdd(pCaloHit);
259  }
260 
261  protoShowerVector.push_back(protoShower);
262  unavailableHitList.insert(unavailableHitList.begin(), showerSpineHitList.begin(), showerSpineHitList.end());
263  }
264 }
265 
266 //------------------------------------------------------------------------------------------------------------------------------------------
267 
268 StatusCode ElectronInitialRegionRefinementAlgorithm::GetHitListOfType(const HitType hitType, const CaloHitList *&pCaloHitList) const
269 {
270  const std::string typeHitListName(hitType == TPC_VIEW_U ? m_caloHitListNameU
271  : hitType == TPC_VIEW_V ? m_caloHitListNameV
273 
274  PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, typeHitListName, pCaloHitList));
275 
276  if (!pCaloHitList || pCaloHitList->empty())
277  {
278  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
279  std::cout << "ShowerStartRefinementBaseTool: unable to find calo hit list " << typeHitListName << std::endl;
280 
281  return STATUS_CODE_NOT_INITIALIZED;
282  }
283 
284  return STATUS_CODE_SUCCESS;
285 }
286 
287 //------------------------------------------------------------------------------------------------------------------------------------------
288 
290  const ParticleFlowObject *const pShowerPfo, const HitType hitType, const CartesianVector &nuVertex3D) const
291 {
292  ClusterList viewCusterList;
293  LArPfoHelper::GetClusters(pShowerPfo, hitType, viewCusterList);
294 
295  if (viewCusterList.empty())
296  throw StatusCodeException(STATUS_CODE_FAILURE);
297 
298  const TwoDSlidingShowerFitResult twoDShowerSlidingFit(
299  viewCusterList.front(), m_showerSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), hitType));
300  const CartesianVector &minLayerPosition(twoDShowerSlidingFit.GetShowerFitResult().GetGlobalMinLayerPosition());
301  const CartesianVector &maxLayerPosition(twoDShowerSlidingFit.GetShowerFitResult().GetGlobalMaxLayerPosition());
302  const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
303 
304  if ((nuVertex2D.GetZ() > minLayerPosition.GetZ()) && (nuVertex2D.GetZ() < maxLayerPosition.GetZ()))
305  return nuVertex2D;
306 
307  const float minSeparation((nuVertex2D - minLayerPosition).GetMagnitudeSquared());
308  const float maxSeparation((nuVertex2D - maxLayerPosition).GetMagnitudeSquared());
309  CartesianVector showerVertexPosition(minSeparation < maxSeparation ? minLayerPosition : maxLayerPosition);
310 
311  return (minSeparation < maxSeparation ? minLayerPosition : maxLayerPosition);
312 }
313 
314 //------------------------------------------------------------------------------------------------------------------------------------------
315 
316 void ElectronInitialRegionRefinementAlgorithm::RefineShowerVertex(const ParticleFlowObject *const pShowerPfo, const HitType hitType,
317  const CartesianVector &nuVertex3D, const CartesianVector &peakDirection, CartesianVector &showerVertexPosition) const
318 {
319  const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
320 
321  if (!this->IsShowerConnected(showerVertexPosition, nuVertex2D, peakDirection))
322  {
323  CaloHitList viewShowerHitList;
324  LArPfoHelper::GetCaloHits(pShowerPfo, hitType, viewShowerHitList);
325 
326  float minL(std::numeric_limits<float>::max());
327 
328  for (const CaloHit *const pCaloHit : viewShowerHitList)
329  {
330  const CartesianVector displacement(pCaloHit->GetPositionVector() - nuVertex2D);
331  const float longitudinalSeparation(peakDirection.GetDotProduct(displacement));
332 
333  if ((longitudinalSeparation < (-1.f)) || (longitudinalSeparation > minL))
334  continue;
335 
336  const float transverseSeparation((peakDirection.GetCrossProduct(displacement)).GetMagnitude());
337 
338  if (transverseSeparation < m_maxCoincidenceTransverseSeparation)
339  {
340  showerVertexPosition = pCaloHit->GetPositionVector();
341  minL = longitudinalSeparation;
342  }
343  }
344  }
345 }
346 
347 //------------------------------------------------------------------------------------------------------------------------------------------
348 
350  const CartesianVector &showerVertexPosition, const CartesianVector &nuVertex2D, const CartesianVector &peakDirection) const
351 {
352  CartesianVector displacement(showerVertexPosition - nuVertex2D);
353 
354  const float longitudinalSeparation(peakDirection.GetDotProduct(displacement));
355 
356  if (longitudinalSeparation < (-1.f))
357  return false;
358 
359  const float transverseSeparation((peakDirection.GetCrossProduct(displacement)).GetMagnitude());
360 
361  if (transverseSeparation > m_maxCoincidenceTransverseSeparation)
362  return false;
363 
364  return true;
365 }
366 
367 //------------------------------------------------------------------------------------------------------------------------------------------
368 
369 bool ElectronInitialRegionRefinementAlgorithm::IsSpineCoincident(const ParticleFlowObject *const pShowerPfo,
370  const CartesianVector &nuVertex3D, const HitType hitType, const CartesianVector &showerVertex, const CaloHitList &showerSpineHitList) const
371 {
372  const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
373 
374  CaloHitList viewShowerHitList;
375  LArPfoHelper::GetCaloHits(pShowerPfo, hitType, viewShowerHitList);
376 
377  CaloHitList postShowerVertexSpineHits;
378  const float showerDistanceFromNuSquared((showerVertex - nuVertex2D).GetMagnitudeSquared());
379 
380  for (const CaloHit *const pSpineHit : showerSpineHitList)
381  {
382  const CartesianVector &hitPosition(pSpineHit->GetPositionVector());
383  const float separationSquared((hitPosition - nuVertex2D).GetMagnitudeSquared());
384 
385  if (separationSquared > showerDistanceFromNuSquared)
386  postShowerVertexSpineHits.push_back(pSpineHit);
387  }
388 
389  if (postShowerVertexSpineHits.size() == 0)
390  return true;
391 
392  // Check whether shower spine is pure
393  const CaloHitList sharedHitList(LArMCParticleHelper::GetSharedHits(postShowerVertexSpineHits, viewShowerHitList));
394  const float spinePurity(static_cast<float>(sharedHitList.size()) / static_cast<float>(postShowerVertexSpineHits.size()));
395 
396  if (spinePurity < m_minSpinePurity)
397  return false;
398 
399  return true;
400 }
401 
402 //------------------------------------------------------------------------------------------------------------------------------------------
403 
404 void ElectronInitialRegionRefinementAlgorithm::BuildViewPathways(const ParticleFlowObject *const pShowerPfo,
405  const CaloHitList &protectedHits, const CartesianVector &nuVertex3D, HitType hitType, ConnectionPathwayVector &viewPathways) const
406 {
407  const CaloHitList *pViewHitList(nullptr);
408 
409  if (this->GetHitListOfType(hitType, pViewHitList) != STATUS_CODE_SUCCESS)
410  return;
411 
412  // Get the peak direction vector
413  CartesianPointVector eventPeakDirectionVector;
414  m_pEventPeakDirectionFinderTool->Run(pShowerPfo, nuVertex3D, pViewHitList, hitType, eventPeakDirectionVector);
415 
416  CaloHitList unavailableHitList(protectedHits);
417  LArPfoHelper::GetCaloHits(pShowerPfo, hitType, unavailableHitList);
418 
419  for (CartesianVector &eventPeakDirection : eventPeakDirectionVector)
420  {
421  CaloHitList pathwayHitList;
422  if (m_pEventPathwayFinderTool->Run(nuVertex3D, pViewHitList, hitType, eventPeakDirection, unavailableHitList, pathwayHitList) != STATUS_CODE_SUCCESS)
423  continue;
424 
425  const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
426  const ConnectionPathway connectionPathway(nuVertex2D, eventPeakDirection);
427 
428  viewPathways.push_back(connectionPathway);
429  unavailableHitList.insert(unavailableHitList.begin(), pathwayHitList.begin(), pathwayHitList.end());
430  }
431 }
432 
433 //------------------------------------------------------------------------------------------------------------------------------------------
434 
436  const CartesianVector &nuVertex3D, const HitType hitType, const ConnectionPathwayVector &viewPathways, ProtoShower &protoShower) const
437 {
438  const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
439  const CartesianVector &peakDirection(protoShower.GetConnectionPathway().GetStartDirection());
440 
441  CaloHitList refinedHitList;
442 
443  for (const CaloHit *const pHitToAdd : protoShower.GetHitsToAddList())
444  {
445  bool found(false);
446 
447  const CartesianVector &hitPosition(pHitToAdd->GetPositionVector());
448  const CartesianVector displacement(hitPosition - nuVertex2D);
449  const float thisT((peakDirection.GetCrossProduct(displacement)).GetMagnitudeSquared());
450 
451  for (const ConnectionPathway &connectionPathway : viewPathways)
452  {
453  const CartesianVector &eventPeakDirection(connectionPathway.GetStartDirection());
454 
455  if (peakDirection.GetOpeningAngle(eventPeakDirection) > (M_PI / 2))
456  continue;
457 
458  const float otherT((eventPeakDirection.GetCrossProduct(displacement)).GetMagnitudeSquared());
459 
460  if ((otherT < thisT) || (otherT < m_unambiguousThreshold))
461  {
462  found = true;
463 
464  if (std::find(protoShower.GetAmbiguousDirectionVector().begin(), protoShower.GetAmbiguousDirectionVector().end(),
465  eventPeakDirection) == protoShower.GetAmbiguousDirectionVector().end())
466  {
467  protoShower.AddAmbiguousDirection(connectionPathway.GetStartDirection());
468  }
469  }
470  }
471 
472  found ? protoShower.AddAmbiguousHit(pHitToAdd) : refinedHitList.push_back(pHitToAdd);
473  }
474 
475  CaloHitList continuousHitList;
476  this->FindContinuousPath(refinedHitList, nuVertex2D, continuousHitList);
477 
478  protoShower.SetHitsToAddList(continuousHitList);
479 }
480 
481 //------------------------------------------------------------------------------------------------------------------------------------------
482 
484  const CaloHitList &refinedHitList, const CartesianVector &nuVertex2D, CaloHitList &continuousHitList) const
485 {
486  continuousHitList.clear();
487 
488  CaloHitVector refinedHitVector(refinedHitList.begin(), refinedHitList.end());
489  std::sort(refinedHitVector.begin(), refinedHitVector.end(), LArConnectionPathwayHelper::SortByDistanceToPoint(nuVertex2D));
490 
491  unsigned int startIndex(refinedHitVector.size());
492 
493  for (unsigned int i = 0; i < refinedHitVector.size(); ++i)
494  {
495  CaloHitList connectedHitList;
496  connectedHitList.push_back(refinedHitVector[i]);
497 
498  bool found(true);
499 
500  while (found)
501  {
502  found = false;
503 
504  for (unsigned int j = (i + 1); j < refinedHitVector.size(); ++j)
505  {
506  const CaloHit *const pCaloHit(refinedHitVector[j]);
507 
508  if (std::find(connectedHitList.begin(), connectedHitList.end(), pCaloHit) != connectedHitList.end())
509  continue;
510 
511  if (LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), connectedHitList) < m_maxConnectionDistance)
512  {
513  found = true;
514  connectedHitList.push_back(pCaloHit);
515  break;
516  }
517  }
518  }
519 
520  if ((connectedHitList.size() >= m_minNConnectedHits) || (connectedHitList.size() == refinedHitVector.size()))
521  {
522  startIndex = i;
523  break;
524  }
525  }
526 
527  for (unsigned int i = startIndex; i < refinedHitVector.size(); ++i)
528  continuousHitList.push_back(refinedHitVector[i]);
529 }
530 
531 //------------------------------------------------------------------------------------------------------------------------------------------
532 
533 void ElectronInitialRegionRefinementAlgorithm::SetMetadata(const ParticleFlowObject *const pShowerPfo, const LArMvaHelper::MvaFeatureMap &featureMap) const
534 {
535  object_creation::ParticleFlowObject::Metadata metadata;
536 
537  metadata.m_propertiesToAdd["FoundConnectionPathway"] = true;
538 
539  if (featureMap.find("LArInitialRegionFeatureTool_initialGapSize") != featureMap.end())
540  metadata.m_propertiesToAdd["MaxInitialGapSize"] = featureMap.at("LArInitialRegionFeatureTool_initialGapSize").Get();
541 
542  if (featureMap.find("LArInitialRegionFeatureTool_largestGapSize") != featureMap.end())
543  metadata.m_propertiesToAdd["MinLargestProjectedGapSize"] = featureMap.at("LArInitialRegionFeatureTool_largestGapSize").Get();
544 
545  if (featureMap.find("LArConnectionRegionFeatureTool_pathwayLength") != featureMap.end())
546  metadata.m_propertiesToAdd["PathwayLengthMin"] = featureMap.at("LArConnectionRegionFeatureTool_pathwayLength").Get();
547 
548  if (featureMap.find("LArConnectionRegionFeatureTool_pathwayScatteringAngle2D") != featureMap.end())
549  metadata.m_propertiesToAdd["MaxShowerStartPathwayScatteringAngle2D"] =
550  featureMap.at("LArConnectionRegionFeatureTool_pathwayScatteringAngle2D").Get();
551 
552  if (featureMap.find("LArShowerRegionFeatureTool_nShowerHits") != featureMap.end())
553  metadata.m_propertiesToAdd["MaxNPostShowerStartHits"] = featureMap.at("LArShowerRegionFeatureTool_nShowerHits").Get();
554 
555  if (featureMap.find("LArShowerRegionFeatureTool_foundHitRatio") != featureMap.end())
556  metadata.m_propertiesToAdd["MaxFoundHitRatio"] = featureMap.at("LArShowerRegionFeatureTool_foundHitRatio").Get();
557 
558  if (featureMap.find("LArShowerRegionFeatureTool_scatterAngle") != featureMap.end())
559  metadata.m_propertiesToAdd["MaxPostShowerStartScatterAngle"] = featureMap.at("LArShowerRegionFeatureTool_scatterAngle").Get();
560 
561  if (featureMap.find("LArShowerRegionFeatureTool_openingAngle") != featureMap.end())
562  metadata.m_propertiesToAdd["MaxPostShowerStartOpeningAngle"] = featureMap.at("LArShowerRegionFeatureTool_openingAngle").Get();
563 
564  if (featureMap.find("LArShowerRegionFeatureTool_nuVertexEnergyAsymmetry") != featureMap.end())
565  metadata.m_propertiesToAdd["MaxPostShowerStartNuVertexEnergyAsymmetry"] =
566  featureMap.at("LArShowerRegionFeatureTool_nuVertexEnergyAsymmetry").Get();
567 
568  if (featureMap.find("LArShowerRegionFeatureTool_nuVertexEnergyWeightedMeanRadialDistance") != featureMap.end())
569  metadata.m_propertiesToAdd["MaxPostShowerStartNuVertexEnergyWeightedMeanRadialDistance"] =
570  featureMap.at("LArShowerRegionFeatureTool_nuVertexEnergyWeightedMeanRadialDistance").Get();
571 
572  if (featureMap.find("LArShowerRegionFeatureTool_showerStartEnergyAsymmetry") != featureMap.end())
573  metadata.m_propertiesToAdd["MaxPostShowerStartShowerStartEnergyAsymmetry"] =
574  featureMap.at("LArShowerRegionFeatureTool_showerStartEnergyAsymmetry").Get();
575 
576  if (featureMap.find("LArShowerRegionFeatureTool_showerStartMoliereRadius") != featureMap.end())
577  metadata.m_propertiesToAdd["MinPostShowerStartShowerStartMoliereRadius"] =
578  featureMap.at("LArShowerRegionFeatureTool_showerStartMoliereRadius").Get();
579 
580  if (featureMap.find("LArAmbiguousRegionFeatureTool_nAmbiguousViews") != featureMap.end())
581  metadata.m_propertiesToAdd["NViewsWithAmbiguousHits"] = featureMap.at("LArAmbiguousRegionFeatureTool_nAmbiguousViews").Get();
582 
583  if (featureMap.find("LArAmbiguousRegionFeatureTool_maxUnaccountedEnergy") != featureMap.end())
584  metadata.m_propertiesToAdd["AmbiguousHitMaxUnaccountedEnergy"] = featureMap.at("LArAmbiguousRegionFeatureTool_maxUnaccountedEnergy").Get();
585 
586  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*this, pShowerPfo, metadata));
587 }
588 
589 //------------------------------------------------------------------------------------------------------------------------------------------
590 
592 {
593  electronHitMap.clear();
594 
595  for (HitType hitType : {TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W})
596  {
597  const CaloHitList *pViewHitList(nullptr);
598 
599  if (this->GetHitListOfType(hitType, pViewHitList) != STATUS_CODE_SUCCESS)
600  continue;
601 
602  for (const CaloHit *const pCaloHit : *pViewHitList)
603  {
604  MCParticleVector contributingMCParticleVector;
605  const MCParticleWeightMap &weightMap(pCaloHit->GetMCParticleWeightMap());
606 
607  for (const auto &mapEntry : weightMap)
608  contributingMCParticleVector.push_back(mapEntry.first);
609 
610  std::sort(contributingMCParticleVector.begin(), contributingMCParticleVector.end(), PointerLessThan<MCParticle>());
611 
612  float highestWeight(0.f);
613  const MCParticle *highestElectronContributor(nullptr);
614 
615  for (const MCParticle *const pMCParticle : contributingMCParticleVector)
616  {
617  const bool isLeadingElectron((std::abs(pMCParticle->GetParticleId()) == 11) &&
618  (LArMCParticleHelper::GetPrimaryMCParticle(pMCParticle) == pMCParticle));
619 
620  if (isLeadingElectron)
621  {
622  const float weight(weightMap.at(pMCParticle));
623 
624  if (weight > highestWeight)
625  {
626  highestWeight = weight;
627  highestElectronContributor = pMCParticle;
628  }
629  }
630  }
631 
632  if (highestElectronContributor)
633  electronHitMap[highestElectronContributor].push_back(pCaloHit);
634  }
635  }
636 }
637 
638 //------------------------------------------------------------------------------------------------------------------------------------------
639 
640 bool ElectronInitialRegionRefinementAlgorithm::IsElectron(const ParticleFlowObject *const pPfo, const HitOwnershipMap &electronHitMap) const
641 {
642  MCParticleVector mcElectronVector;
643 
644  for (auto &entry : electronHitMap)
645  mcElectronVector.push_back(entry.first);
646 
647  CaloHitList pfoHitList;
648  LArPfoHelper::GetCaloHits(pPfo, TPC_VIEW_U, pfoHitList);
649  LArPfoHelper::GetCaloHits(pPfo, TPC_VIEW_V, pfoHitList);
650  LArPfoHelper::GetCaloHits(pPfo, TPC_VIEW_W, pfoHitList);
651 
652  for (const MCParticle *const pMCElectron : mcElectronVector)
653  {
654  const CaloHitList &mcElectronHitList(electronHitMap.at(pMCElectron));
655  const CaloHitList sharedHitList(LArMCParticleHelper::GetSharedHits(pfoHitList, mcElectronHitList));
656 
657  const float completeness(static_cast<float>(sharedHitList.size()) / static_cast<float>(mcElectronHitList.size()));
658  const float purity(static_cast<float>(sharedHitList.size()) / static_cast<float>(pfoHitList.size()));
659 
660  if (completeness < m_minElectronCompleteness)
661  continue;
662 
663  if (purity < m_minElectronPurity)
664  continue;
665 
666  return true;
667  }
668 
669  return false;
670 }
671 
672 //------------------------------------------------------------------------------------------------------------------------------------------
673 
674 StatusCode ElectronInitialRegionRefinementAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
675 {
676  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "ShowerPfoListName", m_showerPfoListName));
677  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "NeutrinoVertexListName", m_neutrinoVertexListName));
678  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListNameU", m_caloHitListNameU));
679  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListNameV", m_caloHitListNameV));
680  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListNameW", m_caloHitListNameW));
681 
682  AlgorithmTool *pAlgorithmTool1(nullptr);
683  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "ShowerPeakDirectionFinder", pAlgorithmTool1));
684  m_pShowerPeakDirectionFinderTool = dynamic_cast<PeakDirectionFinderTool *>(pAlgorithmTool1);
685 
687  return STATUS_CODE_INVALID_PARAMETER;
688 
689  AlgorithmTool *pAlgorithmTool2(nullptr);
690  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "EventPeakDirectionFinder", pAlgorithmTool2));
691  m_pEventPeakDirectionFinderTool = dynamic_cast<PeakDirectionFinderTool *>(pAlgorithmTool2);
692 
694  return STATUS_CODE_INVALID_PARAMETER;
695 
696  AlgorithmTool *pAlgorithmTool3(nullptr);
697  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "ShowerSpineFinder", pAlgorithmTool3));
698  m_pShowerSpineFinderTool = dynamic_cast<ShowerSpineFinderTool *>(pAlgorithmTool3);
699 
701  return STATUS_CODE_INVALID_PARAMETER;
702 
703  AlgorithmTool *pAlgorithmTool4(nullptr);
704  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "EventPathwayFinder", pAlgorithmTool4));
705  m_pEventPathwayFinderTool = dynamic_cast<ShowerSpineFinderTool *>(pAlgorithmTool4);
706 
708  return STATUS_CODE_INVALID_PARAMETER;
709 
710  AlgorithmTool *pAlgorithmTool5(nullptr);
711  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "ShowerStartFinder", pAlgorithmTool5));
712  m_pShowerStartFinderTool = dynamic_cast<ShowerStartFinderTool *>(pAlgorithmTool5);
713 
715  return STATUS_CODE_INVALID_PARAMETER;
716 
717  AlgorithmTool *pAlgorithmTool6(nullptr);
718  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmTool(*this, xmlHandle, "ProtoShowerMatching", pAlgorithmTool6));
719  m_pProtoShowerMatchingTool = dynamic_cast<ProtoShowerMatchingTool *>(pAlgorithmTool6);
720 
722  return STATUS_CODE_INVALID_PARAMETER;
723 
724  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinShowerHits3D", m_minShowerHits3D));
725 
726  PANDORA_RETURN_RESULT_IF_AND_IF(
727  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ShowerSlidingFitWindow", m_showerSlidingFitWindow));
728 
729  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
730  XmlHelper::ReadValue(xmlHandle, "MaxCoincidenceTransverseSeparation", m_maxCoincidenceTransverseSeparation));
731 
732  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinSpinePurity", m_minSpinePurity));
733 
734  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingMode", m_trainingMode));
735 
736  PANDORA_RETURN_RESULT_IF_AND_IF(
737  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingFileName", m_trainingFileName));
738 
739  PANDORA_RETURN_RESULT_IF_AND_IF(
740  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UnambiguousThreshold", m_unambiguousThreshold));
741 
742  PANDORA_RETURN_RESULT_IF_AND_IF(
743  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxConnectionDistance", m_maxConnectionDistance));
744 
745  PANDORA_RETURN_RESULT_IF_AND_IF(
746  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinNConnectedHits", m_minNConnectedHits));
747 
748  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
749  XmlHelper::ReadValue(xmlHandle, "MinElectronCompleteness", m_minElectronCompleteness));
750 
751  PANDORA_RETURN_RESULT_IF_AND_IF(
752  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinElectronPurity", m_minElectronPurity));
753 
754  PANDORA_RETURN_RESULT_IF_AND_IF(
755  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxSeparationFromHit", m_maxSeparationFromHit));
756 
757  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
758  XmlHelper::ReadValue(xmlHandle, "MaxProjectionSeparation", m_maxProjectionSeparation));
759 
760  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxXSeparation", m_maxXSeparation));
761 
762  AlgorithmToolVector algorithmToolVector;
763  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "FeatureTools", algorithmToolVector));
764 
765  LArMvaHelper::AlgorithmToolMap algorithmToolMap;
766  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
767  LArMvaHelper::ProcessAlgorithmToolListToMap(*this, xmlHandle, "FeatureTools", m_algorithmToolNames, algorithmToolMap));
768 
769  for (auto const &[pAlgorithmToolName, pAlgorithmTool] : algorithmToolMap)
770  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArMvaHelper::AddFeatureToolToMap(pAlgorithmTool, pAlgorithmToolName, m_featureToolMap));
771 
772  return STATUS_CODE_SUCCESS;
773 }
774 
775 } // namespace lar_content
pandora::StatusCode Run(const pandora::CartesianVector &nuVertex3D, const pandora::CaloHitList *const pViewHitList, const pandora::HitType hitType, const pandora::CartesianVector &peakDirection, pandora::CaloHitList &unavailableHitList, pandora::CaloHitList &showerSpineHitList)
Header file for the lar two dimensional sliding shower fit result class.
float m_unambiguousThreshold
The min. transverse distance of an unambiguous shower hit from another pathway direction.
static bool SortByNHits(const pandora::ParticleFlowObject *const pLhs, const pandora::ParticleFlowObject *const pRhs)
Sort pfos by number of constituent hits.
Header file for the pfo helper class.
float m_maxSeparationFromHit
The max. separation between the projected 3D shower start and the closest 2D shower hit...
Header file for the ProtoShower class.
bool IsElectron(const pandora::ParticleFlowObject *const pShowerPfo, const HitOwnershipMap &electronHitMap) const
To determine whether a pfo is a true leading electron via its completeness and purity.
Header file for the electron initial region refinement algorithm class.
const pandora::CartesianPointVector & GetAmbiguousDirectionVector() const
Get the ambiguous direction vector.
void SetMetadata(const pandora::ParticleFlowObject *const pShowerPfo, const LArMvaHelper::MvaFeatureMap &featureMap) const
Add the shower characterisation information to the pfo metadata.
pandora::StatusCode GetNeutrinoVertex(pandora::CartesianVector &nuVertex3D) const
Obtain the reconstructed neutrino vertex.
Header file for the connection pathway helper class.
std::map< std::string, pandora::AlgorithmTool * > AlgorithmToolMap
Definition: LArMvaHelper.h:79
float m_minSpinePurity
The min. purity of a coincident shower spine downstream of the shower vertex.
ShowerSpineFinderTool * m_pShowerSpineFinderTool
The shower spine finder tool for the shower.
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos.
bool IsShowerConnected(const pandora::CartesianVector &showerVertexPosition, const pandora::CartesianVector &nuVertex2D, const pandora::CartesianVector &peakDirection) const
To determine whether the shower vertex lies on the connection pathway.
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer)
Produce a training example with the given features and result.
Definition: LArMvaHelper.h:285
float m_maxConnectionDistance
The max. distance between connected hits.
pandora::StatusCode Run(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::CartesianVector &nuVertex3D, const pandora::CaloHitList *const pViewHitList, const pandora::HitType hitType, pandora::CartesianPointVector &peakDirectionVector)
PeakDirectionFinderTool * m_pShowerPeakDirectionFinderTool
The shower initial pathway direction finder tool.
Header file for the shower start finder tool class.
constexpr auto abs(T v)
Returns the absolute value of the argument.
const ConnectionPathway & GetConnectionPathway() const
Get the connection pathway.
pandora::StatusCode Run(const ProtoShowerVector &protoShowerVectorU, const ProtoShowerVector &protoShowerVectorV, const ProtoShowerVector &protoShowerVectorW, ProtoShowerMatchVector &protoShowerMatchVector)
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
static const pandora::MCParticle * GetPrimaryMCParticle(const pandora::MCParticle *const pMCParticle)
Get the primary parent mc particle.
void SetHitsToAddList(const pandora::CaloHitList &hitsToAddList)
Set the hits to add list.
float m_maxXSeparation
The max. drift-coordinate separation between a 3D shower start and a matched 2D shower hit...
static bool FindShowerStarts3D(const pandora::Algorithm *const pAlgorithm, const pandora::ParticleFlowObject *const pShowerPfo, const ProtoShowerMatch &protoShowerMatch, const pandora::CartesianVector &nuVertexPosition, const float maxSeparationFromHit, const float maxProjectionSeparation, const float maxXSeparation, pandora::CartesianPointVector &showerStarts3D)
Create 3D shower start position(s) from three input 2D positions.
void FillShowerPfoVector(pandora::PfoVector &showerPfoVector) const
Obtain a sorted vector of the reconstructed shower pfos.
void BuildViewProtoShowers(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::CartesianVector &nuVertex3D, pandora::HitType hitType, ProtoShowerVector &protoShowerVector) const
Build the 2D ProtoShower objects for a given view.
MvaTypes::MvaFeatureMap MvaFeatureMap
Definition: LArMvaHelper.h:78
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::string m_trainingFileName
The name of the output training file name.
unsigned int m_minNConnectedHits
The number of connected hits needed for a conntected pathway.
float m_maxCoincidenceTransverseSeparation
The max. transverse distance from the pathway direction of a coincident shower vertex.
float m_minElectronCompleteness
The min. completeness of an electron-like pfo.
ShowerStartFinderTool * m_pShowerStartFinderTool
The shower start finder tool.
bool m_trainingMode
Whether to run the algorithm to train the BDT.
ProtoShowerMatch class.
TFile f
Definition: plotHisto.C:6
void RefineShower(const pandora::ParticleFlowObject *const pShowerPfo) const
Find and evaluate shower connection pathway, removing if necessary.
Header file for the geometry helper class.
void AddAmbiguousHit(const pandora::CaloHit *const ambiguousHit)
Add an ambiguous hit to the ambiguous hit list.
ConnectionPathway class.
void FillElectronHitMap(HitOwnershipMap &electronHitMap) const
Determine the one-to-one mapping of leading MCParticle electrons and the hits which contain their ene...
PeakDirectionFinderTool * m_pEventPeakDirectionFinderTool
The other (not incl. shower) initial pathway direction finder tool.
Header file for the lar monte carlo particle helper helper class.
std::vector< ConnectionPathway > ConnectionPathwayVector
pandora::CartesianVector GetShowerVertex(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const pandora::CartesianVector &nuVertex3D) const
Fit the shower to obtain a 2D shower vertex.
Header file for the cluster helper class.
bool IsSpineCoincident(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::CartesianVector &nuVertex3D, const pandora::HitType hitType, const pandora::CartesianVector &showerVertex, const pandora::CaloHitList &showerSpineHitList) const
To determine if the hits downstream of the shower vertex lie within the shower.
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
ShowerCore class.
void FindContinuousPath(const pandora::CaloHitList &refinedHitList, const pandora::CartesianVector &nuVertex2D, pandora::CaloHitList &continuousHitList) const
Find the continuous path of hits that lies closest to a given point.
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
unsigned int m_minShowerHits3D
The min. number of hits of a significant shower.
void BuildViewPathways(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::CaloHitList &protectedHits, const pandora::CartesianVector &nuVertex3D, pandora::HitType hitType, ConnectionPathwayVector &viewPathways) const
Build the connection pathways of all other particles in the event.
static pandora::StatusCode ProcessAlgorithmToolListToMap(const pandora::Algorithm &algorithm, const pandora::TiXmlHandle &xmlHandle, const std::string &listName, pandora::StringVector &algorithToolNameVector, AlgorithmToolMap &algorithmToolMap)
Process a list of algorithms tools in an xml file, using a map. Idea is for this to go to XmlHelper i...
Definition: LArMvaHelper.cc:16
ProtoShowerMatchingTool * m_pProtoShowerMatchingTool
The 2D -> 3D ProtoShower matching tool.
ProtoShower class.
void RefineHitsToAdd(const pandora::CartesianVector &nuVertex3D, const pandora::HitType hitType, const ConnectionPathwayVector &viewPathways, ProtoShower &protoShower) const
Determine the continuous and unambiguous hits to add to an electron-like shower pfo.
double weight
Definition: plottest35.C:25
Header file for the ProtoShower matching tool class.
float m_maxProjectionSeparation
The max. separation between the projected 3D shower start and the shower start of that view...
ConnectionPathwayFeatureTool::FeatureToolMap m_featureToolMap
The feature tool map.
Header file for the peak direction finder tool class.
HitType
Definition: HitType.h:12
std::vector< ProtoShowerMatch > ProtoShowerMatchVector
std::vector< ProtoShower > ProtoShowerVector
static MvaFeatureVector CalculateFeatures(const MvaFeatureToolVector< Ts... > &featureToolVector, TARGS &&...args)
Calculate the features in a given feature tool vector.
Definition: LArMvaHelper.h:399
void AddHitToAdd(const pandora::CaloHit *const hitToAdd)
Add a hit to the hits to add list.
pandora::StatusCode GetHitListOfType(const pandora::HitType hitType, const pandora::CaloHitList *&pCaloHitList) const
Obtain the event hit list of a given view.
pandora::StatusCode Run(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::CartesianVector &peakDirection, const pandora::HitType hitType, const pandora::CaloHitList &showerSpineHitList, pandora::CartesianVector &showerStartPosition, pandora::CartesianVector &showerStartDirection)
void AddAmbiguousDirection(const pandora::CartesianVector &ambiguousDirection)
Add an ambiguous direction to the ambiguous direction vector.
const pandora::CaloHitList & GetHitsToAddList() const
Get the hits to add list.
ShowerSpineFinderTool * m_pEventPathwayFinderTool
The shower spine finder tool for all other event particles.
static void GetCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of calo hits of a particular hit type from a list of pfos.
static pandora::CaloHitList GetSharedHits(const pandora::CaloHitList &hitListA, const pandora::CaloHitList &hitListB)
Get the hits in the intersection of two hit lists.
Header file for the peak direction finder tool class.
std::map< const pandora::MCParticle *, pandora::CaloHitList > HitOwnershipMap
std::list< Vertex > VertexList
Definition: DCEL.h:169
unsigned int m_showerSlidingFitWindow
The sliding fit window for shower fits.
static pandora::StatusCode AddFeatureToolToMap(pandora::AlgorithmTool *const pFeatureTool, std::string pFeatureToolName, MvaFeatureToolMap< Ts... > &featureToolMap)
Add a feature tool to a map of feature tools.
Definition: LArMvaHelper.h:465
const pandora::CartesianVector & GetStartDirection() const
Get the start direction of the connection pathway.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
void RefineShowerVertex(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::HitType hitType, const pandora::CartesianVector &nuVertex3D, const pandora::CartesianVector &peakDirection, pandora::CartesianVector &showerVertexPosition) const
Move the shower vertex closer to the connection pathway.