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