LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
BdtBeamParticleIdTool.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
17 
18 using namespace pandora;
19 
20 namespace lar_content
21 {
22 
23 BdtBeamParticleIdTool::BdtBeamParticleIdTool() :
24  m_useTrainingMode(false),
25  m_trainingOutputFile(""),
26  m_minPurity(0.8f),
27  m_minCompleteness(0.8f),
28  m_adaBoostDecisionTree(AdaBoostDecisionTree()),
29  m_filePathEnvironmentVariable("FW_SEARCH_PATH"),
30  m_maxNeutrinos(std::numeric_limits<int>::max()),
31  m_minAdaBDTScore(0.f),
32  m_sliceFeatureParameters(SliceFeatureParameters())
33 {
34 }
35 
36 //------------------------------------------------------------------------------------------------------------------------------------------
37 
39 {
40  // Get global LArTPC geometry information
41  const LArTPCMap &larTPCMap(this->GetPandora().GetGeometry()->GetLArTPCMap());
42  const LArTPC *const pFirstLArTPC(larTPCMap.begin()->second);
43  float parentMinX(pFirstLArTPC->GetCenterX() - 0.5f * pFirstLArTPC->GetWidthX());
44  float parentMaxX(pFirstLArTPC->GetCenterX() + 0.5f * pFirstLArTPC->GetWidthX());
45  float parentMinY(pFirstLArTPC->GetCenterY() - 0.5f * pFirstLArTPC->GetWidthY());
46  float parentMaxY(pFirstLArTPC->GetCenterY() + 0.5f * pFirstLArTPC->GetWidthY());
47  float parentMinZ(pFirstLArTPC->GetCenterZ() - 0.5f * pFirstLArTPC->GetWidthZ());
48  float parentMaxZ(pFirstLArTPC->GetCenterZ() + 0.5f * pFirstLArTPC->GetWidthZ());
49 
50  for (const LArTPCMap::value_type &mapEntry : larTPCMap)
51  {
52  const LArTPC *const pLArTPC(mapEntry.second);
53  parentMinX = std::min(parentMinX, pLArTPC->GetCenterX() - 0.5f * pLArTPC->GetWidthX());
54  parentMaxX = std::max(parentMaxX, pLArTPC->GetCenterX() + 0.5f * pLArTPC->GetWidthX());
55  parentMinY = std::min(parentMinY, pLArTPC->GetCenterY() - 0.5f * pLArTPC->GetWidthY());
56  parentMaxY = std::max(parentMaxY, pLArTPC->GetCenterY() + 0.5f * pLArTPC->GetWidthY());
57  parentMinZ = std::min(parentMinZ, pLArTPC->GetCenterZ() - 0.5f * pLArTPC->GetWidthZ());
58  parentMaxZ = std::max(parentMaxZ, pLArTPC->GetCenterZ() + 0.5f * pLArTPC->GetWidthZ());
59  }
60 
61  try
62  {
63  m_sliceFeatureParameters.Initialize(parentMinX, parentMaxX, parentMinY, parentMaxY, parentMinZ, parentMaxZ);
64  }
65  catch (const StatusCodeException &statusCodeException)
66  {
67  std::cout << "BdtBeamParticleIdTool::Initialize - unable to initialize LArTPC geometry parameters" << std::endl;
68  return STATUS_CODE_FAILURE;
69  }
70 
71  return STATUS_CODE_SUCCESS;
72 }
73 
74 //------------------------------------------------------------------------------------------------------------------------------------------
75 
76 void BdtBeamParticleIdTool::SelectOutputPfos(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses,
77  const SliceHypotheses &crSliceHypotheses, PfoList &selectedPfos)
78 {
79  if (nuSliceHypotheses.size() != crSliceHypotheses.size())
80  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
81 
82  const unsigned int nSlices(nuSliceHypotheses.size());
83  if (nSlices == 0)
84  return;
85 
86  SliceFeaturesVector sliceFeaturesVector;
87  this->GetSliceFeatures(nuSliceHypotheses, crSliceHypotheses, sliceFeaturesVector);
88 
90  {
91  // ATTN in training mode, just return everything as a cosmic-ray
92  this->SelectAllPfos(pAlgorithm, crSliceHypotheses, selectedPfos);
93 
94  pandora::IntVector bestSliceIndices;
95  this->GetBestMCSliceIndices(pAlgorithm, nuSliceHypotheses, crSliceHypotheses, bestSliceIndices);
96 
97  for (unsigned int sliceIndex = 0; sliceIndex < nSlices; ++sliceIndex)
98  {
99  const SliceFeatures &features(sliceFeaturesVector.at(sliceIndex));
100  if (!features.IsFeatureVectorAvailable())
101  continue;
102 
103  LArMvaHelper::MvaFeatureVector featureVector;
104 
105  try
106  {
107  features.FillFeatureVector(featureVector);
108  }
109  catch (const StatusCodeException &statusCodeException)
110  {
111  std::cout << "BdtBeamParticleIdTool::SelectOutputPfos - unable to fill feature vector" << std::endl;
112  continue;
113  }
114 
115  bool isGoodTrainingSlice(false);
116  if (std::find(bestSliceIndices.begin(), bestSliceIndices.end(), sliceIndex) != bestSliceIndices.end())
117  isGoodTrainingSlice = true;
118 
119  LArMvaHelper::ProduceTrainingExample(m_trainingOutputFile, isGoodTrainingSlice, featureVector);
120  }
121 
122  return;
123  }
124 
125  this->SelectPfosByAdaBDTScore(pAlgorithm, nuSliceHypotheses, crSliceHypotheses, sliceFeaturesVector, selectedPfos);
126 }
127 
128 //------------------------------------------------------------------------------------------------------------------------------------------
129 
131  const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, SliceFeaturesVector &sliceFeaturesVector) const
132 {
133  for (unsigned int sliceIndex = 0, nSlices = nuSliceHypotheses.size(); sliceIndex < nSlices; ++sliceIndex)
134  sliceFeaturesVector.push_back(SliceFeatures(nuSliceHypotheses.at(sliceIndex), crSliceHypotheses.at(sliceIndex), m_sliceFeatureParameters));
135 }
136 
137 //------------------------------------------------------------------------------------------------------------------------------------------
138 
139 void BdtBeamParticleIdTool::SelectAllPfos(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &hypotheses, PfoList &selectedPfos) const
140 {
141  for (const PfoList &pfos : hypotheses)
142  {
143  for (const ParticleFlowObject *const pPfo : pfos)
144  {
145  object_creation::ParticleFlowObject::Metadata metadata;
146  metadata.m_propertiesToAdd["TestBeamScore"] = -1.f;
147  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*pAlgorithm, pPfo, metadata));
148  }
149 
150  this->SelectPfos(pfos, selectedPfos);
151  }
152 }
153 
154 //------------------------------------------------------------------------------------------------------------------------------------------
155 
156 void BdtBeamParticleIdTool::SelectPfos(const PfoList &pfos, PfoList &selectedPfos) const
157 {
158  selectedPfos.insert(selectedPfos.end(), pfos.begin(), pfos.end());
159 }
160 
161 //------------------------------------------------------------------------------------------------------------------------------------------
162 
163 void BdtBeamParticleIdTool::GetBestMCSliceIndices(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses,
164  const SliceHypotheses &crSliceHypotheses, pandora::IntVector &bestSliceIndices) const
165 {
166  // Get all hits in all slices to find true number of mc hits
167  const CaloHitList *pAllReconstructedCaloHitList(nullptr);
168  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*pAlgorithm, m_caloHitListName, pAllReconstructedCaloHitList));
169 
170  const MCParticleList *pMCParticleList(nullptr);
171  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*pAlgorithm, m_mcParticleListName, pMCParticleList));
172 
173  // Obtain map: [mc particle -> primary mc particle]
174  LArMCParticleHelper::MCRelationMap mcToPrimaryMCMap;
175  LArMCParticleHelper::GetMCPrimaryMap(pMCParticleList, mcToPrimaryMCMap);
176 
177  // Remove non-reconstructable hits, e.g. those downstream of a neutron
178  CaloHitList reconstructableCaloHitList;
180  LArMCParticleHelper::SelectCaloHits(pAllReconstructedCaloHitList, mcToPrimaryMCMap, reconstructableCaloHitList,
181  parameters.m_selectInputHits, parameters.m_maxPhotonPropagation);
182 
183  MCParticleToIntMap mcParticleToReconstructableHitsMap;
184  this->PopulateMCParticleToHitsMap(mcParticleToReconstructableHitsMap, reconstructableCaloHitList);
185 
186  const CaloHitSet reconstructableCaloHitSet(reconstructableCaloHitList.begin(), reconstructableCaloHitList.end());
187 
188  for (unsigned int sliceIndex = 0, nSlices = nuSliceHypotheses.size(); sliceIndex < nSlices; ++sliceIndex)
189  {
190  // All hits in a slice - No double counting
191  CaloHitList reconstructedCaloHitList;
192  this->Collect2DHits(crSliceHypotheses.at(sliceIndex), reconstructedCaloHitList, reconstructableCaloHitSet);
193 
194  if (nuSliceHypotheses.at(sliceIndex).size() == 1)
195  {
196  const PfoList &nuFinalStates(nuSliceHypotheses.at(sliceIndex).front()->GetDaughterPfoList());
197  this->Collect2DHits(nuFinalStates, reconstructedCaloHitList, reconstructableCaloHitSet);
198  }
199 
200  const unsigned int nRecoHits(reconstructedCaloHitList.size());
201 
202  // MCParticle to hits in slice map
203  MCParticleToIntMap mcParticleToHitsInSliceMap;
204  this->PopulateMCParticleToHitsMap(mcParticleToHitsInSliceMap, reconstructedCaloHitList);
205 
206  if (mcParticleToHitsInSliceMap.empty())
207  continue;
208 
209  // Get best mc particle for slice
210  const MCParticle *pBestMCParticle(nullptr);
211  unsigned int nSharedHits(0);
212 
213  for (const auto &iter : mcParticleToHitsInSliceMap)
214  {
215  if (iter.second > static_cast<int>(nSharedHits))
216  {
217  pBestMCParticle = iter.first;
218  nSharedHits = iter.second;
219  }
220  }
221 
222  // Only consider if target beam particles
223  if (2001 != LArMCParticleHelper::GetNuanceCode(pBestMCParticle))
224  continue;
225 
226  const unsigned int nMCHits(mcParticleToReconstructableHitsMap.at(pBestMCParticle));
227  const float purity(nRecoHits > 0 ? static_cast<float>(nSharedHits) / static_cast<float>(nRecoHits) : 0.f);
228  const float completeness(nMCHits > 0 ? static_cast<float>(nSharedHits) / static_cast<float>(nMCHits) : 0.f);
229 
230  if (this->PassesQualityCuts(purity, completeness))
231  bestSliceIndices.push_back(sliceIndex);
232  }
233  return;
234 }
235 
236 //------------------------------------------------------------------------------------------------------------------------------------------
237 
238 void BdtBeamParticleIdTool::PopulateMCParticleToHitsMap(MCParticleToIntMap &mcParticleToIntMap, const pandora::CaloHitList &caloHitList) const
239 {
240  for (const CaloHit *const pCaloHit : caloHitList)
241  {
242  try
243  {
244  const MCParticle *pParentMCParticle(LArMCParticleHelper::GetParentMCParticle(MCParticleHelper::GetMainMCParticle(pCaloHit)));
245  MCParticleToIntMap::iterator iter(mcParticleToIntMap.find(pParentMCParticle));
246 
247  if (iter != mcParticleToIntMap.end())
248  {
249  (*iter).second += 1;
250  }
251  else
252  {
253  mcParticleToIntMap.insert(MCParticleToIntMap::value_type(pParentMCParticle, 1));
254  }
255  }
256  catch (const StatusCodeException &statusCodeException)
257  {
258  if (STATUS_CODE_NOT_INITIALIZED != statusCodeException.GetStatusCode())
259  throw statusCodeException;
260  }
261  }
262 }
263 
264 //------------------------------------------------------------------------------------------------------------------------------------------
265 
266 void BdtBeamParticleIdTool::Collect2DHits(const PfoList &pfos, CaloHitList &reconstructedCaloHitList, const CaloHitSet &reconstructableCaloHitSet) const
267 {
268  CaloHitList collectedHits;
269  LArPfoHelper::GetCaloHits(pfos, TPC_VIEW_U, collectedHits);
270  LArPfoHelper::GetCaloHits(pfos, TPC_VIEW_V, collectedHits);
271  LArPfoHelper::GetCaloHits(pfos, TPC_VIEW_W, collectedHits);
272 
273  for (const CaloHit *const pCaloHit : collectedHits)
274  {
275  // ATTN hits collected from Pfos are copies of hits passed from master instance, we need to access their parent to use MC info
276  const CaloHit *pParentCaloHit(static_cast<const CaloHit *>(pCaloHit->GetParentAddress()));
277 
278  if (!reconstructableCaloHitSet.count(pParentCaloHit))
279  continue;
280 
281  // Ensure no hits have been double counted
282  if (std::find(reconstructedCaloHitList.begin(), reconstructedCaloHitList.end(), pParentCaloHit) == reconstructedCaloHitList.end())
283  reconstructedCaloHitList.push_back(pParentCaloHit);
284  }
285 }
286 
287 //------------------------------------------------------------------------------------------------------------------------------------------
288 
289 bool BdtBeamParticleIdTool::PassesQualityCuts(const float purity, const float completeness) const
290 {
291  if ((purity < m_minPurity) || (completeness < m_minCompleteness))
292  return false;
293 
294  return true;
295 }
296 
297 //------------------------------------------------------------------------------------------------------------------------------------------
298 
299 void BdtBeamParticleIdTool::SelectPfosByAdaBDTScore(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses,
300  const SliceHypotheses &crSliceHypotheses, const SliceFeaturesVector &sliceFeaturesVector, PfoList &selectedPfos) const
301 {
302  // Calculate the probability of each slice that passes the minimum probability cut
303  std::vector<UintFloatPair> sliceIndexAdaBDTScorePairs;
304  for (unsigned int sliceIndex = 0, nSlices = nuSliceHypotheses.size(); sliceIndex < nSlices; ++sliceIndex)
305  {
306  const float nuAdaBDTScore(sliceFeaturesVector.at(sliceIndex).GetAdaBoostDecisionTreeScore(m_adaBoostDecisionTree));
307 
308  for (const ParticleFlowObject *const pPfo : crSliceHypotheses.at(sliceIndex))
309  {
310  object_creation::ParticleFlowObject::Metadata metadata;
311  metadata.m_propertiesToAdd["TestBeamScore"] = nuAdaBDTScore;
312  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*pAlgorithm, pPfo, metadata));
313  }
314 
315  for (const ParticleFlowObject *const pPfo : nuSliceHypotheses.at(sliceIndex))
316  {
317  object_creation::ParticleFlowObject::Metadata metadata;
318  metadata.m_propertiesToAdd["TestBeamScore"] = nuAdaBDTScore;
319  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::AlterMetadata(*pAlgorithm, pPfo, metadata));
320  }
321 
322  if (nuAdaBDTScore < m_minAdaBDTScore)
323  {
324  this->SelectPfos(crSliceHypotheses.at(sliceIndex), selectedPfos);
325  continue;
326  }
327 
328  sliceIndexAdaBDTScorePairs.push_back(UintFloatPair(sliceIndex, nuAdaBDTScore));
329  }
330 
331  // Sort the slices by probability
332  std::sort(sliceIndexAdaBDTScorePairs.begin(), sliceIndexAdaBDTScorePairs.end(),
333  [](const UintFloatPair &a, const UintFloatPair &b) { return (a.second > b.second); });
334 
335  // Select the first m_maxNeutrinos as neutrinos, and the rest as cosmic
336  unsigned int nNuSlices(0);
337  for (const UintFloatPair &slice : sliceIndexAdaBDTScorePairs)
338  {
339  if (nNuSlices < m_maxNeutrinos)
340  {
341  this->SelectPfos(nuSliceHypotheses.at(slice.first), selectedPfos);
342  nNuSlices++;
343  continue;
344  }
345 
346  this->SelectPfos(crSliceHypotheses.at(slice.first), selectedPfos);
347  }
348 }
349 
350 //------------------------------------------------------------------------------------------------------------------------------------------
351 //------------------------------------------------------------------------------------------------------------------------------------------
352 
353 BdtBeamParticleIdTool::Plane::Plane(const CartesianVector &normal, const CartesianVector &point) :
354  m_unitNormal(0.f, 0.f, 0.f),
355  m_point(point),
356  m_d(-1. * static_cast<double>(normal.GetDotProduct(point)))
357 {
358  try
359  {
360  m_unitNormal = normal.GetUnitVector();
361  }
362  catch (const StatusCodeException &statusCodeException)
363  {
364  std::cout << "BdtBeamParticleIdTool::Plane::Plane - normal vector to plane has a magnitude of zero" << std::endl;
365  throw statusCodeException;
366  }
367 }
368 
369 //------------------------------------------------------------------------------------------------------------------------------------------
370 
371 CartesianVector BdtBeamParticleIdTool::Plane::GetLineIntersection(const CartesianVector &point, const CartesianVector &direction) const
372 {
373  if (std::fabs(direction.GetDotProduct(m_unitNormal)) < std::numeric_limits<float>::epsilon())
374  return CartesianVector(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
375 
376  const float denominator(direction.GetDotProduct(m_unitNormal));
377 
378  if (std::fabs(denominator) < std::numeric_limits<float>::epsilon())
379  throw StatusCodeException(STATUS_CODE_OUT_OF_RANGE);
380 
381  const double t(-1. * (static_cast<double>(point.GetDotProduct(m_unitNormal)) + m_d) / static_cast<double>(denominator));
382  return (point + (direction * t));
383 }
384 
385 //------------------------------------------------------------------------------------------------------------------------------------------
386 //------------------------------------------------------------------------------------------------------------------------------------------
387 
389  m_larTPCMinX(std::numeric_limits<float>::max()),
390  m_larTPCMaxX(std::numeric_limits<float>::max()),
391  m_larTPCMinY(std::numeric_limits<float>::max()),
392  m_larTPCMaxY(std::numeric_limits<float>::max()),
393  m_larTPCMinZ(std::numeric_limits<float>::max()),
394  m_larTPCMaxZ(std::numeric_limits<float>::max()),
395  m_beamLArTPCIntersection(0.f, 0.f, 0.f),
396  m_beamDirection(0.f, 0.f, 0.f),
397  m_selectedFraction(10.f),
398  m_nSelectedHits(100),
399  m_containmentLimit(0.01f)
400 {
401 }
402 
403 //------------------------------------------------------------------------------------------------------------------------------------------
404 
405 void BdtBeamParticleIdTool::SliceFeatureParameters::Initialize(const float larTPCMinX, const float larTPCMaxX, const float larTPCMinY,
406  const float larTPCMaxY, const float larTPCMinZ, const float larTPCMaxZ)
407 {
408  m_larTPCMinX = larTPCMinX;
409  m_larTPCMaxX = larTPCMaxX;
410  m_larTPCMinY = larTPCMinY;
411  m_larTPCMaxY = larTPCMaxY;
412  m_larTPCMinZ = larTPCMinZ;
413  m_larTPCMaxZ = larTPCMaxZ;
414 
415  const CartesianVector normalTop(0.f, 0.f, 1.f), pointTop(0.f, 0.f, m_larTPCMaxZ);
416  const CartesianVector normalBottom(0.f, 0.f, -1.f), pointBottom(0.f, 0.f, m_larTPCMinZ);
417  const CartesianVector normalRight(1.f, 0.f, 0.f), pointRight(m_larTPCMaxX, 0.f, 0.f);
418  const CartesianVector normalLeft(-1.f, 0.f, 0.f), pointLeft(m_larTPCMinX, 0.f, 0.f);
419  const CartesianVector normalBack(0.f, 1.f, 0.f), pointBack(0.f, m_larTPCMaxY, 0.f);
420  const CartesianVector normalFront(0.f, -1.f, 0.f), pointFront(0.f, m_larTPCMinY, 0.f);
421 
422  m_larTPCPlanes.emplace_back(normalTop, pointTop);
423  m_larTPCPlanes.emplace_back(normalBottom, pointBottom);
424  m_larTPCPlanes.emplace_back(normalRight, pointRight);
425  m_larTPCPlanes.emplace_back(normalLeft, pointLeft);
426  m_larTPCPlanes.emplace_back(normalBack, pointBack);
427  m_larTPCPlanes.emplace_back(normalFront, pointFront);
428 }
429 
430 //------------------------------------------------------------------------------------------------------------------------------------------
431 //------------------------------------------------------------------------------------------------------------------------------------------
432 
433 BdtBeamParticleIdTool::SliceFeatures::SliceFeatures(const PfoList &pfosNu, const PfoList &pfosCr, const SliceFeatureParameters &sliceFeatureParameters) :
434  m_isAvailable(false),
435  m_sliceFeatureParameters(sliceFeatureParameters)
436 {
437  try
438  {
439  double closestDistanceNu(std::numeric_limits<double>::max()), closestDistanceCr(std::numeric_limits<double>::max()),
440  supplementaryAngleToBeamNu(std::numeric_limits<double>::max()), supplementaryAngleToBeamCr(std::numeric_limits<double>::max()),
441  separationNu(std::numeric_limits<double>::max()), separationCr(std::numeric_limits<double>::max());
442  ;
443  CaloHitList caloHitList3DNu, caloHitList3DCr, selectedCaloHitListNu, selectedCaloHitListCr;
444  PfoList allConnectedPfoListNu, allConnectedPfoListCr;
445  LArPcaHelper::EigenValues eigenValuesNu(0.f, 0.f, 0.f);
446  LArPcaHelper::EigenValues eigenValuesCr(0.f, 0.f, 0.f);
447 
448  LArPfoHelper::GetAllConnectedPfos(pfosNu, allConnectedPfoListNu);
449  LArPfoHelper::GetAllConnectedPfos(pfosCr, allConnectedPfoListCr);
450  LArPfoHelper::GetCaloHits(allConnectedPfoListNu, TPC_3D, caloHitList3DNu);
451  LArPfoHelper::GetCaloHits(allConnectedPfoListCr, TPC_3D, caloHitList3DCr);
452 
453  this->GetLeadingCaloHits(caloHitList3DNu, selectedCaloHitListNu, closestDistanceNu);
454  this->GetLeadingCaloHits(caloHitList3DCr, selectedCaloHitListCr, closestDistanceCr);
455 
456  if (!selectedCaloHitListNu.empty() && !selectedCaloHitListCr.empty())
457  {
458  float maxYNu(-std::numeric_limits<float>::max()), maxYCr(-std::numeric_limits<float>::max());
459  CartesianVector centroidNu(0.f, 0.f, 0.f), interceptOneNu(0.f, 0.f, 0.f), interceptTwoNu(0.f, 0.f, 0.f),
460  centroidCr(0.f, 0.f, 0.f), interceptOneCr(0.f, 0.f, 0.f), interceptTwoCr(0.f, 0.f, 0.f);
461 
462  // Beam
463  LArPcaHelper::EigenVectors eigenVecsNu;
464  LArPcaHelper::RunPca(selectedCaloHitListNu, centroidNu, eigenValuesNu, eigenVecsNu);
465  const CartesianVector &majorAxisNu(eigenVecsNu.front());
466  supplementaryAngleToBeamNu = majorAxisNu.GetOpeningAngle(m_sliceFeatureParameters.GetBeamDirection());
467 
468  this->GetLArTPCIntercepts(centroidNu, majorAxisNu, interceptOneNu, interceptTwoNu);
469  const double separationOneNu((interceptOneNu - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
470  const double separationTwoNu((interceptTwoNu - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
471  separationNu = std::min(separationOneNu, separationTwoNu);
472 
473  // Cosmic
474  LArPcaHelper::EigenVectors eigenVecsCr;
475  LArPcaHelper::RunPca(selectedCaloHitListCr, centroidCr, eigenValuesCr, eigenVecsCr);
476  const CartesianVector &majorAxisCr(eigenVecsCr.front());
477  supplementaryAngleToBeamCr = majorAxisCr.GetOpeningAngle(m_sliceFeatureParameters.GetBeamDirection());
478 
479  this->GetLArTPCIntercepts(centroidCr, majorAxisCr, interceptOneCr, interceptTwoCr);
480  const double separationOneCr((interceptOneCr - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
481  const double separationTwoCr((interceptTwoCr - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
482  separationCr = std::min(separationOneCr, separationTwoCr);
483 
484  for (const CaloHit *pCaloHit : caloHitList3DNu)
485  {
486  if (maxYNu < pCaloHit->GetPositionVector().GetY())
487  maxYNu = pCaloHit->GetPositionVector().GetY();
488  }
489 
490  for (const CaloHit *pCaloHit : caloHitList3DCr)
491  {
492  if (maxYCr < pCaloHit->GetPositionVector().GetY())
493  maxYCr = pCaloHit->GetPositionVector().GetY();
494  }
495 
496  m_featureVector.push_back(closestDistanceNu);
497  m_featureVector.push_back(supplementaryAngleToBeamNu);
498  m_featureVector.push_back(separationNu);
499  m_featureVector.push_back(eigenValuesNu.GetX());
500  m_featureVector.push_back(eigenValuesNu.GetY());
501  m_featureVector.push_back(eigenValuesNu.GetZ());
502  m_featureVector.push_back(maxYNu);
503  m_featureVector.push_back(allConnectedPfoListNu.size());
504 
505  m_featureVector.push_back(closestDistanceCr);
506  m_featureVector.push_back(supplementaryAngleToBeamCr);
507  m_featureVector.push_back(separationCr);
508  m_featureVector.push_back(eigenValuesCr.GetX());
509  m_featureVector.push_back(eigenValuesCr.GetY());
510  m_featureVector.push_back(eigenValuesCr.GetZ());
511  m_featureVector.push_back(maxYCr);
512  m_featureVector.push_back(allConnectedPfoListCr.size());
513 
514  m_isAvailable = true;
515  }
516  }
517  catch (const StatusCodeException &)
518  {
519  return;
520  }
521 }
522 
523 //------------------------------------------------------------------------------------------------------------------------------------------
524 
526  const CaloHitList &inputCaloHitList, CaloHitList &outputCaloHitList, double &closestHitToFaceDistance) const
527 {
528  if (inputCaloHitList.empty())
529  {
530  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLeadingCaloHits - empty calo hit list" << std::endl;
531  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
532  }
533 
534  typedef std::pair<const CaloHit *, float> HitDistancePair;
535  typedef std::vector<HitDistancePair> HitDistanceVector;
536  HitDistanceVector hitDistanceVector;
537 
538  for (const CaloHit *const pCaloHit : inputCaloHitList)
539  hitDistanceVector.emplace_back(
540  pCaloHit, (pCaloHit->GetPositionVector() - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitudeSquared());
541 
542  std::sort(hitDistanceVector.begin(), hitDistanceVector.end(),
543  [](const HitDistancePair &lhs, const HitDistancePair &rhs) -> bool { return (lhs.second < rhs.second); });
544 
545  if (hitDistanceVector.front().second < 0.f)
546  {
547  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLeadingCaloHits - unphysical magnitude of a vector" << std::endl;
548  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
549  }
550 
551  closestHitToFaceDistance = std::sqrt(hitDistanceVector.front().second);
552 
553  const unsigned int nInputHits(inputCaloHitList.size());
554  const unsigned int nSelectedCaloHits(nInputHits < m_sliceFeatureParameters.GetNSelectedHits()
555  ? nInputHits
556  : static_cast<unsigned int>(std::ceil(static_cast<float>(nInputHits) * m_sliceFeatureParameters.GetSelectedFraction() / 100.f)));
557 
558  for (const HitDistancePair &hitDistancePair : hitDistanceVector)
559  {
560  outputCaloHitList.push_back(hitDistancePair.first);
561 
562  if (outputCaloHitList.size() >= nSelectedCaloHits)
563  break;
564  }
565 }
566 
567 //------------------------------------------------------------------------------------------------------------------------------------------
568 
570  const CartesianVector &a0, const CartesianVector &lineDirection, CartesianVector &interceptOne, CartesianVector &interceptTwo) const
571 {
572  CartesianPointVector intercepts;
573  CartesianVector lineUnitVector(0.f, 0.f, 0.f);
574 
575  try
576  {
577  lineUnitVector = lineDirection.GetUnitVector();
578  }
579  catch (const StatusCodeException &statusCodeException)
580  {
581  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - normal vector to plane has a magnitude of zero" << std::endl;
582  throw statusCodeException;
583  }
584 
585  for (const Plane &plane : m_sliceFeatureParameters.GetPlanes())
586  {
587  const CartesianVector intercept(plane.GetLineIntersection(a0, lineUnitVector));
588 
589  if (this->IsContained(intercept, m_sliceFeatureParameters.GetContainmentLimit()))
590  intercepts.push_back(intercept);
591  }
592 
593  if (intercepts.size() > 1)
594  {
595  float maximumSeparationSquared(0.f);
596  bool interceptsSet(false);
597 
598  for (unsigned int i = 0; i < intercepts.size(); i++)
599  {
600  for (unsigned int j = i + 1; j < intercepts.size(); j++)
601  {
602  const CartesianVector &candidateInterceptOne(intercepts.at(i));
603  const CartesianVector &candidateInterceptTwo(intercepts.at(j));
604  const float separationSquared((candidateInterceptOne - candidateInterceptTwo).GetMagnitudeSquared());
605 
606  if (separationSquared > maximumSeparationSquared)
607  {
608  maximumSeparationSquared = separationSquared;
609  interceptOne = candidateInterceptOne;
610  interceptTwo = candidateInterceptTwo;
611  interceptsSet = true;
612  }
613  }
614  }
615 
616  if (!interceptsSet)
617  {
618  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - unable to set the intercepts between a line and the LArTPC"
619  << std::endl;
620  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
621  }
622  }
623  else
624  {
625  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - inconsistent number of intercepts between a line and the LArTPC"
626  << std::endl;
627  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
628  }
629 }
630 
631 //------------------------------------------------------------------------------------------------------------------------------------------
632 
633 bool BdtBeamParticleIdTool::SliceFeatures::IsContained(const CartesianVector &spacePoint, const float limit) const
634 {
635  if ((m_sliceFeatureParameters.GetLArTPCMinX() - spacePoint.GetX() > limit) ||
636  (spacePoint.GetX() - m_sliceFeatureParameters.GetLArTPCMaxX() > limit) ||
637  (m_sliceFeatureParameters.GetLArTPCMinY() - spacePoint.GetY() > limit) ||
638  (spacePoint.GetY() - m_sliceFeatureParameters.GetLArTPCMaxY() > limit) ||
639  (m_sliceFeatureParameters.GetLArTPCMinZ() - spacePoint.GetZ() > limit) ||
640  (spacePoint.GetZ() - m_sliceFeatureParameters.GetLArTPCMaxZ() > limit))
641  {
642  return false;
643  }
644 
645  return true;
646 }
647 
648 //------------------------------------------------------------------------------------------------------------------------------------------
649 
651 {
652  if (!m_isAvailable)
653  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
654 
655  if (!featureVector.empty())
656  {
657  std::cout << "BdtBeamParticleIdTool::SliceFeatures::FillFeatureVector - feature vector already populated" << std::endl;
658  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
659  }
660 
661  featureVector.insert(featureVector.end(), m_featureVector.begin(), m_featureVector.end());
662 }
663 
664 //------------------------------------------------------------------------------------------------------------------------------------------
665 
667 {
668  // ATTN if one or more of the features can not be calculated, then default to calling the slice a cosmic ray. -1.f is the minimum score
669  // possible for a weighted bdt.
670  if (!this->IsFeatureVectorAvailable())
671  return -1.f;
672 
673  LArMvaHelper::MvaFeatureVector featureVector;
674 
675  try
676  {
677  this->FillFeatureVector(featureVector);
678  }
679  catch (const StatusCodeException &statusCodeException)
680  {
681  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetAdaBoostDecisionTreeScore - unable to fill feature vector" << std::endl;
682  return -1.f;
683  }
684 
685  return LArMvaHelper::CalculateClassificationScore(adaBoostDecisionTree, featureVector);
686 }
687 
688 //------------------------------------------------------------------------------------------------------------------------------------------
689 //------------------------------------------------------------------------------------------------------------------------------------------
690 
691 StatusCode BdtBeamParticleIdTool::ReadSettings(const TiXmlHandle xmlHandle)
692 {
693  // BDT Settings
694  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UseTrainingMode", m_useTrainingMode));
695 
696  if (m_useTrainingMode)
697  {
698  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "TrainingOutputFileName", m_trainingOutputFile));
699 
700  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListName", m_caloHitListName));
701 
702  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "MCParticleListName", m_mcParticleListName));
703  }
704  else
705  {
706  std::string bdtName;
707  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "BdtName", bdtName));
708 
709  std::string bdtFileName;
710  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "BdtFileName", bdtFileName));
711 
712  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "MinAdaBDTScore", m_minAdaBDTScore));
713 
714  const std::string fullBdtFileName(LArFileHelper::FindFileInPath(bdtFileName, m_filePathEnvironmentVariable));
715  const StatusCode statusCode(m_adaBoostDecisionTree.Initialize(fullBdtFileName, bdtName));
716 
717  if (STATUS_CODE_SUCCESS != statusCode)
718  {
719  std::cout << "BdtBeamParticleIdTool::ReadSettings - unable to load bdt" << std::endl;
720  return statusCode;
721  }
722  }
723 
724  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinimumPurity", m_minPurity));
725 
726  PANDORA_RETURN_RESULT_IF_AND_IF(
727  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinimumCompleteness", m_minCompleteness));
728 
729  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
730  XmlHelper::ReadValue(xmlHandle, "FilePathEnvironmentVariable", m_filePathEnvironmentVariable));
731 
732  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaximumNeutrinos", m_maxNeutrinos));
733 
734  // Geometry Information for training
735  FloatVector beamLArTPCIntersection;
736  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
737  XmlHelper::ReadVectorOfValues(xmlHandle, "BeamTPCIntersection", beamLArTPCIntersection));
738 
739  if (3 == beamLArTPCIntersection.size())
740  {
741  pandora::CartesianVector beamLArTPCIntersectionCartesianVector(
742  beamLArTPCIntersection.at(0), beamLArTPCIntersection.at(1), beamLArTPCIntersection.at(2));
743  m_sliceFeatureParameters.SetBeamLArTPCIntersection(beamLArTPCIntersectionCartesianVector);
744  }
745  else if (!beamLArTPCIntersection.empty())
746  {
747  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid BeamTPCIntersection specified " << std::endl;
748  return STATUS_CODE_INVALID_PARAMETER;
749  }
750  else
751  {
752  // Default for protoDUNE.
753  pandora::CartesianVector beamLArTPCIntersectionCartesianVector(-33.051f, 461.06f, 0.f);
754  m_sliceFeatureParameters.SetBeamLArTPCIntersection(beamLArTPCIntersectionCartesianVector);
755  }
756 
757  FloatVector beamDirection;
758  PANDORA_RETURN_RESULT_IF_AND_IF(
759  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "BeamDirection", beamDirection));
760 
761  if (3 == beamDirection.size())
762  {
763  CartesianVector beamDirectionCartesianVector(beamDirection.at(0), beamDirection.at(1), beamDirection.at(2));
764  m_sliceFeatureParameters.SetBeamDirection(beamDirectionCartesianVector);
765  }
766  else if (!beamDirection.empty())
767  {
768  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid BeamDirection specified " << std::endl;
769  return STATUS_CODE_INVALID_PARAMETER;
770  }
771  else
772  {
773  // Default for protoDUNE.
774  const float thetaXZ0(-11.844f * M_PI / 180.f);
775  CartesianVector beamDirectionCartesianVector(std::sin(thetaXZ0), 0.f, std::cos(thetaXZ0));
776  m_sliceFeatureParameters.SetBeamDirection(beamDirectionCartesianVector);
777  }
778 
779  float selectedFraction(0.f);
780 
781  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SelectedFraction", selectedFraction));
782 
783  if (selectedFraction > std::numeric_limits<float>::epsilon())
785 
786  unsigned int nSelectedHits(0);
787 
788  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NSelectedHits", nSelectedHits));
789 
790  if (nSelectedHits > 0)
792 
793  float containmentLimit(0.f);
794 
795  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ContainmentLimit", containmentLimit));
796 
797  if (containmentLimit < 0.f)
798  {
799  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid ContainmentLimit specified " << std::endl;
800  return STATUS_CODE_INVALID_PARAMETER;
801  }
802  else if (containmentLimit > 0.f)
803  {
805  }
806 
807  return STATUS_CODE_SUCCESS;
808 }
809 
810 } // namespace lar_content
intermediate_table::iterator iterator
void SetBeamLArTPCIntersection(const pandora::CartesianVector &beamLArTPCIntersection)
Set m_beamLArTPCIntersection.
double m_d
Parameter defining a plane.
std::vector< pandora::PfoList > SliceHypotheses
Header file for the pfo helper class.
bool m_selectInputHits
whether to select input hits
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:75
std::string m_filePathEnvironmentVariable
The environment variable providing a list of paths to bdt files.
std::string m_mcParticleListName
Name of input MC particle list.
float m_larTPCMinY
Global LArTPC volume minimum y extent.
Plane(const pandora::CartesianVector &normal, const pandora::CartesianVector &point)
Constructor, using equation of plane: m_a*x + m_b*y + m_c*z + m_d = 0.
float m_minAdaBDTScore
Minimum score required to classify a slice as a beam particle.
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer)
Produce a training example with the given features and result.
Definition: LArMvaHelper.h:285
float m_larTPCMaxX
Global LArTPC volume maximum x extent.
unsigned int GetNSelectedHits() const
Get m_nSelectedHits.
pandora::CartesianVector GetLineIntersection(const pandora::CartesianVector &point, const pandora::CartesianVector &direction) const
Return the intersection between the plane and a line.
float GetAdaBoostDecisionTreeScore(const AdaBoostDecisionTree &adaBoostDecisionTree) const
Get the probability that this slice contains a beam particle.
#define a0
pandora::CartesianVector EigenValues
Definition: LArPcaHelper.h:24
PlaneVector m_larTPCPlanes
Vector of all planes making up global LArTPC volume.
bool m_useTrainingMode
Should use training mode. If true, training examples will be written to the output file...
void SelectPfosByAdaBDTScore(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, const SliceFeaturesVector &sliceFeaturesVector, pandora::PfoList &selectedPfos) const
Select pfos based on the AdaBDT score that the slice contains a beam particle interaction.
std::vector< SliceFeatures > SliceFeaturesVector
STL namespace.
void SelectAllPfos(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &hypotheses, pandora::PfoList &selectedPfos) const
Select all pfos under the same hypothesis.
Header file for the principal curve analysis helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::vector< int > IntVector
void FillFeatureVector(LArMvaHelper::MvaFeatureVector &featureVector) const
Get the feature vector for the SVM.
static void GetMCPrimaryMap(const pandora::MCParticleList *const pMCParticleList, MCRelationMap &mcPrimaryMap)
Get mapping from individual mc particles (in a provided list) and their primary parent mc particles...
float m_larTPCMaxY
Global LArTPC volume maximum y extent.
static unsigned int GetNuanceCode(const pandora::MCParticle *const pMCParticle)
Get the nuance code of an MCParticle.
void SelectPfos(const pandora::PfoList &pfos, pandora::PfoList &selectedPfos) const
Add the given pfos to the selected Pfo list.
bool PassesQualityCuts(const float purity, const float completeness) const
Determine if the event passes the selection cuts for training.
float m_maxPhotonPropagation
the maximum photon propagation length
SliceFeatures(const pandora::PfoList &nuPfos, const pandora::PfoList &crPfos, const SliceFeatureParameters &sliceFeatureParameters)
Constructor.
TFile f
Definition: plotHisto.C:6
void SetBeamDirection(const pandora::CartesianVector &beamDirection)
Set m_beamDirection.
void SetNSelectedHits(const unsigned int nSelectedHits)
Set m_nSelectedHits.
bool IsContained(const pandora::CartesianVector &spacePoint, const float limit) const
Check if a given 3D spacepoint is inside the global LArTPC volume.
const pandora::CartesianVector & GetBeamDirection() const
Get the beam direction.
Header file for the beam particle id tool class.
Header file for the lar monte carlo particle helper helper class.
std::string m_trainingOutputFile
Output file name for training examples.
void SetSelectedFraction(const float selectedFraction)
Set m_selectedFraction.
float m_minPurity
Minimum purity of the best slice to use event for training.
void Collect2DHits(const pandora::PfoList &pfos, pandora::CaloHitList &caloHitList, const pandora::CaloHitSet &reconstructableCaloHitSet) const
Collect all 2D hits in a supplied list of Pfos and push them on to an existing hit list...
void GetBestMCSliceIndices(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, pandora::IntVector &bestSliceIndices) const
Get the slice with the most neutrino induced hits using Monte-Carlo information.
float m_minCompleteness
Minimum completeness of the best slice to use event for training.
void PopulateMCParticleToHitsMap(MCParticleToIntMap &mcParticleToIntMap, const pandora::CaloHitList &caloHitList) const
Fill mc particle to nHits map from calo hit list.
static const pandora::MCParticle * GetParentMCParticle(const pandora::MCParticle *const pMCParticle)
Get the parent mc particle.
const pandora::CartesianVector & GetBeamLArTPCIntersection() const
Get the beam LArTPC intersection.
pandora::CartesianVector m_unitNormal
Unit normal to plane.
static std::string FindFileInPath(const std::string &unqualifiedFileName, const std::string &environmentVariable, const std::string &delimiter=":")
Find the fully-qualified file name by searching through a list of delimiter-separated paths in a name...
Header file for the file helper class.
void Initialize(const float larTPCMinX, const float larTPCMaxX, const float larTPCMinY, const float larTPCMaxY, const float larTPCMinZ, const float larTPCMaxZ)
Set LArTPC geometry information.
void SetContainmentLimit(const float containmentLimit)
Set m_containmentLimit.
const PlaneVector & GetPlanes() const
Get vector of planes.
void GetSliceFeatures(const SliceHypotheses &nuSliceHypotheses, const SliceHypotheses &crSliceHypotheses, SliceFeaturesVector &sliceFeaturesVector) const
Get the features of each slice.
float m_larTPCMinX
Global LArTPC volume minimum x extent.
float m_larTPCMaxZ
Global LArTPC volume maximum z extent.
static void RunPca(const T &t, pandora::CartesianVector &centroid, EigenValues &outputEigenValues, EigenVectors &outputEigenVectors)
Run principal component analysis using input calo hits (TPC_VIEW_U,V,W or TPC_3D; all treated as 3D p...
std::vector< pandora::CartesianVector > EigenVectors
Definition: LArPcaHelper.h:25
void GetLeadingCaloHits(const pandora::CaloHitList &inputCaloHitList, pandora::CaloHitList &outputCaloHitList, double &closestHitToFaceDistance) const
Select a given fraction of a slice&#39;s calo hits that are closest to the beam spot. ...
std::unordered_map< const pandora::MCParticle *, int > MCParticleToIntMap
void SelectOutputPfos(const pandora::Algorithm *const pAlgorithm, const SliceHypotheses &beamSliceHypotheses, const SliceHypotheses &crSliceHypotheses, pandora::PfoList &selectedPfos)
Select which reconstruction hypotheses to use; neutrino outcomes or cosmic-ray muon outcomes for each...
pandora::StatusCode Initialize(const std::string &parameterLocation, const std::string &bdtName)
Initialize the bdt model.
unsigned int m_maxNeutrinos
The maximum number of neutrinos to select in any one event.
static double CalculateClassificationScore(const MvaInterface &classifier, TCONTAINER &&featureContainer)
Use the trained classifer to calculate the classification score of an example (>0 means boolean class...
Definition: LArMvaHelper.h:361
std::string m_caloHitListName
Name of input calo hit list.
void GetLArTPCIntercepts(const pandora::CartesianVector &a0, const pandora::CartesianVector &majorAxis, pandora::CartesianVector &interceptOne, pandora::CartesianVector &interceptTwo) const
Find the intercepts of a line with the protoDUNE detector.
std::pair< unsigned int, float > UintFloatPair
static void GetAllConnectedPfos(const pandora::PfoList &inputPfoList, pandora::PfoList &outputPfoList)
Get a flat list of all pfos, recursively including all daughters and parents associated with those pf...
float m_larTPCMinZ
Global LArTPC volume minimum z extent.
static void GetCaloHits(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::CaloHitList &caloHitList)
Get a list of calo hits of a particular hit type from a list of pfos.
std::unordered_map< const pandora::MCParticle *, const pandora::MCParticle * > MCRelationMap
AdaBoostDecisionTree m_adaBoostDecisionTree
The adaptive boost decision tree.
SliceFeatureParameters m_sliceFeatureParameters
Geometry information block.
static void SelectCaloHits(const pandora::CaloHitList *const pCaloHitList, const MCRelationMap &mcToTargetMCMap, pandora::CaloHitList &selectedCaloHitList, const bool selectInputHits, const float maxPhotonPropagation)
Select a subset of calo hits representing those that represent "reconstructable" regions of the event...