All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BdtBeamParticleIdTool.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArControlFlow/BdtBeamParticleIdTool.cc
3  *
4  * @brief Implementation of the beam particle id tool class.
5  *
6  * $Log: $
7  */
8 
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(
556  ? nInputHits
557  : static_cast<unsigned int>(std::ceil(static_cast<float>(nInputHits) * m_sliceFeatureParameters.GetSelectedFraction() / 100.f)));
558 
559  for (const HitDistancePair &hitDistancePair : hitDistanceVector)
560  {
561  outputCaloHitList.push_back(hitDistancePair.first);
562 
563  if (outputCaloHitList.size() >= nSelectedCaloHits)
564  break;
565  }
566 }
567 
568 //------------------------------------------------------------------------------------------------------------------------------------------
569 
571  const CartesianVector &a0, const CartesianVector &lineDirection, CartesianVector &interceptOne, CartesianVector &interceptTwo) const
572 {
573  CartesianPointVector intercepts;
574  CartesianVector lineUnitVector(0.f, 0.f, 0.f);
575 
576  try
577  {
578  lineUnitVector = lineDirection.GetUnitVector();
579  }
580  catch (const StatusCodeException &statusCodeException)
581  {
582  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - normal vector to plane has a magnitude of zero" << std::endl;
583  throw statusCodeException;
584  }
585 
586  for (const Plane &plane : m_sliceFeatureParameters.GetPlanes())
587  {
588  const CartesianVector intercept(plane.GetLineIntersection(a0, lineUnitVector));
589 
590  if (this->IsContained(intercept, m_sliceFeatureParameters.GetContainmentLimit()))
591  intercepts.push_back(intercept);
592  }
593 
594  if (intercepts.size() > 1)
595  {
596  float maximumSeparationSquared(0.f);
597  bool interceptsSet(false);
598 
599  for (unsigned int i = 0; i < intercepts.size(); i++)
600  {
601  for (unsigned int j = i + 1; j < intercepts.size(); j++)
602  {
603  const CartesianVector &candidateInterceptOne(intercepts.at(i));
604  const CartesianVector &candidateInterceptTwo(intercepts.at(j));
605  const float separationSquared((candidateInterceptOne - candidateInterceptTwo).GetMagnitudeSquared());
606 
607  if (separationSquared > maximumSeparationSquared)
608  {
609  maximumSeparationSquared = separationSquared;
610  interceptOne = candidateInterceptOne;
611  interceptTwo = candidateInterceptTwo;
612  interceptsSet = true;
613  }
614  }
615  }
616 
617  if (!interceptsSet)
618  {
619  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - unable to set the intercepts between a line and the LArTPC"
620  << std::endl;
621  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
622  }
623  }
624  else
625  {
626  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - inconsistent number of intercepts between a line and the LArTPC"
627  << std::endl;
628  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
629  }
630 }
631 
632 //------------------------------------------------------------------------------------------------------------------------------------------
633 
634 bool BdtBeamParticleIdTool::SliceFeatures::IsContained(const CartesianVector &spacePoint, const float limit) const
635 {
636  if ((m_sliceFeatureParameters.GetLArTPCMinX() - spacePoint.GetX() > limit) ||
637  (spacePoint.GetX() - m_sliceFeatureParameters.GetLArTPCMaxX() > limit) ||
638  (m_sliceFeatureParameters.GetLArTPCMinY() - spacePoint.GetY() > limit) ||
639  (spacePoint.GetY() - m_sliceFeatureParameters.GetLArTPCMaxY() > limit) ||
640  (m_sliceFeatureParameters.GetLArTPCMinZ() - spacePoint.GetZ() > limit) ||
641  (spacePoint.GetZ() - m_sliceFeatureParameters.GetLArTPCMaxZ() > limit))
642  {
643  return false;
644  }
645 
646  return true;
647 }
648 
649 //------------------------------------------------------------------------------------------------------------------------------------------
650 
652 {
653  if (!m_isAvailable)
654  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
655 
656  if (!featureVector.empty())
657  {
658  std::cout << "BdtBeamParticleIdTool::SliceFeatures::FillFeatureVector - feature vector already populated" << std::endl;
659  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
660  }
661 
662  featureVector.insert(featureVector.end(), m_featureVector.begin(), m_featureVector.end());
663 }
664 
665 //------------------------------------------------------------------------------------------------------------------------------------------
666 
668 {
669  // 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
670  // possible for a weighted bdt.
671  if (!this->IsFeatureVectorAvailable())
672  return -1.f;
673 
674  LArMvaHelper::MvaFeatureVector featureVector;
675 
676  try
677  {
678  this->FillFeatureVector(featureVector);
679  }
680  catch (const StatusCodeException &statusCodeException)
681  {
682  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetAdaBoostDecisionTreeScore - unable to fill feature vector" << std::endl;
683  return -1.f;
684  }
685 
686  return LArMvaHelper::CalculateClassificationScore(adaBoostDecisionTree, featureVector);
687 }
688 
689 //------------------------------------------------------------------------------------------------------------------------------------------
690 //------------------------------------------------------------------------------------------------------------------------------------------
691 
692 StatusCode BdtBeamParticleIdTool::ReadSettings(const TiXmlHandle xmlHandle)
693 {
694  // BDT Settings
695  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "UseTrainingMode", m_useTrainingMode));
696 
697  if (m_useTrainingMode)
698  {
699  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "TrainingOutputFileName", m_trainingOutputFile));
700 
701  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "CaloHitListName", m_caloHitListName));
702 
703  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "MCParticleListName", m_mcParticleListName));
704  }
705  else
706  {
707  std::string bdtName;
708  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "BdtName", bdtName));
709 
710  std::string bdtFileName;
711  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "BdtFileName", bdtFileName));
712 
713  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "MinAdaBDTScore", m_minAdaBDTScore));
714 
715  const std::string fullBdtFileName(LArFileHelper::FindFileInPath(bdtFileName, m_filePathEnvironmentVariable));
716  const StatusCode statusCode(m_adaBoostDecisionTree.Initialize(fullBdtFileName, bdtName));
717 
718  if (STATUS_CODE_SUCCESS != statusCode)
719  {
720  std::cout << "BdtBeamParticleIdTool::ReadSettings - unable to load bdt" << std::endl;
721  return statusCode;
722  }
723  }
724 
725  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinimumPurity", m_minPurity));
726 
727  PANDORA_RETURN_RESULT_IF_AND_IF(
728  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinimumCompleteness", m_minCompleteness));
729 
730  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
731  XmlHelper::ReadValue(xmlHandle, "FilePathEnvironmentVariable", m_filePathEnvironmentVariable));
732 
733  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaximumNeutrinos", m_maxNeutrinos));
734 
735  // Geometry Information for training
736  FloatVector beamLArTPCIntersection;
737  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
738  XmlHelper::ReadVectorOfValues(xmlHandle, "BeamTPCIntersection", beamLArTPCIntersection));
739 
740  if (3 == beamLArTPCIntersection.size())
741  {
742  pandora::CartesianVector beamLArTPCIntersectionCartesianVector(
743  beamLArTPCIntersection.at(0), beamLArTPCIntersection.at(1), beamLArTPCIntersection.at(2));
744  m_sliceFeatureParameters.SetBeamLArTPCIntersection(beamLArTPCIntersectionCartesianVector);
745  }
746  else if (!beamLArTPCIntersection.empty())
747  {
748  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid BeamTPCIntersection specified " << std::endl;
749  return STATUS_CODE_INVALID_PARAMETER;
750  }
751  else
752  {
753  // Default for protoDUNE.
754  pandora::CartesianVector beamLArTPCIntersectionCartesianVector(-33.051f, 461.06f, 0.f);
755  m_sliceFeatureParameters.SetBeamLArTPCIntersection(beamLArTPCIntersectionCartesianVector);
756  }
757 
758  FloatVector beamDirection;
759  PANDORA_RETURN_RESULT_IF_AND_IF(
760  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "BeamDirection", beamDirection));
761 
762  if (3 == beamDirection.size())
763  {
764  CartesianVector beamDirectionCartesianVector(beamDirection.at(0), beamDirection.at(1), beamDirection.at(2));
765  m_sliceFeatureParameters.SetBeamDirection(beamDirectionCartesianVector);
766  }
767  else if (!beamDirection.empty())
768  {
769  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid BeamDirection specified " << std::endl;
770  return STATUS_CODE_INVALID_PARAMETER;
771  }
772  else
773  {
774  // Default for protoDUNE.
775  const float thetaXZ0(-11.844f * M_PI / 180.f);
776  CartesianVector beamDirectionCartesianVector(std::sin(thetaXZ0), 0.f, std::cos(thetaXZ0));
777  m_sliceFeatureParameters.SetBeamDirection(beamDirectionCartesianVector);
778  }
779 
780  float selectedFraction(0.f);
781 
782  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SelectedFraction", selectedFraction));
783 
784  if (selectedFraction > std::numeric_limits<float>::epsilon())
786 
787  unsigned int nSelectedHits(0);
788 
789  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NSelectedHits", nSelectedHits));
790 
791  if (nSelectedHits > 0)
793 
794  float containmentLimit(0.f);
795 
796  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ContainmentLimit", containmentLimit));
797 
798  if (containmentLimit < 0.f)
799  {
800  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid ContainmentLimit specified " << std::endl;
801  return STATUS_CODE_INVALID_PARAMETER;
802  }
803  else if (containmentLimit > 0.f)
804  {
806  }
807 
808  return STATUS_CODE_SUCCESS;
809 }
810 
811 } // namespace lar_content
void SetBeamLArTPCIntersection(const pandora::CartesianVector &beamLArTPCIntersection)
Set m_beamLArTPCIntersection.
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
Header file for the pfo helper class.
bool m_selectInputHits
whether to select input hits
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:72
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.
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:282
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
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
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...
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.
process_name gaushit a
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.
std::vector< pandora::PfoList > SliceHypotheses
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.
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...
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
Definition: reco_sbnd.fcl:182
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 (&gt;0 means boolean class...
Definition: LArMvaHelper.h:358
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...
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.
BEGIN_PROLOG could also be cout
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 &quot;reconstructable&quot; regions of the event...