LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
CheatingSliceSelectionTool.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
15 using namespace pandora;
16 
17 namespace lar_content
18 {
19 
20 CheatingSliceSelectionTool::CheatingSliceSelectionTool() :
21  m_maxSlices{1},
22  m_threshold{-1.f},
23  m_cutVariable{"completeness"}
24 {
25 }
26 
27 //-----------------------------------------------------------------------------------------------------------------------------------------
28 
29 void CheatingSliceSelectionTool::SelectSlices(const pandora::Algorithm *const /*pAlgorithm*/, const SliceVector &inputSliceVector, SliceVector &outputSliceVector)
30 {
31  // ATTN Ensure this only runs if slicing enabled
32  unsigned int sliceCounter{0};
33  MetricSliceIndexMap reducedSliceVarIndexMap;
34 
35  FloatVector targetWeights(inputSliceVector.size());
36  FloatVector otherWeights(inputSliceVector.size());
37 
38  // Calculate target and total weight for each slice
39  for (const CaloHitList &sliceHits : inputSliceVector)
40  {
41  CaloHitList localHitList{};
42  // ATTN Must ensure we copy the hit actually owned by master instance; access differs with/without slicing enabled
43  for (const CaloHit *const pSliceCaloHit : sliceHits)
44  localHitList.push_back(static_cast<const CaloHit *>(pSliceCaloHit->GetParentAddress()));
45 
46  for (const CaloHit *const pCaloHit : localHitList)
47  {
48  float thisTargetParticleWeight{0.f}, thisTotalWeight{0.f};
49  const MCParticleWeightMap &hitMCParticleWeightMap(pCaloHit->GetMCParticleWeightMap());
50 
51  if (hitMCParticleWeightMap.empty())
52  continue;
53 
54  MCParticleList mcParticleList;
55  for (const auto &mapEntry : hitMCParticleWeightMap)
56  mcParticleList.push_back(mapEntry.first);
57  mcParticleList.sort(LArMCParticleHelper::SortByMomentum);
58 
59  for (const MCParticle *const pMCParticle : mcParticleList)
60  {
61  const float weight{hitMCParticleWeightMap.at(pMCParticle)};
62  const MCParticle *const pParentMCParticle{LArMCParticleHelper::GetParentMCParticle(pMCParticle)};
63 
64  if (this->IsTarget(pParentMCParticle))
65  thisTargetParticleWeight += weight;
66 
67  thisTotalWeight += weight;
68  }
69 
70  // ATTN normalise arbitrary input weights at this point
71  if (thisTotalWeight > std::numeric_limits<float>::epsilon())
72  {
73  thisTargetParticleWeight *= 1.f / thisTotalWeight;
74  thisTotalWeight = 1.f;
75  }
76  else
77  {
78  thisTargetParticleWeight = 0.f;
79  thisTotalWeight = 0.f;
80  }
81  targetWeights[sliceCounter] += thisTargetParticleWeight;
82  otherWeights[sliceCounter] += (1. - thisTargetParticleWeight);
83  }
84 
85  ++sliceCounter;
86  }
87 
88  float totalTargetWeight{0.f};
89  for (const float weight : targetWeights)
90  totalTargetWeight += weight;
91 
92  // Add slices passing cut threshold to map
93  for (unsigned int i = 0; i < targetWeights.size(); ++i)
94  {
95  const float sliceWeight = targetWeights[i] + otherWeights[i];
96  const float completeness{totalTargetWeight > std::numeric_limits<float>::epsilon() ? targetWeights[i] / totalTargetWeight : 0.f};
97  const float purity{sliceWeight > std::numeric_limits<float>::epsilon() ? targetWeights[i] / sliceWeight : 0.f};
98  // Already checked correctness of variable in ReadSettings
99  if (m_cutVariable == "completeness")
100  {
101  if (completeness >= m_threshold)
102  reducedSliceVarIndexMap.emplace(completeness, i);
103  }
104  else if (m_cutVariable == "purity")
105  {
106  if (purity >= m_threshold)
107  reducedSliceVarIndexMap.emplace(purity, i);
108  }
109  }
110  // Select the best m_maxSlices slices - prefix increment ensures all slices retained if m_maxSlices == 0
111  std::vector<int> reducedSliceIndices{};
112  int i = 0;
113  for (const auto [cutVariable, index] : reducedSliceVarIndexMap)
114  { // ATTN: Map is sorted on cut variable from max to min
115  (void)cutVariable; // GCC 7 support, versions 8+ do not need this
116  reducedSliceIndices.push_back(index);
117  outputSliceVector.push_back(inputSliceVector[index]);
118  if (++i == m_maxSlices)
119  break;
120  }
121 }
122 
123 //------------------------------------------------------------------------------------------------------------------------------------------
124 
125 StatusCode CheatingSliceSelectionTool::ReadSettings(const TiXmlHandle xmlHandle)
126 {
127  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxSlices", m_maxSlices));
128  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "Threshold", m_threshold));
129 
130  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "CutVariable", m_cutVariable));
131  std::transform(m_cutVariable.begin(), m_cutVariable.end(), m_cutVariable.begin(), [](unsigned char c) { return std::tolower(c); });
132  if (m_cutVariable != "completeness" && m_cutVariable != "purity")
133  {
134  std::cout << "CheatingSliceSelectionTool::ReadSettings: Unknown cut variable \'" << m_cutVariable << "\'" << std::endl;
135  return STATUS_CODE_INVALID_PARAMETER;
136  }
137 
138  return STATUS_CODE_SUCCESS;
139 }
140 
141 } // namespace lar_content
void SelectSlices(const pandora::Algorithm *const pAlgorithm, const SliceVector &inputSliceVector, SliceVector &outputSliceVector)
Select which slice(s) to use.
std::string m_cutVariable
The variable to cut on ("purity" or "completeness") - default "completeness".
int m_maxSlices
The maximum number of slices to retain (0 to retain all) - default 0.
std::map< float, int, std::greater< float > > MetricSliceIndexMap
Header file for the cheating slice selection tool class.
static bool SortByMomentum(const pandora::MCParticle *const pLhs, const pandora::MCParticle *const pRhs)
Sort mc particles by their momentum.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Header file for the lar monte carlo particle helper helper class.
float m_threshold
The minimum cut threshold to retain a slice (< 0 for no threshold) - default -1.
static const pandora::MCParticle * GetParentMCParticle(const pandora::MCParticle *const pMCParticle)
Get the parent mc particle.
double weight
Definition: plottest35.C:25
virtual bool IsTarget(const pandora::MCParticle *const mcParticle) const =0
Template method to determine if an MC particle matches the target criteria for slice selection...
std::vector< pandora::CaloHitList > SliceVector