LArSoft  v07_13_02
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(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 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), 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 SliceFeatureParameters &sliceFeatureParameters) :
427  m_isAvailable(false),
428  m_sliceFeatureParameters(sliceFeatureParameters)
429 {
430  try
431  {
432  double closestDistanceNu(std::numeric_limits<double>::max()), closestDistanceCr(std::numeric_limits<double>::max()), supplementaryAngleToBeamNu(std::numeric_limits<double>::max()),
433  supplementaryAngleToBeamCr(std::numeric_limits<double>::max()), separationNu(std::numeric_limits<double>::max()), separationCr(std::numeric_limits<double>::max());;
434  CaloHitList caloHitList3DNu, caloHitList3DCr, selectedCaloHitListNu, selectedCaloHitListCr;
435  PfoList allConnectedPfoListNu, allConnectedPfoListCr;
436  LArPcaHelper::EigenValues eigenValuesNu(0.f, 0.f, 0.f);
437  LArPcaHelper::EigenValues eigenValuesCr(0.f, 0.f, 0.f);
438 
439  LArPfoHelper::GetAllConnectedPfos(pfosNu, allConnectedPfoListNu);
440  LArPfoHelper::GetAllConnectedPfos(pfosCr, allConnectedPfoListCr);
441  LArPfoHelper::GetCaloHits(allConnectedPfoListNu, TPC_3D, caloHitList3DNu);
442  LArPfoHelper::GetCaloHits(allConnectedPfoListCr, TPC_3D, caloHitList3DCr);
443 
444  this->GetLeadingCaloHits(caloHitList3DNu, selectedCaloHitListNu, closestDistanceNu);
445  this->GetLeadingCaloHits(caloHitList3DCr, selectedCaloHitListCr, closestDistanceCr);
446 
447  if (!selectedCaloHitListNu.empty() && !selectedCaloHitListCr.empty())
448  {
450  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);
451 
452  // Beam
453  LArPcaHelper::EigenVectors eigenVecsNu;
454  LArPcaHelper::RunPca(selectedCaloHitListNu, centroidNu, eigenValuesNu, eigenVecsNu);
455  const CartesianVector &majorAxisNu(eigenVecsNu.front());
456  supplementaryAngleToBeamNu = majorAxisNu.GetOpeningAngle(m_sliceFeatureParameters.GetBeamDirection());
457 
458  this->GetLArTPCIntercepts(centroidNu, majorAxisNu, interceptOneNu, interceptTwoNu);
459  const double separationOneNu((interceptOneNu - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
460  const double separationTwoNu((interceptTwoNu - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
461  separationNu = std::min(separationOneNu, separationTwoNu);
462 
463  // Cosmic
464  LArPcaHelper::EigenVectors eigenVecsCr;
465  LArPcaHelper::RunPca(selectedCaloHitListCr, centroidCr, eigenValuesCr, eigenVecsCr);
466  const CartesianVector &majorAxisCr(eigenVecsCr.front());
467  supplementaryAngleToBeamCr = majorAxisCr.GetOpeningAngle(m_sliceFeatureParameters.GetBeamDirection());
468 
469  this->GetLArTPCIntercepts(centroidCr, majorAxisCr, interceptOneCr, interceptTwoCr);
470  const double separationOneCr((interceptOneCr - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
471  const double separationTwoCr((interceptTwoCr - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitude());
472  separationCr = std::min(separationOneCr, separationTwoCr);
473 
474  for (const CaloHit *pCaloHit : caloHitList3DNu)
475  {
476  if (maxYNu < pCaloHit->GetPositionVector().GetY())
477  maxYNu = pCaloHit->GetPositionVector().GetY();
478  }
479 
480  for (const CaloHit *pCaloHit : caloHitList3DCr)
481  {
482  if (maxYCr < pCaloHit->GetPositionVector().GetY())
483  maxYCr = pCaloHit->GetPositionVector().GetY();
484  }
485 
486  m_featureVector.push_back(closestDistanceNu);
487  m_featureVector.push_back(supplementaryAngleToBeamNu);
488  m_featureVector.push_back(separationNu);
489  m_featureVector.push_back(eigenValuesNu.GetX());
490  m_featureVector.push_back(eigenValuesNu.GetY());
491  m_featureVector.push_back(eigenValuesNu.GetZ());
492  m_featureVector.push_back(maxYNu);
493  m_featureVector.push_back(allConnectedPfoListNu.size());
494 
495  m_featureVector.push_back(closestDistanceCr);
496  m_featureVector.push_back(supplementaryAngleToBeamCr);
497  m_featureVector.push_back(separationCr);
498  m_featureVector.push_back(eigenValuesCr.GetX());
499  m_featureVector.push_back(eigenValuesCr.GetY());
500  m_featureVector.push_back(eigenValuesCr.GetZ());
501  m_featureVector.push_back(maxYCr);
502  m_featureVector.push_back(allConnectedPfoListCr.size());
503 
504  m_isAvailable = true;
505  }
506  }
507  catch (const StatusCodeException &)
508  {
509  return;
510  }
511 }
512 
513 //------------------------------------------------------------------------------------------------------------------------------------------
514 
515 void BdtBeamParticleIdTool::SliceFeatures::GetLeadingCaloHits(const CaloHitList &inputCaloHitList, CaloHitList &outputCaloHitList,
516  double &closestHitToFaceDistance) const
517 {
518  if (inputCaloHitList.empty())
519  {
520  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLeadingCaloHits - empty calo hit list" << std::endl;
521  throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
522  }
523 
524  typedef std::pair<const CaloHit*, float> HitDistancePair;
525  typedef std::vector<HitDistancePair> HitDistanceVector;
526  HitDistanceVector hitDistanceVector;
527 
528  for (const CaloHit *const pCaloHit : inputCaloHitList)
529  hitDistanceVector.emplace_back(pCaloHit, (pCaloHit->GetPositionVector() - m_sliceFeatureParameters.GetBeamLArTPCIntersection()).GetMagnitudeSquared());
530 
531  std::sort(hitDistanceVector.begin(), hitDistanceVector.end(), [](const HitDistancePair &lhs, const HitDistancePair &rhs) -> bool {return (lhs.second < rhs.second);});
532 
533  if (hitDistanceVector.front().second < 0.f)
534  {
535  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLeadingCaloHits - unphysical magnitude of a vector" << std::endl;
536  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
537  }
538 
539  closestHitToFaceDistance = std::sqrt(hitDistanceVector.front().second);
540 
541  const unsigned int nInputHits(inputCaloHitList.size());
542  const unsigned int nSelectedCaloHits(nInputHits < m_sliceFeatureParameters.GetNSelectedHits() ? nInputHits :
543  static_cast<unsigned int>(std::ceil(static_cast<float>(nInputHits) * m_sliceFeatureParameters.GetSelectedFraction() / 100.f)));
544 
545  for (const HitDistancePair &hitDistancePair : hitDistanceVector)
546  {
547  outputCaloHitList.push_back(hitDistancePair.first);
548 
549  if (outputCaloHitList.size() >= nSelectedCaloHits)
550  break;
551  }
552 }
553 
554 //------------------------------------------------------------------------------------------------------------------------------------------
555 
556 void BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts(const CartesianVector &a0, const CartesianVector &lineDirection,
557  CartesianVector &interceptOne, CartesianVector &interceptTwo) const
558 {
559  CartesianPointVector intercepts;
560  CartesianVector lineUnitVector(0.f, 0.f, 0.f);
561 
562  try
563  {
564  lineUnitVector = lineDirection.GetUnitVector();
565  }
566  catch (const StatusCodeException &statusCodeException)
567  {
568  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - normal vector to plane has a magnitude of zero" << std::endl;
569  throw statusCodeException;
570  }
571 
572  for (const Plane &plane : m_sliceFeatureParameters.GetPlanes())
573  {
574  const CartesianVector intercept(plane.GetLineIntersection(a0, lineUnitVector));
575 
576  if (this->IsContained(intercept, m_sliceFeatureParameters.GetContainmentLimit()))
577  intercepts.push_back(intercept);
578  }
579 
580  if (intercepts.size() > 1)
581  {
582  float maximumSeparationSquared(0.f);
583  bool interceptsSet(false);
584 
585  for (unsigned int i = 0; i < intercepts.size(); i++)
586  {
587  for (unsigned int j = i + 1; j < intercepts.size(); j++)
588  {
589  const CartesianVector &candidateInterceptOne(intercepts.at(i));
590  const CartesianVector &candidateInterceptTwo(intercepts.at(j));
591  const float separationSquared((candidateInterceptOne - candidateInterceptTwo).GetMagnitudeSquared());
592 
593  if (separationSquared > maximumSeparationSquared)
594  {
595  maximumSeparationSquared = separationSquared;
596  interceptOne = candidateInterceptOne;
597  interceptTwo = candidateInterceptTwo;
598  interceptsSet = true;
599  }
600  }
601  }
602 
603  if (!interceptsSet)
604  {
605  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - unable to set the intercepts between a line and the LArTPC" << std::endl;
606  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
607  }
608  }
609  else
610  {
611  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetLArTPCIntercepts - inconsistent number of intercepts between a line and the LArTPC" << std::endl;
612  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
613  }
614 }
615 
616 //------------------------------------------------------------------------------------------------------------------------------------------
617 
618 bool BdtBeamParticleIdTool::SliceFeatures::IsContained(const CartesianVector &spacePoint, const float limit) const
619 {
620  if ((m_sliceFeatureParameters.GetLArTPCMinX() - spacePoint.GetX() > limit) || (spacePoint.GetX() - m_sliceFeatureParameters.GetLArTPCMaxX() > limit) ||
621  (m_sliceFeatureParameters.GetLArTPCMinY() - spacePoint.GetY() > limit) || (spacePoint.GetY() - m_sliceFeatureParameters.GetLArTPCMaxY() > limit) ||
622  (m_sliceFeatureParameters.GetLArTPCMinZ() - spacePoint.GetZ() > limit) || (spacePoint.GetZ() - m_sliceFeatureParameters.GetLArTPCMaxZ() > limit))
623  {
624  return false;
625  }
626 
627  return true;
628 }
629 
630 //------------------------------------------------------------------------------------------------------------------------------------------
631 
633 {
634  if (!m_isAvailable)
635  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
636 
637  if (!featureVector.empty())
638  {
639  std::cout << "BdtBeamParticleIdTool::SliceFeatures::FillFeatureVector - feature vector already populated" << std::endl;
640  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
641  }
642 
643  featureVector.insert(featureVector.end(), m_featureVector.begin(), m_featureVector.end());
644 }
645 
646 //------------------------------------------------------------------------------------------------------------------------------------------
647 
649 {
650  // 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
651  // possible for a weighted bdt.
652  if (!this->IsFeatureVectorAvailable()) return -1.f;
653 
654  LArMvaHelper::MvaFeatureVector featureVector;
655 
656  try
657  {
658  this->FillFeatureVector(featureVector);
659  }
660  catch (const StatusCodeException &statusCodeException)
661  {
662  std::cout << "BdtBeamParticleIdTool::SliceFeatures::GetAdaBoostDecisionTreeScore - unable to fill feature vector" << std::endl;
663  return -1.f;
664  }
665 
666  return LArMvaHelper::CalculateClassificationScore(adaBoostDecisionTree, featureVector);
667 }
668 
669 //------------------------------------------------------------------------------------------------------------------------------------------
670 //------------------------------------------------------------------------------------------------------------------------------------------
671 
672 StatusCode BdtBeamParticleIdTool::ReadSettings(const TiXmlHandle xmlHandle)
673 {
674  // BDT Settings
675  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
676  "UseTrainingMode", m_useTrainingMode));
677 
678  if (m_useTrainingMode)
679  {
680  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
681  "TrainingOutputFileName", m_trainingOutputFile));
682 
683  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
684  "CaloHitListName", m_caloHitListName));
685 
686  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
687  "MCParticleListName", m_mcParticleListName));
688  }
689  else
690  {
691  std::string bdtName;
692  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
693  "BdtName", bdtName));
694 
695  std::string bdtFileName;
696  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
697  "BdtFileName", bdtFileName));
698 
699  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
700  "MinAdaBDTScore", m_minAdaBDTScore));
701 
702  const std::string fullBdtFileName(LArFileHelper::FindFileInPath(bdtFileName, m_filePathEnvironmentVariable));
703  const StatusCode statusCode(m_adaBoostDecisionTree.Initialize(fullBdtFileName, bdtName));
704 
705  if (STATUS_CODE_SUCCESS != statusCode)
706  {
707  std::cout << "BdtBeamParticleIdTool::ReadSettings - unable to load bdt" << std::endl;
708  return statusCode;
709  }
710  }
711 
712  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
713  "MinimumPurity", m_minPurity));
714 
715  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
716  "MinimumCompleteness", m_minCompleteness));
717 
718  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
719  "FilePathEnvironmentVariable", m_filePathEnvironmentVariable));
720 
721  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
722  "MaximumNeutrinos", m_maxNeutrinos));
723 
724  // Geometry Information for training
725  FloatVector beamLArTPCIntersection;
726  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
727  "BeamTPCIntersection", beamLArTPCIntersection));
728 
729  if (3 == beamLArTPCIntersection.size())
730  {
731  pandora::CartesianVector beamLArTPCIntersectionCartesianVector(beamLArTPCIntersection.at(0), beamLArTPCIntersection.at(1), beamLArTPCIntersection.at(2));
732  m_sliceFeatureParameters.SetBeamLArTPCIntersection(beamLArTPCIntersectionCartesianVector);
733  }
734  else if (!beamLArTPCIntersection.empty())
735  {
736  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid BeamTPCIntersection specified " << std::endl;
737  return STATUS_CODE_INVALID_PARAMETER;
738  }
739  else
740  {
741  // Default for protoDUNE.
742  pandora::CartesianVector beamLArTPCIntersectionCartesianVector(-33.051f, 461.06f, 0.f);
743  m_sliceFeatureParameters.SetBeamLArTPCIntersection(beamLArTPCIntersectionCartesianVector);
744  }
745 
746  FloatVector beamDirection;
747  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle,
748  "BeamDirection", beamDirection));
749 
750  if (3 == beamDirection.size())
751  {
752  CartesianVector beamDirectionCartesianVector(beamDirection.at(0), beamDirection.at(1), beamDirection.at(2));
753  m_sliceFeatureParameters.SetBeamDirection(beamDirectionCartesianVector);
754  }
755  else if (!beamDirection.empty())
756  {
757  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid BeamDirection specified " << std::endl;
758  return STATUS_CODE_INVALID_PARAMETER;
759  }
760  else
761  {
762  // Default for protoDUNE.
763  const float thetaXZ0(-11.844f * M_PI / 180.f);
764  CartesianVector beamDirectionCartesianVector(std::sin(thetaXZ0), 0.f, std::cos(thetaXZ0));
765  m_sliceFeatureParameters.SetBeamDirection(beamDirectionCartesianVector);
766  }
767 
768  float selectedFraction(0.f);
769 
770  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
771  "SelectedFraction", selectedFraction));
772 
773  if (selectedFraction > std::numeric_limits<float>::epsilon())
775 
776  unsigned int nSelectedHits(0);
777 
778  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
779  "NSelectedHits", nSelectedHits));
780 
781  if (nSelectedHits > 0)
783 
784  float containmentLimit(0.f);
785 
786  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
787  "ContainmentLimit", containmentLimit));
788 
789  if (containmentLimit < 0.f)
790  {
791  std::cout << "BdtBeamParticleIdTool::ReadSettings - invalid ContainmentLimit specified " << std::endl;
792  return STATUS_CODE_INVALID_PARAMETER;
793  }
794  else if (containmentLimit > 0.f)
795  {
797  }
798 
799  return STATUS_CODE_SUCCESS;
800 }
801 
802 } // 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...
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.
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.
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.
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 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.
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.
AdaBoostDecisionTree m_adaBoostDecisionTree
The adaptive boost decision tree.
SliceFeatureParameters m_sliceFeatureParameters
Geometry information block.