Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
PeakDirectionFinderTool.cc
Go to the documentation of this file.
1
11
14
16
17using namespace pandora;
18
19namespace lar_content
20{
21
23 m_pathwaySearchRegion(10.f),
24 m_theta0XZBinSize(0.005f),
25 m_smoothingWindow(1),
26 m_ambiguousParticleMode(false)
27{
28}
29
30//------------------------------------------------------------------------------------------------------------------------------------------
31
33 const CaloHitList *const pViewHitList, const HitType hitType, CartesianPointVector &peakDirectionVector)
34{
35 CaloHitList viewShowerHitList;
36 LArPfoHelper::GetCaloHits(pShowerPfo, hitType, viewShowerHitList);
37
38 const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
39
40 // Get event hits in region of interest
41 CaloHitList viewROIHits;
42 this->CollectHitsWithinROI(viewShowerHitList, pViewHitList, nuVertex2D, viewROIHits);
43
44 if (viewROIHits.empty())
45 return STATUS_CODE_NOT_FOUND;
46
47 // Fill angular decomposition map
48 AngularDecompositionMap angularDecompositionMap;
49 this->FillAngularDecompositionMap(viewROIHits, nuVertex2D, angularDecompositionMap);
50
51 if (angularDecompositionMap.empty())
52 return STATUS_CODE_NOT_FOUND;
53
54 // Smooth angular decomposition map
55 this->SmoothAngularDecompositionMap(angularDecompositionMap);
56
57 // Get peak directions
58 this->RetrievePeakDirections(angularDecompositionMap, peakDirectionVector);
59
60 if (peakDirectionVector.empty())
61 return STATUS_CODE_NOT_FOUND;
62
63 return STATUS_CODE_SUCCESS;
64}
65
66//------------------------------------------------------------------------------------------------------------------------------------------
67
68void PeakDirectionFinderTool::CollectHitsWithinROI(const CaloHitList &showerHitList, const CaloHitList *const pViewHitList,
69 const CartesianVector &nuVertex2D, CaloHitList &viewROIHits) const
70{
72 {
73 for (const CaloHit *const pCaloHit : *pViewHitList)
74 {
75 if (std::find(showerHitList.begin(), showerHitList.end(), pCaloHit) != showerHitList.end())
76 continue;
77
78 viewROIHits.push_back(pCaloHit);
79 }
80 }
81 else
82 {
83 float lowestTheta(std::numeric_limits<float>::max()), highestTheta((-1.f) * std::numeric_limits<float>::max());
84
85 this->GetAngularExtrema(showerHitList, nuVertex2D, lowestTheta, highestTheta);
86 this->CollectHitsWithinExtrema(pViewHitList, nuVertex2D, lowestTheta, highestTheta, viewROIHits);
87 }
88}
89
90//------------------------------------------------------------------------------------------------------------------------------------------
91
93 const CaloHitList &showerHitList, const CartesianVector &nuVertex2D, float &lowestTheta, float &highestTheta) const
94{
95 lowestTheta = std::numeric_limits<float>::max();
96 highestTheta = (-1.f) * std::numeric_limits<float>::max();
97
98 const CartesianVector xAxis(1.f, 0.f, 0.f);
99
100 for (const CaloHit *const pCaloHit : showerHitList)
101 {
102 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
103 const CartesianVector displacementVector(hitPosition - nuVertex2D);
104
105 float theta0XZ(xAxis.GetOpeningAngle(displacementVector));
106
107 if (displacementVector.GetZ() < 0.f)
108 theta0XZ = (2.0 * M_PI) - theta0XZ;
109
110 if (theta0XZ < lowestTheta)
111 lowestTheta = theta0XZ;
112
113 if (theta0XZ > highestTheta)
114 highestTheta = theta0XZ;
115 }
116}
117
118//------------------------------------------------------------------------------------------------------------------------------------------
119
120void PeakDirectionFinderTool::CollectHitsWithinExtrema(const CaloHitList *const pViewHitList, const CartesianVector &nuVertex2D,
121 const float lowestTheta, const float highestTheta, CaloHitList &viewROIHits) const
122{
123 const CartesianVector xAxis(1.f, 0.f, 0.f);
124
125 for (const CaloHit *const pCaloHit : *pViewHitList)
126 {
127 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
128 const CartesianVector displacementVector(hitPosition - nuVertex2D);
129
130 float theta0XZ(xAxis.GetOpeningAngle(displacementVector));
131
132 if (displacementVector.GetZ() < 0.f)
133 theta0XZ = (2.0 * M_PI) - theta0XZ;
134
135 if ((theta0XZ < lowestTheta) || (theta0XZ > highestTheta))
136 continue;
137
138 viewROIHits.push_back(pCaloHit);
139 }
140}
141
142//------------------------------------------------------------------------------------------------------------------------------------------
143
145 const CaloHitList &viewShowerHitList, const CartesianVector &nuVertex2D, AngularDecompositionMap &angularDecompositionMap) const
146{
147 const CartesianVector xAxis(1.f, 0.f, 0.f);
148
149 for (const CaloHit *const pCaloHit : viewShowerHitList)
150 {
151 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
152 const CartesianVector displacementVector(hitPosition - nuVertex2D);
153
155 continue;
156
157 float theta0XZ(xAxis.GetOpeningAngle(displacementVector));
158
159 if (displacementVector.GetZ() < 0.f)
160 theta0XZ *= -1.f;
161
162 const int theta0XZFactor(std::floor(theta0XZ / m_theta0XZBinSize));
163
164 if (angularDecompositionMap.find(theta0XZFactor) == angularDecompositionMap.end())
165 angularDecompositionMap[theta0XZFactor] = 1;
166 else
167 angularDecompositionMap[theta0XZFactor] += 1;
168 }
169}
170
171//------------------------------------------------------------------------------------------------------------------------------------------
172
174{
175 const int loopMin((-1) * m_smoothingWindow);
176 const int loopMax(m_smoothingWindow);
177
178 const AngularDecompositionMap angularDecompositionMapTemp(angularDecompositionMap);
179
180 angularDecompositionMap.clear();
181
182 for (const auto &entry : angularDecompositionMapTemp)
183 {
184 float total(0.f);
185 const int currentBin(entry.first);
186
187 for (int binOffset = loopMin; binOffset <= loopMax; ++binOffset)
188 {
189 const int contributingBin = currentBin + binOffset;
190 total += (angularDecompositionMapTemp.find(contributingBin) == angularDecompositionMapTemp.end())
191 ? 0.f
192 : angularDecompositionMapTemp.at(contributingBin);
193 }
194
195 angularDecompositionMap[currentBin] = total / static_cast<float>((2.0 * m_smoothingWindow) + 1);
196 }
197}
198
199//------------------------------------------------------------------------------------------------------------------------------------------
200
201void PeakDirectionFinderTool::RetrievePeakDirections(const AngularDecompositionMap &angularDecompositionMap, CartesianPointVector &peakDirectionVector) const
202{
203 IntVector orderedBinIndexVector;
204
205 for (const auto &entry : angularDecompositionMap)
206 orderedBinIndexVector.push_back(entry.first);
207
208 // Order peak bin vector from highest to lowest bin height
209 // Tie-break: highest index wins
210 std::sort(orderedBinIndexVector.begin(), orderedBinIndexVector.end(), [&angularDecompositionMap](const int a, const int b) -> bool {
211 const float aWeight(angularDecompositionMap.at(a));
212 const float bWeight(angularDecompositionMap.at(b));
213
214 if (std::fabs(aWeight - bWeight) < std::numeric_limits<float>::epsilon())
215 return a > b;
216 else
217 return aWeight > bWeight;
218 });
219
220 for (int binIndex : orderedBinIndexVector)
221 {
222 const float binWeight(angularDecompositionMap.at(binIndex));
223
224 int precedingBin(binIndex - 1);
225 bool foundPreceeding(false);
226
227 while (!foundPreceeding)
228 {
229 if ((angularDecompositionMap.find(precedingBin) == angularDecompositionMap.end()) ||
230 (std::fabs(angularDecompositionMap.at(precedingBin) - angularDecompositionMap.at(binIndex)) > std::numeric_limits<float>::epsilon()))
231 {
232 foundPreceeding = true;
233 break;
234 }
235
236 --precedingBin;
237 }
238
239 int followingBin(binIndex + 1);
240 bool foundFollowing(false);
241
242 while (!foundFollowing)
243 {
244 if ((angularDecompositionMap.find(followingBin) == angularDecompositionMap.end()) ||
245 (std::fabs(angularDecompositionMap.at(followingBin) - angularDecompositionMap.at(binIndex)) > std::numeric_limits<float>::epsilon()))
246 {
247 foundFollowing = true;
248 break;
249 }
250
251 ++followingBin;
252 }
253
254 const float precedingBinWeight(
255 angularDecompositionMap.find(precedingBin) == angularDecompositionMap.end() ? 0.f : angularDecompositionMap.at(precedingBin));
256 const float followingBinWeight(
257 angularDecompositionMap.find(followingBin) == angularDecompositionMap.end() ? 0.f : angularDecompositionMap.at(followingBin));
258
259 if ((binWeight < precedingBinWeight) || (binWeight < followingBinWeight))
260 continue;
261
262 // Convert to a direction
263 const float theta0XZ(binIndex * m_theta0XZBinSize);
264 const CartesianVector peakDirection(std::cos(theta0XZ), 0.f, std::sin(theta0XZ));
265
266 peakDirectionVector.push_back(peakDirection);
267 }
268}
269
270//------------------------------------------------------------------------------------------------------------------------------------------
271
273{
275 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "PathwaySearchRegion", m_pathwaySearchRegion));
276
277 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "Theta0XZBinSize", m_theta0XZBinSize));
278
279 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SmoothingWindow", m_smoothingWindow));
280
282 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "AmbiguousParticleMode", m_ambiguousParticleMode));
283
284 return STATUS_CODE_SUCCESS;
285}
286
287} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the algorithm tool class.
Header file for the geometry helper class.
Header file for the pfo helper class.
Header file for the peak direction finder tool class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
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.
int m_smoothingWindow
On each side, the number of neighbouring bins with which each bin is averaged.
void GetAngularExtrema(const pandora::CaloHitList &showerHitList, const pandora::CartesianVector &nuVertex2D, float &lowestTheta, float &highestTheta) const
Determine the angle (from the +ve drift-axis) of the shower cone boundaries (originating from the nu ...
void SmoothAngularDecompositionMap(AngularDecompositionMap &angularDecompositionMap) const
Smooth the ROI angular angular distribution.
bool m_ambiguousParticleMode
Whether to find the initial pathway direction of the shower or of the other event particles.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
void CollectHitsWithinExtrema(const pandora::CaloHitList *const pViewHitList, const pandora::CartesianVector &nuVertex2D, const float lowestTheta, const float highestTheta, pandora::CaloHitList &viewROIHits) const
Collect the hits that lie within the initial shower cone (originating from the nu vertex)
float m_theta0XZBinSize
The angular distribution bin size.
void RetrievePeakDirections(const AngularDecompositionMap &angularDecompositionMap, pandora::CartesianPointVector &peakDirectionVector) const
Obtain a vector of directions from the angular distribution peaks.
float m_pathwaySearchRegion
The initial shower cone distance.
void FillAngularDecompositionMap(const pandora::CaloHitList &viewShowerHitList, const pandora::CartesianVector &nuVertex2D, AngularDecompositionMap &angularDecompositionMap) const
Determine the angular distribution of the ROI hits.
pandora::StatusCode Run(const pandora::ParticleFlowObject *const pShowerPfo, const pandora::CartesianVector &nuVertex3D, const pandora::CaloHitList *const pViewHitList, const pandora::HitType hitType, pandora::CartesianPointVector &peakDirectionVector)
void CollectHitsWithinROI(const pandora::CaloHitList &showerHitList, const pandora::CaloHitList *const pViewHitList, const pandora::CartesianVector &nuVertex2D, pandora::CaloHitList &viewROIHits) const
Collect the 2D hits within a region of interest (m_ambiguousParticleMode ? hits not in the shower : h...
CaloHit class.
Definition CaloHit.h:26
CartesianVector class.
float GetMagnitudeSquared() const
Get the magnitude squared.
float GetZ() const
Get the cartesian z coordinate.
float GetOpeningAngle(const CartesianVector &rhs) const
Get the opening angle of the cartesian vector with respect to a second cartesian vector.
ParticleFlowObject class.
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
HitType
Calorimeter hit type enum.
std::vector< int > IntVector
std::vector< CartesianVector > CartesianPointVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.