Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
TrainedVertexSelectionAlgorithm.cc
Go to the documentation of this file.
1
10
17
24
26
28
29#include <random>
30
31using namespace pandora;
32
33namespace lar_content
34{
35
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
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
146void 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
216 HitKDNode2DList found;
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
285inline bool TrainedVertexSelectionAlgorithm::IsClusterShowerLike(const Cluster *const pCluster) const
286{
287 return (pCluster->GetParticleId() == E_MINUS && LArClusterHelper::GetLength(pCluster) < m_minShowerSpineLength);
288}
289
290//------------------------------------------------------------------------------------------------------------------------------------------
291
292void 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
332void 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
352void 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
402inline 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 if (this->IsBeamModeOn())
419 {
420 featureVector.push_back(static_cast<double>(eventFeatureInfo.m_nHits));
421 featureVector.push_back(static_cast<double>(eventFeatureInfo.m_nClusters));
422 featureVector.push_back(static_cast<double>(eventFeatureInfo.m_nCandidates));
423 }
424}
425
426//------------------------------------------------------------------------------------------------------------------------------------------
427
429 const SlidingFitDataListMap &slidingFitDataListMap, const ShowerClusterListMap &showerClusterListMap, const KDTreeMap &kdTreeMap,
430 const Vertex *const pVertex, VertexFeatureInfoMap &vertexFeatureInfoMap) const
431{
432 float bestFastScore(-std::numeric_limits<float>::max()); // not actually used - artefact of toolizing RPhi score and still using performance trick
433
434 // ATTN - If beam mode is false GetBeamDeweightingScore will fail, so have a default value that we'll ignore when poplating the feature vector
435 double tempBeamDeweight{0.f};
436 if (this->IsBeamModeOn())
437 tempBeamDeweight = this->GetBeamDeweightingScore(beamConstants, pVertex);
438
439 const double beamDeweighting(tempBeamDeweight);
440
441 const double energyKick(LArMvaHelper::CalculateFeaturesOfType<EnergyKickFeatureTool>(m_featureToolVector, this, pVertex,
442 slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
443 .at(0)
444 .Get());
445
446 const double localAsymmetry(LArMvaHelper::CalculateFeaturesOfType<LocalAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
447 slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
448 .at(0)
449 .Get());
450
451 const double globalAsymmetry(LArMvaHelper::CalculateFeaturesOfType<GlobalAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
452 slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
453 .at(0)
454 .Get());
455
456 const double showerAsymmetry(LArMvaHelper::CalculateFeaturesOfType<ShowerAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
457 slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
458 .at(0)
459 .Get());
460
461 //const double rPhiFeature(LArMvaHelper::CalculateFeaturesOfType<RPhiFeatureTool>(m_featureToolVector, this, pVertex,
462 // slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore).at(0).Get());
463
464 double dEdxAsymmetry(0.f), vertexEnergy(0.f);
465
467 {
468 dEdxAsymmetry = LArMvaHelper::CalculateFeaturesOfType<EnergyDepositionAsymmetryFeatureTool>(m_featureToolVector, this, pVertex,
469 slidingFitDataListMap, clusterListMap, kdTreeMap, showerClusterListMap, beamDeweighting, bestFastScore)
470 .at(0)
471 .Get();
472
473 vertexEnergy = this->GetVertexEnergy(pVertex, kdTreeMap);
474 }
475
476 VertexFeatureInfo vertexFeatureInfo(beamDeweighting, 0.f, energyKick, localAsymmetry, globalAsymmetry, showerAsymmetry, dEdxAsymmetry, vertexEnergy);
477 vertexFeatureInfoMap.emplace(pVertex, vertexFeatureInfo);
478}
479
480//------------------------------------------------------------------------------------------------------------------------------------------
481
483 VertexFeatureInfoMap &vertexFeatureInfoMap, const Vertex *const pVertex, VertexScoreList &initialScoreList) const
484{
485 VertexFeatureInfo vertexFeatureInfo = vertexFeatureInfoMap.at(pVertex);
486
487 const float beamDeweightingScore(vertexFeatureInfo.m_beamDeweighting / m_beamDeweightingConstant);
488 const float energyKickScore(-vertexFeatureInfo.m_energyKick / m_energyKickConstant);
489 const float localAsymmetryScore(vertexFeatureInfo.m_localAsymmetry / m_localAsymmetryConstant);
490 const float globalAsymmetryScore(vertexFeatureInfo.m_globalAsymmetry / m_globalAsymmetryConstant);
491 const float showerAsymmetryScore(vertexFeatureInfo.m_showerAsymmetry / m_showerAsymmetryConstant);
492
493 initialScoreList.emplace_back(pVertex, beamDeweightingScore + energyKickScore + localAsymmetryScore + globalAsymmetryScore + showerAsymmetryScore);
494}
495
496//------------------------------------------------------------------------------------------------------------------------------------------
497
499{
500 std::sort(initialScoreList.begin(), initialScoreList.end());
501
502 for (const VertexScore &vertexScore : initialScoreList)
503 {
504 const Vertex *const pVertex(vertexScore.GetVertex());
505 bool farEnoughAway(true);
506
507 for (const Vertex *const pRegionVertex : bestRegionVertices)
508 {
509 if (pRegionVertex == pVertex)
510 {
511 farEnoughAway = false;
512 break;
513 }
514
515 const float distance = (pRegionVertex->GetPosition() - pVertex->GetPosition()).GetMagnitude();
516
517 if (distance <= m_regionRadius)
518 {
519 farEnoughAway = false;
520 break;
521 }
522 }
523
524 if (farEnoughAway)
525 bestRegionVertices.push_back(pVertex);
526 }
527}
528
529//------------------------------------------------------------------------------------------------------------------------------------------
530
531void TrainedVertexSelectionAlgorithm::ProduceTrainingSets(const VertexVector &vertexVector, const VertexVector &bestRegionVertices,
532 VertexFeatureInfoMap &vertexFeatureInfoMap, const LArMvaHelper::MvaFeatureVector &eventFeatureList, const KDTreeMap &kdTreeMap) const
533{
534 if (vertexVector.empty())
535 return;
536
537 // Create a distribution for random coin flips.
538 std::random_device device;
539 std::mt19937 generator(device());
540 std::bernoulli_distribution coinFlip(0.5);
541
542 const std::string interactionType(this->GetInteractionType());
543
544 // Produce training examples for the vertices representing regions.
545 const Vertex *const pBestRegionVertex(this->ProduceTrainingExamples(bestRegionVertices, vertexFeatureInfoMap, coinFlip, generator,
546 interactionType, m_trainingOutputFileRegion, eventFeatureList, kdTreeMap, m_regionRadius, m_useRPhiFeatureForRegion));
547
548 // Get all the vertices in the best region.
549 VertexVector regionalVertices{pBestRegionVertex};
550 for (const Vertex *const pVertex : vertexVector)
551 {
552 if (pVertex == pBestRegionVertex)
553 continue;
554
555 if ((pBestRegionVertex->GetPosition() - pVertex->GetPosition()).GetMagnitude() < m_regionRadius)
556 regionalVertices.push_back(pVertex);
557 }
558
559 this->CalculateRPhiScores(regionalVertices, vertexFeatureInfoMap, kdTreeMap);
560
561 // Produce training examples for the final vertices within the best region.
562 if (!regionalVertices.empty())
563 {
564 this->ProduceTrainingExamples(regionalVertices, vertexFeatureInfoMap, coinFlip, generator, interactionType,
565 m_trainingOutputFileVertex, eventFeatureList, kdTreeMap, m_maxTrueVertexRadius, true);
566 }
567}
568
569//------------------------------------------------------------------------------------------------------------------------------------------
570
572 VertexVector &vertexVector, VertexFeatureInfoMap &vertexFeatureInfoMap, const KDTreeMap &kdTreeMap) const
573{
574 float bestFastScore(-std::numeric_limits<float>::max());
575
576 for (auto iter = vertexVector.begin(); iter != vertexVector.end(); /* no increment */)
577 {
578 VertexFeatureInfo &vertexFeatureInfo = vertexFeatureInfoMap.at(*iter);
579 vertexFeatureInfo.m_rPhiFeature = static_cast<float>(LArMvaHelper::CalculateFeaturesOfType<RPhiFeatureTool>(m_featureToolVector, this,
580 *iter, SlidingFitDataListMap(), ClusterListMap(), kdTreeMap, ShowerClusterListMap(), vertexFeatureInfo.m_beamDeweighting, bestFastScore)
581 .at(0)
582 .Get());
583
584 if (m_dropFailedRPhiFastScoreCandidates && (vertexFeatureInfo.m_rPhiFeature <= std::numeric_limits<float>::epsilon()))
585 iter = vertexVector.erase(iter);
586
587 else
588 ++iter;
589 }
590}
591
592//------------------------------------------------------------------------------------------------------------------------------------------
593
595{
596 // Extract input collections
597 const MCParticleList *pMCParticleList(nullptr);
598 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_mcParticleListName, pMCParticleList));
599
600 const CaloHitList *pCaloHitList(nullptr);
601 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_caloHitListName, pCaloHitList));
602
603 LArMCParticleHelper::MCContributionMap targetMCParticlesToGoodHitsMap;
604
605 if (m_testBeamMode)
606 {
608 LArMCParticleHelper::IsTriggeredBeamParticle, targetMCParticlesToGoodHitsMap);
609 }
610 else
611 {
612 // ATTN Assumes single neutrino is parent of all neutrino-induced mc particles
614 LArMCParticleHelper::IsBeamNeutrinoFinalState, targetMCParticlesToGoodHitsMap);
615 }
616
617 MCParticleList mcPrimaryList;
618 for (const auto &mapEntry : targetMCParticlesToGoodHitsMap)
619 mcPrimaryList.push_back(mapEntry.first);
620 mcPrimaryList.sort(LArMCParticleHelper::SortByMomentum);
621
623 return LArInteractionTypeHelper::ToString(interactionType);
624}
625
626//------------------------------------------------------------------------------------------------------------------------------------------
627
629 const VertexFeatureInfoMap &vertexFeatureInfoMap, std::bernoulli_distribution &coinFlip, std::mt19937 &generator,
630 const std::string &interactionType, const std::string &trainingOutputFile, const LArMvaHelper::MvaFeatureVector &eventFeatureList,
631 const KDTreeMap &kdTreeMap, const float maxRadius, const bool useRPhi) const
632{
633 const Vertex *pBestVertex(nullptr);
634 float bestVertexDr(std::numeric_limits<float>::max());
635
636 LArMvaHelper::MvaFeatureVector bestVertexFeatureList;
637 this->GetBestVertex(vertexVector, pBestVertex, bestVertexDr);
638
639 VertexFeatureInfo bestVertexFeatureInfo(vertexFeatureInfoMap.at(pBestVertex));
640 this->AddVertexFeaturesToVector(bestVertexFeatureInfo, bestVertexFeatureList, useRPhi);
641
642 for (const Vertex *const pVertex : vertexVector)
643 {
644 if (pVertex == pBestVertex)
645 continue;
646
648 VertexFeatureInfo vertexFeatureInfo(vertexFeatureInfoMap.at(pVertex));
649 this->AddVertexFeaturesToVector(vertexFeatureInfo, featureList, useRPhi);
650
652 {
653 LArMvaHelper::MvaFeatureVector sharedFeatureList;
654 float separation(0.f), axisHits(0.f);
655 this->GetSharedFeatures(pVertex, pBestVertex, kdTreeMap, separation, axisHits);
656 VertexSharedFeatureInfo sharedFeatureInfo(separation, axisHits);
657 this->AddSharedFeaturesToVector(sharedFeatureInfo, sharedFeatureList);
658
659 if (pBestVertex && (bestVertexDr < maxRadius))
660 {
661 if (coinFlip(generator))
662 LArMvaHelper::ProduceTrainingExample(trainingOutputFile + "_" + interactionType + ".txt", true,
663 LArMvaHelper::ConcatenateFeatureLists(eventFeatureList, bestVertexFeatureList, featureList, sharedFeatureList));
664 else
665 LArMvaHelper::ProduceTrainingExample(trainingOutputFile + "_" + interactionType + ".txt", false,
666 LArMvaHelper::ConcatenateFeatureLists(eventFeatureList, featureList, bestVertexFeatureList, sharedFeatureList));
667 }
668 }
669 else
670 {
671 if (pBestVertex && (bestVertexDr < maxRadius))
672 {
673 if (coinFlip(generator))
674 LArMvaHelper::ProduceTrainingExample(trainingOutputFile + "_" + interactionType + ".txt", true,
675 LArMvaHelper::ConcatenateFeatureLists(eventFeatureList, bestVertexFeatureList, featureList));
676 else
677 LArMvaHelper::ProduceTrainingExample(trainingOutputFile + "_" + interactionType + ".txt", false,
678 LArMvaHelper::ConcatenateFeatureLists(eventFeatureList, featureList, bestVertexFeatureList));
679 }
680 }
681 }
682
683 return pBestVertex;
684}
685
686//------------------------------------------------------------------------------------------------------------------------------------------
687
689 const Vertex *const pVertex1, const Vertex *const pVertex2, const KDTreeMap &kdTreeMap, float &separation, float &axisHits) const
690{
691 separation = (pVertex1->GetPosition() - pVertex2->GetPosition()).GetMagnitude();
692
694 LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex2->GetPosition(), TPC_VIEW_U), kdTreeMap.at(TPC_VIEW_U), axisHits);
695
697 LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex2->GetPosition(), TPC_VIEW_V), kdTreeMap.at(TPC_VIEW_V), axisHits);
698
700 LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex2->GetPosition(), TPC_VIEW_W), kdTreeMap.at(TPC_VIEW_W), axisHits);
701
702 axisHits = separation > std::numeric_limits<float>::epsilon() ? axisHits / separation : 0.f;
703}
704
705//------------------------------------------------------------------------------------------------------------------------------------------
706
708 const CartesianVector pos1, const CartesianVector pos2, HitKDTree2D &kdTree, float &axisHits) const
709{
710 if (pos1 == pos2)
711 return;
712
713 // Define the axis and perpendicular directions
714 const CartesianVector unitAxis = (pos1 - pos2).GetUnitVector();
715 const CartesianVector unitPerp(unitAxis.GetZ(), 0, -unitAxis.GetX());
716
717 // Define the corners of the search box
718 const CartesianVector point1 = pos1 + unitPerp;
719 const CartesianVector point2 = pos1 - unitPerp;
720 const CartesianVector point3 = pos2 + unitPerp;
721 const CartesianVector point4 = pos2 - unitPerp;
722
723 // Find the total coordinate span these points cover
724 const float xMin{std::min({point1.GetX(), point2.GetX(), point3.GetX(), point4.GetX()})};
725 const float xMax{std::max({point1.GetX(), point2.GetX(), point3.GetX(), point4.GetX()})};
726 const float zMin{std::min({point1.GetZ(), point2.GetZ(), point3.GetZ(), point4.GetZ()})};
727 const float zMax{std::max({point1.GetZ(), point2.GetZ(), point3.GetZ(), point4.GetZ()})};
728
729 // Use a kd search to find the hits in the 'wide' area
730 KDTreeBox searchBox(xMin, zMin, xMax, zMax);
731 HitKDNode2DList found;
732 kdTree.search(searchBox, found);
733
734 // Use IsHitInBox method to check the 'wide' area hits for those in the search box
735 for (auto f : found)
736 {
737 const CartesianVector &hitPos = f.data->GetPositionVector();
738 bool inBox = this->IsHitInBox(hitPos, point1, point2, point3, point4);
739
740 if (inBox)
741 ++axisHits;
742 }
743}
744
745//------------------------------------------------------------------------------------------------------------------------------------------
746
748 const CartesianVector &point2, const CartesianVector &point3, const CartesianVector &point4) const
749{
750 bool b1 = std::signbit(((point2 - point1).GetCrossProduct(point2 - hitPos)).GetY());
751 bool b2 = std::signbit(((point4 - point3).GetCrossProduct(point4 - hitPos)).GetY());
752
753 if (!(b1 xor b2))
754 return false;
755
756 bool b3 = std::signbit(((point3 - point1).GetCrossProduct(point3 - hitPos)).GetY());
757 bool b4 = std::signbit(((point4 - point2).GetCrossProduct(point4 - hitPos)).GetY());
758
759 return (b3 xor b4);
760}
761
762//------------------------------------------------------------------------------------------------------------------------------------------
763
764void TrainedVertexSelectionAlgorithm::GetBestVertex(const VertexVector &vertexVector, const Vertex *&pBestVertex, float &bestVertexDr) const
765{
766 // Extract input collections
767 const MCParticleList *pMCParticleList(nullptr);
768 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_mcParticleListName, pMCParticleList));
769
770 // Obtain vector: true targets
771 MCParticleVector mcTargetVector;
772
773 if (m_testBeamMode)
774 {
775 LArMCParticleHelper::GetTrueTestBeamParticles(pMCParticleList, mcTargetVector);
776 }
777 else
778 {
779 LArMCParticleHelper::GetTrueNeutrinos(pMCParticleList, mcTargetVector);
780 }
781
782 for (const Vertex *const pVertex : vertexVector)
783 {
784 float mcVertexDr(std::numeric_limits<float>::max());
785 for (const MCParticle *const pMCTarget : mcTargetVector)
786 {
787 const CartesianVector &mcTargetPosition(
788 (m_testBeamMode && std::fabs(pMCTarget->GetParticleId()) == 11) ? pMCTarget->GetVertex() : pMCTarget->GetEndpoint());
789 const CartesianVector mcTargetCorrectedPosition(
790 mcTargetPosition.GetX() + m_mcVertexXCorrection, mcTargetPosition.GetY(), mcTargetPosition.GetZ());
791 const float dr = (mcTargetCorrectedPosition - pVertex->GetPosition()).GetMagnitude();
792
793 if (dr < mcVertexDr)
794 mcVertexDr = dr;
795 }
796
797 if (mcVertexDr < bestVertexDr)
798 {
799 bestVertexDr = mcVertexDr;
800 pBestVertex = pVertex;
801 }
802 }
803}
804
805//------------------------------------------------------------------------------------------------------------------------------------------
806
808 const VertexFeatureInfo &vertexFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector, const bool useRPhi) const
809{
810 if (this->IsBeamModeOn())
811 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_beamDeweighting));
812 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_energyKick));
813 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_globalAsymmetry));
814 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_localAsymmetry));
815 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_showerAsymmetry));
816
818 {
819 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_dEdxAsymmetry));
820 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_vertexEnergy));
821 }
822
823 if (useRPhi)
824 featureVector.push_back(static_cast<double>(vertexFeatureInfo.m_rPhiFeature));
825}
826
827//------------------------------------------------------------------------------------------------------------------------------------------
828
830 const VertexSharedFeatureInfo &vertexSharedFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector) const
831{
832 featureVector.push_back(static_cast<double>(vertexSharedFeatureInfo.m_separation));
833 featureVector.push_back(static_cast<double>(vertexSharedFeatureInfo.m_axisHits));
834}
835
836//------------------------------------------------------------------------------------------------------------------------------------------
837
839 const Vertex *const pFavouriteVertex, const VertexVector &vertexVector, VertexScoreList &finalVertexScoreList) const
840{
841 if (pFavouriteVertex)
842 {
843 const CartesianVector vertexPosition(pFavouriteVertex->GetPosition());
844
845 for (const Vertex *const pVertex : vertexVector)
846 {
847 if ((pVertex->GetPosition() - vertexPosition).GetMagnitude() < m_rPhiFineTuningRadius)
848 {
849 const float rPhiScore(vertexFeatureInfoMap.at(pVertex).m_rPhiFeature);
850 finalVertexScoreList.emplace_back(pVertex, rPhiScore);
851 }
852 }
853 }
854}
855
856//------------------------------------------------------------------------------------------------------------------------------------------
857//------------------------------------------------------------------------------------------------------------------------------------------
858
860{
861 AlgorithmToolVector algorithmToolVector;
862 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*this, xmlHandle, "FeatureTools", algorithmToolVector));
863
864 for (AlgorithmTool *const pAlgorithmTool : algorithmToolVector)
866
867 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingSetMode", m_trainingSetMode));
868
869 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
870 XmlHelper::ReadValue(xmlHandle, "AllowClassifyDuringTraining", m_allowClassifyDuringTraining));
871
873 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MCVertexXCorrection", m_mcVertexXCorrection));
874
875 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
876 XmlHelper::ReadValue(xmlHandle, "TrainingOutputFileRegion", m_trainingOutputFileRegion));
877
878 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
879 XmlHelper::ReadValue(xmlHandle, "TrainingOutputFileVertex", m_trainingOutputFileVertex));
880
882 {
883 std::cout << "TrainedVertexSelectionAlgorithm: TrainingOutputFileRegion and TrainingOutputFileVertex are required for training set "
884 << "mode" << std::endl;
885 return STATUS_CODE_INVALID_PARAMETER;
886 }
887
889 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MCParticleListName", m_mcParticleListName));
890
891 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListName", m_caloHitListName));
892
893 if (m_trainingSetMode && (m_mcParticleListName.empty() || m_caloHitListName.empty()))
894 {
895 std::cout << "TrainedVertexSelectionAlgorithm: MCParticleListName and CaloHitListName are required for training set mode" << std::endl;
896 return STATUS_CODE_INVALID_PARAMETER;
897 }
898
899 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputClusterListNames", m_inputClusterListNames));
900
902 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterCaloHits", m_minClusterCaloHits));
903
905 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
906
908 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinShowerSpineLength", m_minShowerSpineLength));
909
910 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
911 XmlHelper::ReadValue(xmlHandle, "BeamDeweightingConstant", m_beamDeweightingConstant));
912
914 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LocalAsymmetryConstant", m_localAsymmetryConstant));
915
916 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
917 XmlHelper::ReadValue(xmlHandle, "GlobalAsymmetryConstant", m_globalAsymmetryConstant));
918
919 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
920 XmlHelper::ReadValue(xmlHandle, "ShowerAsymmetryConstant", m_showerAsymmetryConstant));
921
923 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "EnergyKickConstant", m_energyKickConstant));
924
925 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
926 XmlHelper::ReadValue(xmlHandle, "ShowerClusteringDistance", m_showerClusteringDistance));
927
929 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinShowerClusterHits", m_minShowerClusterHits));
930
931 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
932 XmlHelper::ReadValue(xmlHandle, "UseShowerClusteringApproximation", m_useShowerClusteringApproximation));
933
934 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "RegionRadius", m_regionRadius));
935
937 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "RPhiFineTuningRadius", m_rPhiFineTuningRadius));
938
940 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxTrueVertexRadius", m_maxTrueVertexRadius));
941
942 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
943 XmlHelper::ReadValue(xmlHandle, "UseRPhiFeatureForRegion", m_useRPhiFeatureForRegion));
944
945 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
946 XmlHelper::ReadValue(xmlHandle, "DropFailedRPhiFastScoreCandidates", m_dropFailedRPhiFastScoreCandidates));
947
948 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TestBeamMode", m_testBeamMode));
949
951 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LegacyEventShapes", m_legacyEventShapes));
952
953 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LegacyVariables", m_legacyVariables));
954
956 std::cout << "TrainedVertexSelectionAlgorithm: WARNING -- Producing training sample using incorrect legacy event shapes, consider turning LegacyEventShapes off"
957 << std::endl;
958
960}
961
962} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the energy deposition asymmetry feature tool class.
Header file for the energy kick feature tool class.
Header file for the global asymmetry feature tool class.
Header file for the kd tree linker algo template class.
Header file for the cluster helper class.
Header file for the file helper class.
Header file for the geometry helper class.
Header file for the interaction type helper class.
Header file for the lar monte carlo particle helper helper class.
Header file for the local asymmetry feature tool class.
Header file for the r/phi feature tool class.
Header file for the shower asymmetry feature tool class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:19
Header file for the trained vertex selection algorithm class.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
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".
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...
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)
static float GetLength(const pandora::Cluster *const pCluster)
Get length of cluster.
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.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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 InteractionType GetInteractionType(const pandora::MCParticleList &mcPrimaryList)
Get the interaction type of an event.
static std::string ToString(const InteractionType interactionType)
Get a string representation of an interaction type.
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
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.
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
static bool IsTriggeredBeamParticle(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary triggered beam MCParticle.
static void GetTrueTestBeamParticles(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &trueTestBeamParticles)
Get triggered test beam MC particles from an input MC particle list.
static void GetTrueNeutrinos(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &trueNeutrinos)
Get neutrino MC particles from an input MC particle list.
static bool IsBeamNeutrinoFinalState(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary neutrino final state MCParticle.
MvaTypes::MvaFeatureVector MvaFeatureVector
static MvaFeatureVector ConcatenateFeatureLists()
Recursively concatenate vectors of features (terminating method)
static pandora::StatusCode AddFeatureToolToVector(pandora::AlgorithmTool *const pFeatureTool, MvaFeatureToolVector< Ts... > &featureToolVector)
Add a feature tool to a vector of feature tools.
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer)
Produce a training example with the given features and result.
float m_axisHits
The hit density along the axis between the two vertices.
float m_showerAsymmetryConstant
The shower asymmetry constant for the initial region score list.
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.
bool m_legacyVariables
Whether to only use the old variables.
void AddEventFeaturesToVector(const EventFeatureInfo &eventFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector) const
Add the event features to a vector in the correct order.
EventFeatureInfo CalculateEventFeatures(const pandora::ClusterList &clusterListU, const pandora::ClusterList &clusterListV, const pandora::ClusterList &clusterListW, const pandora::VertexVector &vertexVector) const
Calculate the event parameters.
float m_rPhiFineTuningRadius
The maximum distance the r/phi tune can move a vertex.
float m_showerClusteringDistance
The shower clustering distance.
pandora::StringVector m_inputClusterListNames
The list of cluster list names.
void IncrementShoweryParameters(const pandora::ClusterList &clusterList, unsigned int &nShoweryHits, unsigned int &nHits, float &eventEnergy) const
Increment the showery hit parameters for a cluster list.
bool IsClusterShowerLike(const pandora::Cluster *const pCluster) const
Find whether a cluster is shower-like.
unsigned int m_minClusterCaloHits
The min number of hits parameter in the energy score.
void IncrementSharedAxisValues(const pandora::CartesianVector pos1, const pandora::CartesianVector pos2, HitKDTree2D &kdTree, float &axisHits) const
Increments the axis hits information for one view.
float GetCoordinateSpan(const pandora::InputFloat &minCoord, const pandora::InputFloat &maxCoord) const
Get the coordinate span.
bool m_legacyEventShapes
Whether to use the old event shapes calculation.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
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.
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.
void GetBestRegionVertices(VertexScoreList &initialScoreList, pandora::VertexVector &bestRegionVertices) const
Get the list of top-N separated vertices.
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.
std::string m_mcParticleListName
The MC particle list for creating training examples.
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...
void AddVertexFeaturesToVector(const VertexFeatureInfo &vertexFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector, const bool useRPhi) const
Add the vertex features to a vector in the correct order.
VertexFeatureTool::FeatureToolVector m_featureToolVector
The feature tool vector.
void UpdateSpanCoordinate(const float minPositionCoord, const float maxPositionCoord, pandora::InputFloat &minCoord, pandora::InputFloat &maxCoord) const
Update the min/max coordinate spans.
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
std::string GetInteractionType() const
Get the interaction type string.
bool m_useShowerClusteringApproximation
Whether to use the shower clustering distance approximation.
void GetLegacyEventShapeFeatures(const pandora::ClusterList &clusterList, float &eventVolume, float &longitudinality) const
Get the event shape features.
std::pair< pandora::CartesianVector, pandora::CartesianVector > ClusterEndPoints
float m_globalAsymmetryConstant
The global asymmetry constant for the initial region score list.
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.
void GetShowerLikeClusterEndPoints(const pandora::ClusterList &clusterList, pandora::ClusterList &showerLikeClusters, ClusterEndPointsMap &clusterEndPointsMap) const
Add the endpoints of any shower-like clusters to the map.
std::unordered_map< const pandora::CaloHit *, const pandora::Cluster * > HitToClusterMap
std::map< const pandora::Vertex *const, VertexFeatureInfo > VertexFeatureInfoMap
std::string m_trainingOutputFileRegion
The training output file for the region mva.
void AddSharedFeaturesToVector(const VertexSharedFeatureInfo &vertexSharedFeatureInfo, LArMvaHelper::MvaFeatureVector &featureVector) const
Add the shared features to a vector in the correct order.
void CalculateShowerClusterList(const pandora::ClusterList &inputClusterList, ShowerClusterList &showerClusterList) const
Calculate the shower cluster map for a cluster list.
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.
std::map< const pandora::Cluster *const, ClusterEndPoints > ClusterEndPointsMap
float m_mcVertexXCorrection
The correction to the x-coordinate of the MC vertex position.
float m_maxTrueVertexRadius
The maximum distance at which a vertex candidate can be considered the 'true' vertex.
bool m_useRPhiFeatureForRegion
Whether to use the r/phi feature for the region vertex.
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.
void PopulateKdTree(const pandora::ClusterList &clusterList, HitKDTree2D &kdTree, HitToClusterMap &hitToClusterMap) const
Populate kd tree with information about hits in a provided list of clusters.
std::string m_trainingOutputFileVertex
The training output file for the vertex mva.
float m_minShowerSpineLength
The minimum length at which all are considered to be tracks.
float m_localAsymmetryConstant
The local asymmetry constant for the initial region score list.
bool m_allowClassifyDuringTraining
Whether classification is allowed during training.
bool m_dropFailedRPhiFastScoreCandidates
Whether to drop candidates that fail the r/phi fast score test.
void PopulateInitialScoreList(VertexFeatureInfoMap &vertexFeatureInfoMap, const pandora::Vertex *const pVertex, VertexScoreList &initialScoreList) const
Populate the initial vertex score list for a given vertex.
float m_energyKickConstant
The energy kick constant for the initial region score list.
unsigned int m_minShowerClusterHits
The minimum number of shower cluster hits.
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.
float m_beamDeweightingConstant
The beam deweighting constant for the initial region score list.
void GetEventShapeFeatures(const ClusterListMap &clusterListMap, float &eventArea, float &longitudinality) const
Get the event shape features.
void Get2DSpan(const pandora::ClusterList &clusterList, float &xSpan, float &zSpan) const
Get the coordinate span in one view.
std::map< pandora::HitType, const SlidingFitDataList > SlidingFitDataListMap
Map of sliding fit data lists for passing to tools.
std::map< pandora::HitType, const pandora::ClusterList & > ClusterListMap
Map array of cluster lists for passing to tools.
std::map< pandora::HitType, const std::reference_wrapper< HitKDTree2D > > KDTreeMap
Map array of hit kd trees for passing to tools.
float GetBeamDeweightingScore(const BeamConstants &beamConstants, const pandora::Vertex *const pVertex) const
Get the beam deweighting score for a vertex.
std::map< pandora::HitType, const ShowerClusterList > ShowerClusterListMap
Map of shower cluster 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.
bool IsBeamModeOn() const
Whether algorithm is running in beam mode, assuming neutrinos travel in positive z-direction.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
AlgorithmTool class. Algorithm tools will tend to be tailored for specific parent algorithms,...
CaloHit class.
Definition CaloHit.h:26
CartesianVector class.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetY() const
Get the cartesian y coordinate.
Cluster class.
Definition Cluster.h:31
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
Definition Cluster.h:470
int GetParticleId() const
Get the particle id flag.
Definition Cluster.h:547
MCParticle class.
Definition MCParticle.h:26
Calo hit lists arranged by pseudo layer.
const_iterator end() const
Returns a const iterator referring to the past-the-end element in the ordered calo hit list.
const_iterator begin() const
Returns a const iterator referring to the first element in the ordered calo hit list.
TheList::const_iterator const_iterator
void FillCaloHitList(CaloHitList &caloHitList) const
Fill a provided calo hit list with all the calo hits in the ordered calo hit list.
bool IsInitialized() const
Whether the pandora type is initialized.
const T & Get() const
Get the value held by the pandora type.
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
Vertex class.
Definition Vertex.h:26
const CartesianVector & GetPosition() const
Get the vertex position.
Definition Vertex.h:103
static StatusCode ReadVectorOfValues(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, std::vector< T > &vector)
Read a vector of values from a (space separated) list in an xml element.
Definition XmlHelper.h:229
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
static StatusCode ProcessAlgorithmToolList(const Algorithm &algorithm, const TiXmlHandle &xmlHandle, const std::string &listName, AlgorithmToolVector &algorithmToolVector)
Process a list of algorithms tools in an xml file.
Definition XmlHelper.cc:101
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
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
MANAGED_CONTAINER< const MCParticle * > MCParticleList
std::vector< const CaloHit * > CaloHitVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< AlgorithmTool * > AlgorithmToolVector
std::unordered_set< const Cluster * > ClusterSet
MANAGED_CONTAINER< const CaloHit * > CaloHitList
std::vector< float > FloatVector
std::vector< const MCParticle * > MCParticleVector
StatusCode
The StatusCode enum.
std::vector< const Vertex * > VertexVector