9 #include "Pandora/AlgorithmHeaders.h" 10 #include "Pandora/AlgorithmTool.h" 22 PeakDirectionFinderTool::PeakDirectionFinderTool() :
23 m_pathwaySearchRegion(10.
f),
24 m_theta0XZBinSize(0.005
f),
26 m_ambiguousParticleMode(false)
33 const CaloHitList *
const pViewHitList,
const HitType hitType, CartesianPointVector &peakDirectionVector)
35 CaloHitList viewShowerHitList;
41 CaloHitList viewROIHits;
44 if (viewROIHits.empty())
45 return STATUS_CODE_NOT_FOUND;
51 if (angularDecompositionMap.empty())
52 return STATUS_CODE_NOT_FOUND;
60 if (peakDirectionVector.empty())
61 return STATUS_CODE_NOT_FOUND;
63 return STATUS_CODE_SUCCESS;
69 const CartesianVector &nuVertex2D, CaloHitList &viewROIHits)
const 73 for (
const CaloHit *
const pCaloHit : *pViewHitList)
75 if (std::find(showerHitList.begin(), showerHitList.end(), pCaloHit) != showerHitList.end())
78 viewROIHits.push_back(pCaloHit);
83 float lowestTheta(std::numeric_limits<float>::max()), highestTheta((-1.
f) * std::numeric_limits<float>::max());
93 const CaloHitList &showerHitList,
const CartesianVector &nuVertex2D,
float &lowestTheta,
float &highestTheta)
const 95 lowestTheta = std::numeric_limits<float>::max();
96 highestTheta = (-1.f) * std::numeric_limits<float>::max();
98 const CartesianVector xAxis(1.
f, 0.
f, 0.
f);
100 for (
const CaloHit *
const pCaloHit : showerHitList)
102 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
103 const CartesianVector displacementVector(hitPosition - nuVertex2D);
105 float theta0XZ(xAxis.GetOpeningAngle(displacementVector));
107 if (displacementVector.GetZ() < 0.f)
108 theta0XZ = (2.0 * M_PI) - theta0XZ;
110 if (theta0XZ < lowestTheta)
111 lowestTheta = theta0XZ;
113 if (theta0XZ > highestTheta)
114 highestTheta = theta0XZ;
121 const float lowestTheta,
const float highestTheta, CaloHitList &viewROIHits)
const 123 const CartesianVector xAxis(1.
f, 0.
f, 0.
f);
125 for (
const CaloHit *
const pCaloHit : *pViewHitList)
127 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
128 const CartesianVector displacementVector(hitPosition - nuVertex2D);
130 float theta0XZ(xAxis.GetOpeningAngle(displacementVector));
132 if (displacementVector.GetZ() < 0.f)
133 theta0XZ = (2.0 * M_PI) - theta0XZ;
135 if ((theta0XZ < lowestTheta) || (theta0XZ > highestTheta))
138 viewROIHits.push_back(pCaloHit);
145 const CaloHitList &viewShowerHitList,
const CartesianVector &nuVertex2D,
AngularDecompositionMap &angularDecompositionMap)
const 147 const CartesianVector xAxis(1.
f, 0.
f, 0.
f);
149 for (
const CaloHit *
const pCaloHit : viewShowerHitList)
151 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
152 const CartesianVector displacementVector(hitPosition - nuVertex2D);
157 float theta0XZ(xAxis.GetOpeningAngle(displacementVector));
159 if (displacementVector.GetZ() < 0.f)
164 if (angularDecompositionMap.find(theta0XZFactor) == angularDecompositionMap.end())
165 angularDecompositionMap[theta0XZFactor] = 1;
167 angularDecompositionMap[theta0XZFactor] += 1;
180 angularDecompositionMap.clear();
182 for (
const auto &entry : angularDecompositionMapTemp)
185 const int currentBin(entry.first);
187 for (
int binOffset = loopMin; binOffset <= loopMax; ++binOffset)
189 const int contributingBin = currentBin + binOffset;
190 total += (angularDecompositionMapTemp.find(contributingBin) == angularDecompositionMapTemp.end())
192 : angularDecompositionMapTemp.at(contributingBin);
195 angularDecompositionMap[currentBin] = total /
static_cast<float>((2.0 *
m_smoothingWindow) + 1);
205 for (
const auto &entry : angularDecompositionMap)
206 orderedBinIndexVector.push_back(entry.first);
210 std::sort(orderedBinIndexVector.begin(), orderedBinIndexVector.end(),
211 [&angularDecompositionMap](
const int a,
const int b) ->
bool 213 const float aWeight(angularDecompositionMap.at(a));
214 const float bWeight(angularDecompositionMap.at(b));
216 if (std::fabs(aWeight - bWeight) < std::numeric_limits<float>::epsilon())
219 return aWeight > bWeight;
222 for (
int binIndex : orderedBinIndexVector)
224 const float binWeight(angularDecompositionMap.at(binIndex));
226 int precedingBin(binIndex - 1);
227 bool foundPreceeding(
false);
229 while (!foundPreceeding)
231 if ((angularDecompositionMap.find(precedingBin) == angularDecompositionMap.end()) ||
232 (std::fabs(angularDecompositionMap.at(precedingBin) - angularDecompositionMap.at(binIndex)) > std::numeric_limits<float>::epsilon()))
234 foundPreceeding =
true;
241 int followingBin(binIndex + 1);
242 bool foundFollowing(
false);
244 while (!foundFollowing)
246 if ((angularDecompositionMap.find(followingBin) == angularDecompositionMap.end()) ||
247 (std::fabs(angularDecompositionMap.at(followingBin) - angularDecompositionMap.at(binIndex)) > std::numeric_limits<float>::epsilon()))
249 foundFollowing =
true;
256 const float precedingBinWeight(
257 angularDecompositionMap.find(precedingBin) == angularDecompositionMap.end() ? 0.f : angularDecompositionMap.at(precedingBin));
258 const float followingBinWeight(
259 angularDecompositionMap.find(followingBin) == angularDecompositionMap.end() ? 0.f : angularDecompositionMap.at(followingBin));
261 if ((binWeight < precedingBinWeight) || (binWeight < followingBinWeight))
266 const CartesianVector peakDirection(std::cos(theta0XZ), 0.
f, std::sin(theta0XZ));
268 peakDirectionVector.push_back(peakDirection);
276 PANDORA_RETURN_RESULT_IF_AND_IF(
277 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"PathwaySearchRegion",
m_pathwaySearchRegion));
279 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"Theta0XZBinSize",
m_theta0XZBinSize));
281 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SmoothingWindow",
m_smoothingWindow));
283 PANDORA_RETURN_RESULT_IF_AND_IF(
284 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"AmbiguousParticleMode",
m_ambiguousParticleMode));
286 return STATUS_CODE_SUCCESS;
Header file for the pfo helper class.
float m_theta0XZBinSize
The angular distribution bin size.
void FillAngularDecompositionMap(const pandora::CaloHitList &viewShowerHitList, const pandora::CartesianVector &nuVertex2D, AngularDecompositionMap &angularDecompositionMap) const
Determine the angular distribution of the ROI hits.
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...
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 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) ...
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
int m_smoothingWindow
On each side, the number of neighbouring bins with which each bin is averaged.
std::vector< int > IntVector
std::map< int, float > AngularDecompositionMap
float m_pathwaySearchRegion
The initial shower cone distance.
Header file for the geometry helper class.
void SmoothAngularDecompositionMap(AngularDecompositionMap &angularDecompositionMap) const
Smooth the ROI angular angular distribution.
void RetrievePeakDirections(const AngularDecompositionMap &angularDecompositionMap, pandora::CartesianPointVector &peakDirectionVector) const
Obtain a vector of directions from the angular distribution peaks.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
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 ...
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.
bool m_ambiguousParticleMode
Whether to find the initial pathway direction of the shower or of the other event particles...