TrainedVertexSelectionAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArVertex/TrainedVertexSelectionAlgorithm.cc
3  *
4  * @brief Implementation of the trained vertex selection algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
17 
24 
26 
28 
29 #include <random>
30 
31 using namespace pandora;
32 
33 namespace lar_content
34 {
35 
36 TrainedVertexSelectionAlgorithm::TrainedVertexSelectionAlgorithm() :
38  m_trainingSetMode(false),
39  m_allowClassifyDuringTraining(false),
40  m_mcVertexXCorrection(0.f),
41  m_minClusterCaloHits(12),
42  m_slidingFitWindow(100),
43  m_minShowerSpineLength(15.f),
44  m_beamDeweightingConstant(0.4),
45  m_localAsymmetryConstant(3.f),
46  m_globalAsymmetryConstant(1.f),
47  m_showerAsymmetryConstant(1.f),
48  m_energyKickConstant(0.06),
49  m_showerClusteringDistance(3.f),
50  m_minShowerClusterHits(1),
51  m_useShowerClusteringApproximation(false),
52  m_regionRadius(10.f),
53  m_rPhiFineTuningRadius(2.f),
54  m_maxTrueVertexRadius(1.f),
55  m_useRPhiFeatureForRegion(false),
56  m_dropFailedRPhiFastScoreCandidates(true),
57  m_testBeamMode(false),
58  m_legacyEventShapes(true),
59  m_legacyVariables(true)
60 {
61 }
62 
63 //------------------------------------------------------------------------------------------------------------------------------------------
64 
65 void TrainedVertexSelectionAlgorithm::CalculateShowerClusterList(const ClusterList &inputClusterList, ShowerClusterList &showerClusterList) const
66 {
67  ClusterEndPointsMap clusterEndPointsMap;
68  ClusterList showerLikeClusters;
69  this->GetShowerLikeClusterEndPoints(inputClusterList, showerLikeClusters, clusterEndPointsMap);
70 
71  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
72  ClusterList availableShowerLikeClusters(showerLikeClusters.begin(), showerLikeClusters.end());
73 
74  HitKDTree2D kdTree;
75  HitToClusterMap hitToClusterMap;
76 
78  this->PopulateKdTree(availableShowerLikeClusters, kdTree, hitToClusterMap);
79 
80  while (!availableShowerLikeClusters.empty())
81  {
82  ClusterList showerCluster;
83  showerCluster.push_back(availableShowerLikeClusters.back());
84  availableShowerLikeClusters.pop_back();
85 
86  bool addedCluster(true);
87  while (addedCluster && !availableShowerLikeClusters.empty())
88  {
89  addedCluster = false;
90  for (const Cluster *const pCluster : showerCluster)
91  {
93  {
94  addedCluster = this->AddClusterToShower(kdTree, hitToClusterMap, availableShowerLikeClusters, pCluster, showerCluster);
95  }
96  else
97  {
98  addedCluster = this->AddClusterToShower(clusterEndPointsMap, availableShowerLikeClusters, pCluster, showerCluster);
99  }
100 
101  if (addedCluster)
102  break;
103  }
104  }
105 
106  unsigned int totHits(0);
107  for (const Cluster *const pCluster : showerCluster)
108  totHits += pCluster->GetNCaloHits();
109 
110  if (totHits < m_minClusterCaloHits)
111  continue;
112 
113  showerClusterList.emplace_back(showerCluster, slidingFitPitch, m_slidingFitWindow);
114  }
115 }
116 
117 //------------------------------------------------------------------------------------------------------------------------------------------
118 
120  const ClusterList &clusterList, ClusterList &showerLikeClusters, ClusterEndPointsMap &clusterEndPointsMap) const
121 {
122  for (const Cluster *const pCluster : clusterList)
123  {
124  if (pCluster->GetNCaloHits() < m_minShowerClusterHits)
125  continue;
126 
127  if (this->IsClusterShowerLike(pCluster))
128  showerLikeClusters.push_back(pCluster);
129 
130  CaloHitList clusterCaloHitList;
131  pCluster->GetOrderedCaloHitList().FillCaloHitList(clusterCaloHitList);
132 
133  CaloHitVector clusterCaloHitVector(clusterCaloHitList.begin(), clusterCaloHitList.end());
134  std::sort(clusterCaloHitVector.begin(), clusterCaloHitVector.end(), LArClusterHelper::SortHitsByPosition);
135 
136  if (clusterCaloHitVector.empty())
137  continue;
138 
139  ClusterEndPoints clusterEndPoints(clusterCaloHitVector.front()->GetPositionVector(), clusterCaloHitVector.back()->GetPositionVector());
140  clusterEndPointsMap.emplace(pCluster, clusterEndPoints);
141  }
142 }
143 
144 //------------------------------------------------------------------------------------------------------------------------------------------
145 
146 void TrainedVertexSelectionAlgorithm::PopulateKdTree(const ClusterList &clusterList, HitKDTree2D &kdTree, HitToClusterMap &hitToClusterMap) const
147 {
148  CaloHitList allCaloHits;
149 
150  for (const Cluster *const pCluster : clusterList)
151  {
152  CaloHitList daughterHits;
153  pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
154  allCaloHits.insert(allCaloHits.end(), daughterHits.begin(), daughterHits.end());
155 
156  for (const CaloHit *const pCaloHit : daughterHits)
157  (void)hitToClusterMap.insert(HitToClusterMap::value_type(pCaloHit, pCluster));
158  }
159 
160  HitKDNode2DList hitKDNode2DList;
161  KDTreeBox hitsBoundingRegion2D(fill_and_bound_2d_kd_tree(allCaloHits, hitKDNode2DList));
162  kdTree.build(hitKDNode2DList, hitsBoundingRegion2D);
163 }
164 
165 //------------------------------------------------------------------------------------------------------------------------------------------
166 
168  ClusterList &availableShowerLikeClusters, const Cluster *const pCluster, ClusterList &showerCluster) const
169 {
170  const auto existingEndPointsIter(clusterEndPointsMap.find(pCluster));
171  if (existingEndPointsIter == clusterEndPointsMap.end())
172  return false;
173 
174  const ClusterEndPoints &existingClusterEndPoints(existingEndPointsIter->second);
175 
176  for (auto iter = availableShowerLikeClusters.begin(); iter != availableShowerLikeClusters.end(); ++iter)
177  {
178  const Cluster *const pAvailableShowerLikeCluster(*iter);
179  const auto &newEndPointsIter(clusterEndPointsMap.find(pAvailableShowerLikeCluster));
180 
181  if (newEndPointsIter == clusterEndPointsMap.end())
182  continue;
183 
184  const ClusterEndPoints &newClusterEndPoints(newEndPointsIter->second);
185  const float startStartDistance((newClusterEndPoints.first - existingClusterEndPoints.first).GetMagnitude());
186  const float startEndDistance((newClusterEndPoints.first - existingClusterEndPoints.second).GetMagnitude());
187  const float endStartDistance((newClusterEndPoints.second - existingClusterEndPoints.first).GetMagnitude());
188  const float endEndDistance((newClusterEndPoints.second - existingClusterEndPoints.second).GetMagnitude());
189 
190  const float smallestDistance(std::min(std::min(startStartDistance, startEndDistance), std::min(endStartDistance, endEndDistance)));
191 
192  if (smallestDistance < m_showerClusteringDistance)
193  {
194  showerCluster.push_back(pAvailableShowerLikeCluster);
195  availableShowerLikeClusters.erase(iter); // Now must return, after invalidating current iterator
196  return true;
197  }
198  }
199 
200  return false;
201 }
202 
203 //------------------------------------------------------------------------------------------------------------------------------------------
204 
206  ClusterList &availableShowerLikeClusters, const Cluster *const pCluster, ClusterList &showerCluster) const
207 {
208  ClusterSet nearbyClusters;
209  CaloHitList daughterHits;
210  pCluster->GetOrderedCaloHitList().FillCaloHitList(daughterHits);
211 
212  for (const CaloHit *const pCaloHit : daughterHits)
213  {
215 
217  kdTree.search(searchRegionHits, found);
218 
219  for (const auto &hit : found)
220  (void)nearbyClusters.insert(hitToClusterMap.at(hit.data));
221  }
222 
223  for (auto iter = availableShowerLikeClusters.begin(); iter != availableShowerLikeClusters.end(); ++iter)
224  {
225  const Cluster *const pAvailableShowerLikeCluster(*iter);
226 
227  if ((pAvailableShowerLikeCluster != pCluster) && nearbyClusters.count(pAvailableShowerLikeCluster))
228  {
229  showerCluster.push_back(pAvailableShowerLikeCluster);
230  availableShowerLikeClusters.erase(iter); // Now must return, after invalidating current iterator
231  return true;
232  }
233  }
234 
235  return false;
236 }
237 
238 //------------------------------------------------------------------------------------------------------------------------------------------
239 
241  const ClusterList &clusterListU, const ClusterList &clusterListV, const ClusterList &clusterListW, const VertexVector &vertexVector) const
242 {
243  float eventEnergy(0.f);
244  unsigned int nShoweryHits(0), nHits(0);
245 
246  this->IncrementShoweryParameters(clusterListU, nShoweryHits, nHits, eventEnergy);
247  this->IncrementShoweryParameters(clusterListV, nShoweryHits, nHits, eventEnergy);
248  this->IncrementShoweryParameters(clusterListW, nShoweryHits, nHits, eventEnergy);
249 
250  const unsigned int nClusters(clusterListU.size() + clusterListV.size() + clusterListW.size());
251  const float eventShoweryness((nHits > 0) ? static_cast<float>(nShoweryHits) / static_cast<float>(nHits) : 0.f);
252 
253  ClusterList allClusters(clusterListU);
254  allClusters.insert(allClusters.end(), clusterListV.begin(), clusterListV.end());
255  allClusters.insert(allClusters.end(), clusterListW.begin(), clusterListW.end());
256 
257  const ClusterListMap clusterListMap{{TPC_VIEW_U, clusterListU}, {TPC_VIEW_V, clusterListV}, {TPC_VIEW_W, clusterListW}};
258 
259  float eventArea(0.f), longitudinality(0.f);
261  this->GetLegacyEventShapeFeatures(allClusters, eventArea, longitudinality);
262  else
263  this->GetEventShapeFeatures(clusterListMap, eventArea, longitudinality);
264 
265  return EventFeatureInfo(eventShoweryness, eventEnergy, eventArea, longitudinality, nHits, nClusters, vertexVector.size());
266 }
267 
268 //------------------------------------------------------------------------------------------------------------------------------------------
269 
271  const ClusterList &clusterList, unsigned int &nShoweryHits, unsigned int &nHits, float &eventEnergy) const
272 {
273  for (const Cluster *const pCluster : clusterList)
274  {
275  if (this->IsClusterShowerLike(pCluster))
276  nShoweryHits += pCluster->GetNCaloHits();
277 
278  eventEnergy += pCluster->GetElectromagneticEnergy();
279  nHits += pCluster->GetNCaloHits();
280  }
281 }
282 
283 //------------------------------------------------------------------------------------------------------------------------------------------
284 
285 inline bool TrainedVertexSelectionAlgorithm::IsClusterShowerLike(const Cluster *const pCluster) const
286 {
287  return (pCluster->GetParticleId() == E_MINUS && LArClusterHelper::GetLength(pCluster) < m_minShowerSpineLength);
288 }
289 
290 //------------------------------------------------------------------------------------------------------------------------------------------
291 
292 void TrainedVertexSelectionAlgorithm::GetLegacyEventShapeFeatures(const ClusterList &clusterList, float &eventVolume, float &longitudinality) const
293 {
294  InputFloat xMin, yMin, zMin, xMax, yMax, zMax;
295 
296  for (const Cluster *const pCluster : clusterList)
297  {
298  CartesianVector minPosition(0.f, 0.f, 0.f), maxPosition(0.f, 0.f, 0.f);
299  LArClusterHelper::GetClusterBoundingBox(pCluster, minPosition, maxPosition);
300 
301  this->UpdateSpanCoordinate(minPosition.GetX(), maxPosition.GetX(), xMin, xMax);
302  this->UpdateSpanCoordinate(minPosition.GetY(), maxPosition.GetY(), yMin, yMax);
303  this->UpdateSpanCoordinate(minPosition.GetZ(), maxPosition.GetZ(), zMin, zMax);
304  }
305 
306  const float xSpan(this->GetCoordinateSpan(xMax, xMin));
307  const float ySpan(this->GetCoordinateSpan(yMax, zMin));
308  const float zSpan(this->GetCoordinateSpan(yMax, zMin));
309 
310  // Calculate the volume and longitudinality of the event (ySpan often 0 - to be investigated).
311  if ((xSpan > std::numeric_limits<float>::epsilon()) && (ySpan > std::numeric_limits<float>::epsilon()))
312  {
313  eventVolume = xSpan * ySpan * zSpan;
314  longitudinality = zSpan / (xSpan + ySpan);
315  }
316 
317  else if (ySpan > std::numeric_limits<float>::epsilon())
318  {
319  eventVolume = ySpan * ySpan * zSpan;
320  longitudinality = zSpan / (ySpan + ySpan);
321  }
322 
323  else if (xSpan > std::numeric_limits<float>::epsilon())
324  {
325  eventVolume = xSpan * xSpan * zSpan;
326  longitudinality = zSpan / (xSpan + xSpan);
327  }
328 }
329 
330 //------------------------------------------------------------------------------------------------------------------------------------------
331 
332 void TrainedVertexSelectionAlgorithm::GetEventShapeFeatures(const ClusterListMap &clusterListMap, float &eventArea, float &longitudinality) const
333 {
334  float xSpanU(0.f), zSpanU(0.f), xSpanV(0.f), zSpanV(0.f), xSpanW(0.f), zSpanW(0.f);
335 
336  this->Get2DSpan(clusterListMap.at(TPC_VIEW_U), xSpanU, zSpanU);
337  this->Get2DSpan(clusterListMap.at(TPC_VIEW_V), xSpanV, zSpanV);
338  this->Get2DSpan(clusterListMap.at(TPC_VIEW_W), xSpanW, zSpanW);
339 
340  const float xSpan = (xSpanU + xSpanV + xSpanW) / 3.f;
341  const float zSpan = (zSpanU + zSpanV + zSpanW) / 3.f;
342 
343  if ((xSpan > std::numeric_limits<float>::epsilon()) && (zSpan > std::numeric_limits<float>::epsilon()))
344  {
345  eventArea = xSpan * zSpan;
346  longitudinality = zSpan / (xSpan + zSpan);
347  }
348 }
349 
350 //------------------------------------------------------------------------------------------------------------------------------------------
351 
352 void TrainedVertexSelectionAlgorithm::Get2DSpan(const ClusterList &clusterList, float &xSpan, float &zSpan) const
353 {
354  FloatVector xPositions, zPositions;
355 
356  for (const Cluster *const pCluster : clusterList)
357  {
358  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
359 
360  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
361  {
362  for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
363  {
364  xPositions.push_back((*hitIter)->GetPositionVector().GetX());
365  zPositions.push_back((*hitIter)->GetPositionVector().GetZ());
366  }
367  }
368  }
369 
370  std::sort(xPositions.begin(), xPositions.end());
371  std::sort(zPositions.begin(), zPositions.end());
372 
373  if (xPositions.empty())
374  {
375  xSpan = 0;
376  zSpan = 0;
377  }
378  else
379  {
380  const int low = std::round(0.05 * xPositions.size());
381  const int high = std::round(0.95 * xPositions.size()) - 1;
382 
383  xSpan = xPositions[high] - xPositions[low];
384  zSpan = zPositions[high] - zPositions[low];
385  }
386 }
387 
388 //------------------------------------------------------------------------------------------------------------------------------------------
389 
391  const float minPositionCoord, const float maxPositionCoord, InputFloat &minCoord, InputFloat &maxCoord) const
392 {
393  if (!minCoord.IsInitialized() || minPositionCoord < minCoord.Get())
394  minCoord = minPositionCoord;
395 
396  if (!maxCoord.IsInitialized() || maxPositionCoord > maxCoord.Get())
397  maxCoord = maxPositionCoord;
398 }
399 
400 //------------------------------------------------------------------------------------------------------------------------------------------
401 
402 inline float TrainedVertexSelectionAlgorithm::GetCoordinateSpan(const InputFloat &minCoord, const InputFloat &maxCoord) const
403 {
404  if (minCoord.IsInitialized() && maxCoord.IsInitialized())
405  return std::fabs(maxCoord.Get() - minCoord.Get());
406 
407  return 0.f;
408 }
409 
410 //------------------------------------------------------------------------------------------------------------------------------------------
411 
413 {
414  featureVector.push_back(static_cast<double>(eventFeatureInfo.m_eventShoweryness));
415  featureVector.push_back(static_cast<double>(eventFeatureInfo.m_eventEnergy));
416  featureVector.push_back(static_cast<double>(eventFeatureInfo.m_eventArea));
417  featureVector.push_back(static_cast<double>(eventFeatureInfo.m_longitudinality));
418  featureVector.push_back(static_cast<double>(eventFeatureInfo.m_nHits));
419  featureVector.push_back(static_cast<double>(eventFeatureInfo.m_nClusters));
420  featureVector.push_back(static_cast<double>(eventFeatureInfo.m_nCandidates));
421 }
422 
423 //------------------------------------------------------------------------------------------------------------------------------------------
424 
426  const SlidingFitDataListMap &slidingFitDataListMap, const ShowerClusterListMap &showerClusterListMap, const KDTreeMap &kdTreeMap,
427  const Vertex *const pVertex, VertexFeatureInfoMap &vertexFeatureInfoMap) const
428 {
429  float bestFastScore(-std::numeric_limits<float>::max()); // not actually used - artefact of toolizing RPhi score and still using performance trick
430 
431  const double beamDeweighting(this->GetBeamDeweightingScore(beamConstants, pVertex));
432 
433  const double energyKick(LArMvaHelper::CalculateFeaturesOfType<EnergyKickFeatureTool>(m_featureToolVector, this, pVertex,
434  slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
435  .at(0)
436  .Get());
437 
438  const double localAsymmetry(LArMvaHelper::CalculateFeaturesOfType<LocalAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
439  slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
440  .at(0)
441  .Get());
442 
443  const double globalAsymmetry(LArMvaHelper::CalculateFeaturesOfType<GlobalAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
444  slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
445  .at(0)
446  .Get());
447 
448  const double showerAsymmetry(LArMvaHelper::CalculateFeaturesOfType<ShowerAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
449  slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
450  .at(0)
451  .Get());
452 
453  //const double rPhiFeature(LArMvaHelper::CalculateFeaturesOfType<RPhiFeatureTool>(m_featureToolVector, this, pVertex,
454  // slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore).at(0).Get());
455 
456  double dEdxAsymmetry(0.f), vertexEnergy(0.f);
457 
458  if (!m_legacyVariables)
459  {
460  dEdxAsymmetry = LArMvaHelper::CalculateFeaturesOfType<EnergyDepositionAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
461  slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
462  .at(0)
463  .Get();
464 
465  vertexEnergy = this->GetVertexEnergy(pVertex, kdTreeMap);
466  }
467 
468  VertexFeatureInfo vertexFeatureInfo(beamDeweighting, 0.f, energyKick, localAsymmetry, globalAsymmetry, showerAsymmetry, dEdxAsymmetry, vertexEnergy);
469  vertexFeatureInfoMap.emplace(pVertex, vertexFeatureInfo);
470 }
471 
472 //------------------------------------------------------------------------------------------------------------------------------------------
473 
475  VertexFeatureInfoMap &vertexFeatureInfoMap, const Vertex *const pVertex, VertexScoreList &initialScoreList) const
476 {
477  VertexFeatureInfo vertexFeatureInfo = vertexFeatureInfoMap.at(pVertex);
478 
479  const float beamDeweightingScore(vertexFeatureInfo.m_beamDeweighting / m_beamDeweightingConstant);
480  const float energyKickScore(-vertexFeatureInfo.m_energyKick / m_energyKickConstant);
481  const float localAsymmetryScore(vertexFeatureInfo.m_localAsymmetry / m_localAsymmetryConstant);
482  const float globalAsymmetryScore(vertexFeatureInfo.m_globalAsymmetry / m_globalAsymmetryConstant);
483  const float showerAsymmetryScore(vertexFeatureInfo.m_showerAsymmetry / m_showerAsymmetryConstant);
484 
485  initialScoreList.emplace_back(pVertex, beamDeweightingScore + energyKickScore + localAsymmetryScore + globalAsymmetryScore + showerAsymmetryScore);
486 }
487 
488 //------------------------------------------------------------------------------------------------------------------------------------------
489 
491 {
492  std::sort(initialScoreList.begin(), initialScoreList.end());
493 
494  for (const VertexScore &vertexScore : initialScoreList)
495  {
496  const Vertex *const pVertex(vertexScore.GetVertex());
497  bool farEnoughAway(true);
498 
499  for (const Vertex *const pRegionVertex : bestRegionVertices)
500  {
501  if (pRegionVertex == pVertex)
502  {
503  farEnoughAway = false;
504  break;
505  }
506 
507  const float distance = (pRegionVertex->GetPosition() - pVertex->GetPosition()).GetMagnitude();
508 
509  if (distance <= m_regionRadius)
510  {
511  farEnoughAway = false;
512  break;
513  }
514  }
515 
516  if (farEnoughAway)
517  bestRegionVertices.push_back(pVertex);
518  }
519 }
520 
521 //------------------------------------------------------------------------------------------------------------------------------------------
522 
523 void TrainedVertexSelectionAlgorithm::ProduceTrainingSets(const VertexVector &vertexVector, const VertexVector &bestRegionVertices,
524  VertexFeatureInfoMap &vertexFeatureInfoMap, const LArMvaHelper::MvaFeatureVector &eventFeatureList, const KDTreeMap &kdTreeMap) const
525 {
526  if (vertexVector.empty())
527  return;
528 
529  // Create a distribution for random coin flips.
530  std::random_device device;
531  std::mt19937 generator(device());
532  std::bernoulli_distribution coinFlip(0.5);
533 
534  const std::string interactionType(this->GetInteractionType());
535 
536  // Produce training examples for the vertices representing regions.
537  const Vertex *const pBestRegionVertex(this->ProduceTrainingExamples(bestRegionVertices, vertexFeatureInfoMap, coinFlip, generator,
538  interactionType, m_trainingOutputFileRegion, eventFeatureList, kdTreeMap, m_regionRadius, m_useRPhiFeatureForRegion));
539 
540  // Get all the vertices in the best region.
541  VertexVector regionalVertices{pBestRegionVertex};
542  for (const Vertex *const pVertex : vertexVector)
543  {
544  if (pVertex == pBestRegionVertex)
545  continue;
546 
547  if ((pBestRegionVertex->GetPosition() - pVertex->GetPosition()).GetMagnitude() < m_regionRadius)
548  regionalVertices.push_back(pVertex);
549  }
550 
551  this->CalculateRPhiScores(regionalVertices, vertexFeatureInfoMap, kdTreeMap);
552 
553  // Produce training examples for the final vertices within the best region.
554  if (!regionalVertices.empty())
555  {
556  this->ProduceTrainingExamples(regionalVertices, vertexFeatureInfoMap, coinFlip, generator, interactionType,
557  m_trainingOutputFileVertex, eventFeatureList, kdTreeMap, m_maxTrueVertexRadius, true);
558  }
559 }
560 
561 //------------------------------------------------------------------------------------------------------------------------------------------
562 
564  VertexVector &vertexVector, VertexFeatureInfoMap &vertexFeatureInfoMap, const KDTreeMap &kdTreeMap) const
565 {
566  float bestFastScore(-std::numeric_limits<float>::max());
567 
568  for (auto iter = vertexVector.begin(); iter != vertexVector.end(); /* no increment */)
569  {
570  VertexFeatureInfo &vertexFeatureInfo = vertexFeatureInfoMap.at(*iter);
571  vertexFeatureInfo.m_rPhiFeature = static_cast<float>(LArMvaHelper::CalculateFeaturesOfType<RPhiFeatureTool>(m_featureToolVector, this,
572  *iter, SlidingFitDataListMap(), ClusterListMap(), kdTreeMap, ShowerClusterListMap(), vertexFeatureInfo.m_beamDeweighting, bestFastScore)
573  .at(0)
574  .Get());
575 
576  if (m_dropFailedRPhiFastScoreCandidates && (vertexFeatureInfo.m_rPhiFeature <= std::numeric_limits<float>::epsilon()))
577  iter = vertexVector.erase(iter);
578 
579  else
580  ++iter;
581  }
582 }
583 
584 //------------------------------------------------------------------------------------------------------------------------------------------
585 
587 {
588  // Extract input collections
589  const MCParticleList *pMCParticleList(nullptr);
590  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_mcParticleListName, pMCParticleList));
591 
592  const CaloHitList *pCaloHitList(nullptr);
593  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_caloHitListName, pCaloHitList));
594 
595  LArMCParticleHelper::MCContributionMap targetMCParticlesToGoodHitsMap;
596 
597  if (m_testBeamMode)
598  {
600  LArMCParticleHelper::IsTriggeredBeamParticle, targetMCParticlesToGoodHitsMap);
601  }
602  else
603  {
604  // ATTN Assumes single neutrino is parent of all neutrino-induced mc particles
606  LArMCParticleHelper::IsBeamNeutrinoFinalState, targetMCParticlesToGoodHitsMap);
607  }
608 
609  MCParticleList mcPrimaryList;
610  for (const auto &mapEntry : targetMCParticlesToGoodHitsMap)
611  mcPrimaryList.push_back(mapEntry.first);
612  mcPrimaryList.sort(LArMCParticleHelper::SortByMomentum);
613 
615  return LArInteractionTypeHelper::ToString(interactionType);
616 }
617 
618 //------------------------------------------------------------------------------------------------------------------------------------------
619 
621  const VertexFeatureInfoMap &vertexFeatureInfoMap, std::bernoulli_distribution &coinFlip, std::mt19937 &generator,
622  const std::string &interactionType, const std::string &trainingOutputFile, const LArMvaHelper::MvaFeatureVector &eventFeatureList,
623  const KDTreeMap &kdTreeMap, const float maxRadius, const bool useRPhi) const
624 {
625  const Vertex *pBestVertex(nullptr);
626  float bestVertexDr(std::numeric_limits<float>::max());
627 
628  LArMvaHelper::MvaFeatureVector bestVertexFeatureList;
629  this->GetBestVertex(vertexVector, pBestVertex, bestVertexDr);
630 
631  VertexFeatureInfo bestVertexFeatureInfo(vertexFeatureInfoMap.at(pBestVertex));
632  this->AddVertexFeaturesToVector(bestVertexFeatureInfo, bestVertexFeatureList, useRPhi);
633 
634  for (const Vertex *const pVertex : vertexVector)
635  {
636  if (pVertex == pBestVertex)
637  continue;
638 
639  LArMvaHelper::MvaFeatureVector featureList;
640  VertexFeatureInfo vertexFeatureInfo(vertexFeatureInfoMap.at(pVertex));
641  this->AddVertexFeaturesToVector(vertexFeatureInfo, featureList, useRPhi);
642 
643  if (!m_legacyVariables)
644  {
645  LArMvaHelper::MvaFeatureVector sharedFeatureList;
646  float separation(0.f), axisHits(0.f);
647  this->GetSharedFeatures(pVertex, pBestVertex, kdTreeMap, separation, axisHits);
648  VertexSharedFeatureInfo sharedFeatureInfo(separation, axisHits);
649  this->AddSharedFeaturesToVector(sharedFeatureInfo, sharedFeatureList);
650 
651  if (pBestVertex && (bestVertexDr < maxRadius))
652  {
653  if (coinFlip(generator))
654  LArMvaHelper::ProduceTrainingExample(trainingOutputFile + "_" + interactionType + ".txt", true, eventFeatureList,
655  bestVertexFeatureList, featureList, sharedFeatureList);
656  else
657  LArMvaHelper::ProduceTrainingExample(trainingOutputFile + "_" + interactionType + ".txt", false, eventFeatureList,
658  featureList, bestVertexFeatureList, sharedFeatureList);
659  }
660  }
661  else
662  {
663  if (pBestVertex && (bestVertexDr < maxRadius))
664  {
665  if (coinFlip(generator))
667  trainingOutputFile + "_" + interactionType + ".txt", true, eventFeatureList, bestVertexFeatureList, featureList);
668  else
670  trainingOutputFile + "_" + interactionType + ".txt", false, eventFeatureList, featureList, bestVertexFeatureList);
671  }
672  }
673  }
674 
675  return pBestVertex;
676 }
677 
678 //------------------------------------------------------------------------------------------------------------------------------------------
679 
681  const Vertex *const pVertex1, const Vertex *const pVertex2, const KDTreeMap &kdTreeMap, float &separation, float &axisHits) const
682 {
683  separation = (pVertex1->GetPosition() - pVertex2->GetPosition()).GetMagnitude();
684 
685  this->IncrementSharedAxisValues(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex1->GetPosition(), TPC_VIEW_U),
686  LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex2->GetPosition(), TPC_VIEW_U), kdTreeMap.at(TPC_VIEW_U), axisHits);
687 
688  this->IncrementSharedAxisValues(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex1->GetPosition(), TPC_VIEW_V),
689  LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex2->GetPosition(), TPC_VIEW_V), kdTreeMap.at(TPC_VIEW_V), axisHits);
690 
691  this->IncrementSharedAxisValues(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex1->GetPosition(), TPC_VIEW_W),
692  LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex2->GetPosition(), TPC_VIEW_W), kdTreeMap.at(TPC_VIEW_W), axisHits);
693 
694  axisHits = separation > std::numeric_limits<float>::epsilon() ? axisHits / separation : 0.f;
695 }
696 
697 //------------------------------------------------------------------------------------------------------------------------------------------
698 
700  const CartesianVector pos1, const CartesianVector pos2, HitKDTree2D &kdTree, float &axisHits) const
701 {
702  if (pos1 == pos2)
703  return;
704 
705  // Define the axis and perpendicular directions
706  const CartesianVector unitAxis = (pos1 - pos2).GetUnitVector();
707  const CartesianVector unitPerp(unitAxis.GetZ(), 0, -unitAxis.GetX());
708 
709  // Define the corners of the search box
710  const CartesianVector point1 = pos1 + unitPerp;
711  const CartesianVector point2 = pos1 - unitPerp;
712  const CartesianVector point3 = pos2 + unitPerp;
713  const CartesianVector point4 = pos2 - unitPerp;
714 
715  // Find the total coordinate span these points cover
716  const float xMin{std::min({point1.GetX(), point2.GetX(), point3.GetX(), point4.GetX()})};
717  const float xMax{std::max({point1.GetX(), point2.GetX(), point3.GetX(), point4.GetX()})};
718  const float zMin{std::min({point1.GetZ(), point2.GetZ(), point3.GetZ(), point4.GetZ()})};
719  const float zMax{std::max({point1.GetZ(), point2.GetZ(), point3.GetZ(), point4.GetZ()})};
720 
721  // Use a kd search to find the hits in the 'wide' area
722  KDTreeBox searchBox(xMin, zMin, xMax, zMax);
724  kdTree.search(searchBox, found);
725 
726  // Use IsHitInBox method to check the 'wide' area hits for those in the search box
727  for (auto f : found)
728  {
729  const CartesianVector &hitPos = f.data->GetPositionVector();
730  bool inBox = this->IsHitInBox(hitPos, point1, point2, point3, point4);
731 
732  if (inBox)
733  ++axisHits;
734  }
735 }
736 
737 //------------------------------------------------------------------------------------------------------------------------------------------
738 
739 bool TrainedVertexSelectionAlgorithm::IsHitInBox(const CartesianVector &hitPos, const CartesianVector &point1,
740  const CartesianVector &point2, const CartesianVector &point3, const CartesianVector &point4) const
741 {
742  bool b1 = std::signbit(((point2 - point1).GetCrossProduct(point2 - hitPos)).GetY());
743  bool b2 = std::signbit(((point4 - point3).GetCrossProduct(point4 - hitPos)).GetY());
744 
745  if (!(b1 xor b2))
746  return false;
747 
748  bool b3 = std::signbit(((point3 - point1).GetCrossProduct(point3 - hitPos)).GetY());
749  bool b4 = std::signbit(((point4 - point2).GetCrossProduct(point4 - hitPos)).GetY());
750 
751  return (b3 xor b4);
752 }
753 
754 //------------------------------------------------------------------------------------------------------------------------------------------
755 
756 void TrainedVertexSelectionAlgorithm::GetBestVertex(const VertexVector &vertexVector, const Vertex *&pBestVertex, float &bestVertexDr) const
757 {
758  // Extract input collections
759  const MCParticleList *pMCParticleList(nullptr);
760  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_mcParticleListName, pMCParticleList));
761 
762  // Obtain vector: true targets
763  MCParticleVector mcTargetVector;
764 
765  if (m_testBeamMode)
766  {
767  LArMCParticleHelper::GetTrueTestBeamParticles(pMCParticleList, mcTargetVector);
768  }
769  else
770  {
771  LArMCParticleHelper::GetTrueNeutrinos(pMCParticleList, mcTargetVector);
772  }
773 
774  for (const Vertex *const pVertex : vertexVector)
775  {
776  float mcVertexDr(std::numeric_limits<float>::max());
777  for (const MCParticle *const pMCTarget : mcTargetVector)
778  {
779  const CartesianVector &mcTargetPosition(
780  (m_testBeamMode && std::fabs(pMCTarget->GetParticleId()) == 11) ? pMCTarget->GetVertex() : pMCTarget->GetEndpoint());
781  const CartesianVector mcTargetCorrectedPosition(
782  mcTargetPosition.GetX() + m_mcVertexXCorrection, mcTargetPosition.GetY(), mcTargetPosition.GetZ());
783  const float dr = (mcTargetCorrectedPosition - pVertex->GetPosition()).GetMagnitude();
784 
785  if (dr < mcVertexDr)
786  mcVertexDr = dr;
787  }
788 
789  if (mcVertexDr < bestVertexDr)
790  {
791  bestVertexDr = mcVertexDr;
792  pBestVertex = pVertex;
793  }
794  }
795 }
796 
797 //------------------------------------------------------------------------------------------------------------------------------------------
798 
800  const VertexFeatureInfo &vertexFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector, const bool useRPhi) const
801 {
802  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_beamDeweighting));
803  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_energyKick));
804  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_globalAsymmetry));
805  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_localAsymmetry));
806  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_showerAsymmetry));
807 
808  if (!m_legacyVariables)
809  {
810  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_dEdxAsymmetry));
811  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_vertexEnergy));
812  }
813 
814  if (useRPhi)
815  featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_rPhiFeature));
816 }
817 
818 //------------------------------------------------------------------------------------------------------------------------------------------
819 
821  const VertexSharedFeatureInfo &vertexSharedFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector) const
822 {
823  featureVector.push_back(static_cast<double>(vertexSharedFeatureInfo.m_separation));
824  featureVector.push_back(static_cast<double>(vertexSharedFeatureInfo.m_axisHits));
825 }
826 
827 //------------------------------------------------------------------------------------------------------------------------------------------
828 
830  const Vertex *const pFavouriteVertex, const VertexVector &vertexVector, VertexScoreList &finalVertexScoreList) const
831 {
832  if (pFavouriteVertex)
833  {
834  const CartesianVector vertexPosition(pFavouriteVertex->GetPosition());
835 
836  for (const Vertex *const pVertex : vertexVector)
837  {
838  if ((pVertex->GetPosition() - vertexPosition).GetMagnitude() < m_rPhiFineTuningRadius)
839  {
840  const float rPhiScore(vertexFeatureInfoMap.at(pVertex).m_rPhiFeature);
841  finalVertexScoreList.emplace_back(pVertex, rPhiScore);
842  }
843  }
844  }
845 }
846 
847 //------------------------------------------------------------------------------------------------------------------------------------------
848 //------------------------------------------------------------------------------------------------------------------------------------------
849 
850 StatusCode TrainedVertexSelectionAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
851 {
852  AlgorithmToolVector algorithmToolVector;
853  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "FeatureTools", algorithmToolVector));
854 
855  for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
856  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, LArMvaHelper::AddFeatureToolToVector(pAlgorithmTool, m_featureToolVector));
857 
858  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingSetMode", m_trainingSetMode));
859 
860  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
861  XmlHelper::ReadValue(xmlHandle, "AllowClassifyDuringTraining", m_allowClassifyDuringTraining));
862 
863  PANDORA_RETURN_RESULT_IF_AND_IF(
864  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MCVertexXCorrection", m_mcVertexXCorrection));
865 
866  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
867  XmlHelper::ReadValue(xmlHandle, "TrainingOutputFileRegion", m_trainingOutputFileRegion));
868 
869  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
870  XmlHelper::ReadValue(xmlHandle, "TrainingOutputFileVertex", m_trainingOutputFileVertex));
871 
873  {
874  std::cout << "TrainedVertexSelectionAlgorithm: TrainingOutputFileRegion and TrainingOutputFileVertex are required for training set "
875  << "mode" << std::endl;
876  return STATUS_CODE_INVALID_PARAMETER;
877  }
878 
879  PANDORA_RETURN_RESULT_IF_AND_IF(
880  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MCParticleListName", m_mcParticleListName));
881 
882  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListName", m_caloHitListName));
883 
884  if (m_trainingSetMode && (m_mcParticleListName.empty() || m_caloHitListName.empty()))
885  {
886  std::cout << "TrainedVertexSelectionAlgorithm: MCParticleListName and CaloHitListName are required for training set mode" << std::endl;
887  return STATUS_CODE_INVALID_PARAMETER;
888  }
889 
890  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputClusterListNames", m_inputClusterListNames));
891 
892  PANDORA_RETURN_RESULT_IF_AND_IF(
893  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterCaloHits", m_minClusterCaloHits));
894 
895  PANDORA_RETURN_RESULT_IF_AND_IF(
896  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
897 
898  PANDORA_RETURN_RESULT_IF_AND_IF(
899  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinShowerSpineLength", m_minShowerSpineLength));
900 
901  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
902  XmlHelper::ReadValue(xmlHandle, "BeamDeweightingConstant", m_beamDeweightingConstant));
903 
904  PANDORA_RETURN_RESULT_IF_AND_IF(
905  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LocalAsymmetryConstant", m_localAsymmetryConstant));
906 
907  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
908  XmlHelper::ReadValue(xmlHandle, "GlobalAsymmetryConstant", m_globalAsymmetryConstant));
909 
910  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
911  XmlHelper::ReadValue(xmlHandle, "ShowerAsymmetryConstant", m_showerAsymmetryConstant));
912 
913  PANDORA_RETURN_RESULT_IF_AND_IF(
914  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "EnergyKickConstant", m_energyKickConstant));
915 
916  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
917  XmlHelper::ReadValue(xmlHandle, "ShowerClusteringDistance", m_showerClusteringDistance));
918 
919  PANDORA_RETURN_RESULT_IF_AND_IF(
920  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinShowerClusterHits", m_minShowerClusterHits));
921 
922  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
923  XmlHelper::ReadValue(xmlHandle, "UseShowerClusteringApproximation", m_useShowerClusteringApproximation));
924 
925  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "RegionRadius", m_regionRadius));
926 
927  PANDORA_RETURN_RESULT_IF_AND_IF(
928  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "RPhiFineTuningRadius", m_rPhiFineTuningRadius));
929 
930  PANDORA_RETURN_RESULT_IF_AND_IF(
931  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxTrueVertexRadius", m_maxTrueVertexRadius));
932 
933  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
934  XmlHelper::ReadValue(xmlHandle, "UseRPhiFeatureForRegion", m_useRPhiFeatureForRegion));
935 
936  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
937  XmlHelper::ReadValue(xmlHandle, "DropFailedRPhiFastScoreCandidates", m_dropFailedRPhiFastScoreCandidates));
938 
939  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TestBeamMode", m_testBeamMode));
940 
941  PANDORA_RETURN_RESULT_IF_AND_IF(
942  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LegacyEventShapes", m_legacyEventShapes));
943 
944  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LegacyVariables", m_legacyVariables));
945 
947  std::cout << "TrainedVertexSelectionAlgorithm: WARNING -- Producing training sample using incorrect legacy event shapes, consider turning LegacyEventShapes off"
948  << std::endl;
949 
951 }
952 
953 } // namespace lar_content
void AddEventFeaturesToVector(const EventFeatureInfo &eventFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector) const
Add the event features to a vector in the correct order.
void GetLegacyEventShapeFeatures(const pandora::ClusterList &clusterList, float &eventVolume, float &longitudinality) const
Get the event shape features.
std::string m_trainingOutputFileVertex
The training output file for the vertex mva.
unsigned int m_nCandidates
The total number of vertex candidates.
bool m_useShowerClusteringApproximation
Whether to use the shower clustering distance approximation.
bool m_useRPhiFeatureForRegion
Whether to use the r/phi feature for the region vertex.
Header file for the kd tree linker algo template class.
void GetBestRegionVertices(VertexScoreList &initialScoreList, pandora::VertexVector &bestRegionVertices) const
Get the list of top-N separated vertices.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:58
unsigned int m_minClusterCaloHits
The min number of hits parameter in the energy score.
Header file for the interaction type helper class.
void PopulateInitialScoreList(VertexFeatureInfoMap &vertexFeatureInfoMap, const pandora::Vertex *const pVertex, VertexScoreList &initialScoreList) const
Populate the initial vertex score list for a given vertex.
Header file for the energy deposition asymmetry feature tool class.
VertexFeatureTool::FeatureToolVector m_featureToolVector
The feature tool vector.
std::string string
Definition: nybbler.cc:12
Box structure used to define 2D field. It&#39;s used in KDTree building step to divide the detector space...
void PopulateFinalVertexScoreList(const VertexFeatureInfoMap &vertexFeatureInfoMap, const pandora::Vertex *const pFavouriteVertex, const pandora::VertexVector &vertexVector, VertexScoreList &finalVertexScoreList) const
Populate the final vertex score list using the r/phi score to find the best vertex in the vicinity...
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
bool m_legacyEventShapes
Whether to use the old event shapes calculation.
intermediate_table::const_iterator const_iterator
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
void AddVertexFeaturesToVector(const VertexFeatureInfo &vertexFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector, const bool useRPhi) const
Add the vertex features to a vector in the correct order.
void IncrementSharedAxisValues(const pandora::CartesianVector pos1, const pandora::CartesianVector pos2, HitKDTree2D &kdTree, float &axisHits) const
Increments the axis hits information for one view.
const pandora::Vertex * ProduceTrainingExamples(const pandora::VertexVector &vertexVector, const VertexFeatureInfoMap &vertexFeatureInfoMap, std::bernoulli_distribution &coinFlip, std::mt19937 &generator, const std::string &interactionType, const std::string &trainingOutputFile, const LArMvaHelper::MvaFeatureVector &eventFeatureList, const KDTreeMap &kdTreeMap, const float maxRadius, const bool useRPhi) const
Produce a set of training examples for a binary classifier.
bool IsClusterShowerLike(const pandora::Cluster *const pCluster) const
Find whether a cluster is shower-like.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
static InteractionType GetInteractionType(const pandora::MCParticleList &mcPrimaryList)
Get the interaction type of an event.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
void CalculateRPhiScores(pandora::VertexVector &vertexVector, VertexFeatureInfoMap &vertexFeatureInfoMap, const KDTreeMap &kdTreeMap) const
Calculate the r/phi scores for the vertices in a vector, possibly erasing those that fail the fast sc...
Header file for the trained vertex selection algorithm class.
void Get2DSpan(const pandora::ClusterList &clusterList, float &xSpan, float &zSpan) const
Get the coordinate span in one view.
float m_localAsymmetryConstant
The local asymmetry constant for the initial region score list.
bool IsHitInBox(const pandora::CartesianVector &hitPos, const pandora::CartesianVector &point1, const pandora::CartesianVector &point2, const pandora::CartesianVector &point3, const pandora::CartesianVector &point4) const
Determines whether a hit lies within the box defined by four other positions.
unsigned int m_minShowerClusterHits
The minimum number of shower cluster hits.
Header file for the geometry helper class.
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
static void GetClusterBoundingBox(const pandora::Cluster *const pCluster, pandora::CartesianVector &minimumCoordinate, pandora::CartesianVector &maximumCoordinate)
Get minimum and maximum X, Y and Z positions of the calo hits in a cluster.
void ProduceTrainingSets(const pandora::VertexVector &vertexVector, const pandora::VertexVector &bestRegionVertices, VertexFeatureInfoMap &vertexFeatureInfoMap, const LArMvaHelper::MvaFeatureVector &eventFeatureList, const KDTreeMap &kdTreeMap) const
Produce the region and vertex training sets.
static void SelectReconstructableMCParticles(const pandora::MCParticleList *pMCParticleList, const pandora::CaloHitList *pCaloHitList, const PrimaryParameters &parameters, std::function< bool(const pandora::MCParticle *const)> fCriteria, MCContributionMap &selectedMCParticlesToHitsMap)
Select target, reconstructable mc particles that match given criteria.
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TLISTS &&...featureLists)
Produce a training example with the given features and result.
Definition: LArMvaHelper.h:197
std::map< pandora::HitType, const ShowerClusterList > ShowerClusterListMap
Map of shower cluster lists for passing to tools.
std::string m_mcParticleListName
The MC particle list for creating training examples.
void PopulateVertexFeatureInfoMap(const BeamConstants &beamConstants, const ClusterListMap &clusterListMap, const SlidingFitDataListMap &slidingFitDataListMap, const ShowerClusterListMap &showerClusterListMap, const KDTreeMap &kdTreeMap, const pandora::Vertex *const pVertex, VertexFeatureInfoMap &vertexFeatureInfoMap) const
Populate the vertex feature info map for a given vertex.
float m_globalAsymmetryConstant
The global asymmetry constant for the initial region score list.
Header file for the lar monte carlo particle helper helper class.
std::pair< pandora::CartesianVector, pandora::CartesianVector > ClusterEndPoints
static bool SortHitsByPosition(const pandora::CaloHit *const pLhs, const pandora::CaloHit *const pRhs)
Sort calo hits by their position (use Z, followed by X, followed by Y)
Header file for the cluster helper class.
static std::string ToString(const InteractionType interactionType)
Get a string representation of an interaction type.
EventFeatureInfo CalculateEventFeatures(const pandora::ClusterList &clusterListU, const pandora::ClusterList &clusterListV, const pandora::ClusterList &clusterListW, const pandora::VertexVector &vertexVector) const
Calculate the event parameters.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM >> &eltList, const KDTreeBoxT< DIM > &region)
Build the KD tree from the "eltList" in the space define by "region".
float m_maxTrueVertexRadius
The maximum distance at which a vertex candidate can be considered the &#39;true&#39; vertex.
std::map< pandora::HitType, const pandora::ClusterList & > ClusterListMap
Map array of cluster lists for passing to tools.
static float GetLength(const pandora::Cluster *const pCluster)
Get length of cluster.
static pandora::StatusCode AddFeatureToolToVector(pandora::AlgorithmTool *const pFeatureTool, MvaFeatureToolVector< Ts... > &featureToolVector)
Add a feature tool to a vector of feature tools.
Definition: LArMvaHelper.h:274
float m_showerAsymmetryConstant
The shower asymmetry constant for the initial region score list.
static bool IsTriggeredBeamParticle(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary triggered beam MCParticle.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
Header file for the local asymmetry feature tool class.
Header file for the file helper class.
static int max(int a, int b)
generator
Definition: train.py:468
void PopulateKdTree(const pandora::ClusterList &clusterList, HitKDTree2D &kdTree, HitToClusterMap &hitToClusterMap) const
Populate kd tree with information about hits in a provided list of clusters.
Detector simulation of raw signals on wires.
float m_beamDeweightingConstant
The beam deweighting constant for the initial region score list.
bool m_allowClassifyDuringTraining
Whether classification is allowed during training.
void CalculateShowerClusterList(const pandora::ClusterList &inputClusterList, ShowerClusterList &showerClusterList) const
Calculate the shower cluster map for a cluster list.
std::string m_trainingOutputFileRegion
The training output file for the region mva.
bool m_dropFailedRPhiFastScoreCandidates
Whether to drop candidates that fail the r/phi fast score test.
void AddSharedFeaturesToVector(const VertexSharedFeatureInfo &vertexSharedFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector) const
Add the shared features to a vector in the correct order.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
float m_energyKickConstant
The energy kick constant for the initial region score list.
void GetSharedFeatures(const pandora::Vertex *const pVertex1, const pandora::Vertex *const pVertex2, const KDTreeMap &kdTreeMap, float &separation, float &axisHits) const
Calculates the shared features of a pair of vertex candidates.
static void GetTrueNeutrinos(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &trueNeutrinos)
Get neutrino MC particles from an input MC particle list.
std::map< pandora::HitType, const SlidingFitDataList > SlidingFitDataListMap
Map of sliding fit data lists for passing to tools.
float GetVertexEnergy(const pandora::Vertex *const pVertex, const KDTreeMap &kdTreeMap) const
Calculate the energy of a vertex candidate by summing values from all three planes.
void UpdateSpanCoordinate(const float minPositionCoord, const float maxPositionCoord, pandora::InputFloat &minCoord, pandora::InputFloat &maxCoord) const
Update the min/max coordinate spans.
float m_mcVertexXCorrection
The correction to the x-coordinate of the MC vertex position.
void IncrementShoweryParameters(const pandora::ClusterList &clusterList, unsigned int &nShoweryHits, unsigned int &nHits, float &eventEnergy) const
Increment the showery hit parameters for a cluster list.
float GetCoordinateSpan(const pandora::InputFloat &minCoord, const pandora::InputFloat &maxCoord) const
Get the coordinate span.
bool m_legacyVariables
Whether to only use the old variables.
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
std::map< const pandora::Cluster *const, ClusterEndPoints > ClusterEndPointsMap
void GetEventShapeFeatures(const ClusterListMap &clusterListMap, float &eventArea, float &longitudinality) const
Get the event shape features.
std::string m_caloHitListName
The 2D CaloHit list name.
std::vector< art::Ptr< recob::Vertex > > VertexVector
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 >> &nodes)
fill_and_bound_2d_kd_tree
Header file for the shower asymmetry feature tool class.
bool AddClusterToShower(const ClusterEndPointsMap &clusterEndPointsMap, pandora::ClusterList &availableShowerLikeClusters, const pandora::Cluster *const pCluster, pandora::ClusterList &showerCluster) const
Try to add an available cluster to a given shower cluster, using shower clustering approximation...
float m_minShowerSpineLength
The minimum length at which all are considered to be tracks.
void GetShowerLikeClusterEndPoints(const pandora::ClusterList &clusterList, pandora::ClusterList &showerLikeClusters, ClusterEndPointsMap &clusterEndPointsMap) const
Add the endpoints of any shower-like clusters to the map.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
std::map< pandora::HitType, const std::reference_wrapper< HitKDTree2D > > KDTreeMap
Map array of hit kd trees for passing to tools.
Dft::FloatVector FloatVector
float GetBeamDeweightingScore(const BeamConstants &beamConstants, const pandora::Vertex *const pVertex) const
Get the beam deweighting score for a vertex.
static void GetTrueTestBeamParticles(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &trueTestBeamParticles)
Get triggered test beam MC particles from an input MC particle list.
Header file for the energy kick feature tool class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float m_showerClusteringDistance
The shower clustering distance.
float m_axisHits
The hit density along the axis between the two vertices.
static bool IsBeamNeutrinoFinalState(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary neutrino final state MCParticle.
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
pandora::StringVector m_inputClusterListNames
The list of cluster list names.
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM >> &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
std::map< const pandora::Vertex *const, VertexFeatureInfo > VertexFeatureInfoMap
float m_rPhiFineTuningRadius
The maximum distance the r/phi tune can move a vertex.
QTextStream & endl(QTextStream &s)
void GetBestVertex(const pandora::VertexVector &vertexVector, const pandora::Vertex *&pBestVertex, float &bestVertexDr) const
Use the MC information to get the best vertex from a list.
Header file for the r/phi feature tool class.
Header file for the global asymmetry feature tool class.
std::string GetInteractionType() const
Get the interaction type string.