Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
ShowerSpineFinderTool.cc
Go to the documentation of this file.
1
11
15
17
19
20using namespace pandora;
21
22namespace lar_content
23{
24
26 m_hitThresholdForSpine(7),
27 m_growingFitInitialLength(10.f),
28 m_initialFitDistanceToLine(0.5f),
29 m_minInitialHitsFound(7),
30 m_maxFittingHits(15),
31 m_localSlidingFitWindow(10),
32 m_growingFitSegmentLength(5.f),
33 m_highResolutionSlidingFitWindow(5),
34 m_distanceToLine(0.75f),
35 m_hitConnectionDistance(0.75f)
36{
37}
38
39//------------------------------------------------------------------------------------------------------------------------------------------
40
41StatusCode ShowerSpineFinderTool::Run(const CartesianVector &nuVertex3D, const CaloHitList *const pViewHitList, const HitType hitType,
42 const CartesianVector &peakDirection, CaloHitList &unavailableHitList, CaloHitList &showerSpineHitList)
43{
44 const CartesianVector nuVertex2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), nuVertex3D, hitType));
45
46 this->FindShowerSpine(pViewHitList, nuVertex2D, peakDirection, unavailableHitList, showerSpineHitList);
47
48 // Demand that spine is significant, be lenient here as some have small stubs and a gap
49 if (showerSpineHitList.size() < m_hitThresholdForSpine)
50 return STATUS_CODE_NOT_FOUND;
51
52 return STATUS_CODE_SUCCESS;
53}
54
55//------------------------------------------------------------------------------------------------------------------------------------------
56
57void ShowerSpineFinderTool::FindShowerSpine(const CaloHitList *const pViewHitList, const CartesianVector &nuVertex2D,
58 const CartesianVector &initialDirection, CaloHitList &unavailableHitList, CaloHitList &showerSpineHitList) const
59{
60 // Use initial direction to find seed hits for a starting fit
61 float highestL(0.f);
62 CartesianPointVector runningFitPositionVector;
63
64 for (const CaloHit *const pCaloHit : *pViewHitList)
65 {
66 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
67 const CartesianVector &displacementVector(hitPosition - nuVertex2D);
68 const float l(initialDirection.GetDotProduct(displacementVector));
69 const float t(initialDirection.GetCrossProduct(displacementVector).GetMagnitude());
70
71 if ((l < m_growingFitInitialLength) && (l > 0.f) && (t < m_initialFitDistanceToLine))
72 {
73 if (l > highestL)
74 highestL = l;
75
76 if (std::find(unavailableHitList.begin(), unavailableHitList.end(), pCaloHit) == unavailableHitList.end())
77 {
78 showerSpineHitList.push_back(pCaloHit);
79 }
80
81 runningFitPositionVector.push_back(hitPosition);
82 }
83 }
84
85 // Require significant number of initial hits
86 if (runningFitPositionVector.size() < m_minInitialHitsFound)
87 {
88 showerSpineHitList.clear();
89 return;
90 }
91
92 // Perform a running fit to collect a pathway of hits
93 unsigned int count(0);
94 bool hitsCollected(true);
95 const bool isEndDownstream(initialDirection.GetZ() > 0.f);
96 const float slidingFitPitch(LArGeometryHelper::GetWirePitch(this->GetPandora(), showerSpineHitList.front()->GetHitType()));
97 CartesianVector extrapolatedStartPosition(nuVertex2D), extrapolatedDirection(initialDirection);
98 CartesianVector extrapolatedEndPosition(extrapolatedStartPosition + (extrapolatedDirection * highestL));
99
100 while (hitsCollected)
101 {
102 ++count;
103
104 try
105 {
106 const int excessHitsInFit(runningFitPositionVector.size() - m_maxFittingHits);
107
108 if (excessHitsInFit > 0)
109 {
110 // Remove furthest away hits
111 std::sort(runningFitPositionVector.begin(), runningFitPositionVector.end(),
113
114 for (int i = 0; i < excessHitsInFit; ++i)
115 runningFitPositionVector.erase(std::prev(runningFitPositionVector.end()));
116 }
117
118 const TwoDSlidingFitResult extrapolatedFit(&runningFitPositionVector, m_localSlidingFitWindow, slidingFitPitch);
119
120 extrapolatedStartPosition =
121 count == 1 ? extrapolatedEndPosition
122 : isEndDownstream ? extrapolatedFit.GetGlobalMaxLayerPosition() : extrapolatedFit.GetGlobalMinLayerPosition();
123 extrapolatedDirection =
124 isEndDownstream ? extrapolatedFit.GetGlobalMaxLayerDirection() : extrapolatedFit.GetGlobalMinLayerDirection() * (-1.f);
125 extrapolatedEndPosition = extrapolatedStartPosition + (extrapolatedDirection * m_growingFitSegmentLength);
126
127 hitsCollected = this->CollectSubsectionHits(extrapolatedFit, extrapolatedStartPosition, extrapolatedEndPosition,
128 extrapolatedDirection, isEndDownstream, pViewHitList, runningFitPositionVector, unavailableHitList, showerSpineHitList);
129
130 // If no hits found, as a final effort, reduce the sliding fit window
131 if (!hitsCollected)
132 {
133 const TwoDSlidingFitResult microExtrapolatedFit(&runningFitPositionVector, m_highResolutionSlidingFitWindow, slidingFitPitch);
134
135 extrapolatedStartPosition = count == 1 ? extrapolatedStartPosition
136 : isEndDownstream ? microExtrapolatedFit.GetGlobalMaxLayerPosition()
137 : microExtrapolatedFit.GetGlobalMinLayerPosition();
138 extrapolatedDirection = isEndDownstream ? microExtrapolatedFit.GetGlobalMaxLayerDirection()
139 : microExtrapolatedFit.GetGlobalMinLayerDirection() * (-1.f);
140 extrapolatedEndPosition = extrapolatedStartPosition + (extrapolatedDirection * m_growingFitSegmentLength);
141
142 hitsCollected = this->CollectSubsectionHits(microExtrapolatedFit, extrapolatedStartPosition, extrapolatedEndPosition,
143 extrapolatedDirection, isEndDownstream, pViewHitList, runningFitPositionVector, unavailableHitList, showerSpineHitList);
144 }
145 }
146 catch (const StatusCodeException &)
147 {
148 return;
149 }
150 }
151}
152
153//------------------------------------------------------------------------------------------------------------------------------------------
154
156 const CartesianVector &extrapolatedStartPosition, const CartesianVector &extrapolatedEndPosition,
157 const CartesianVector &extrapolatedDirection, const bool isEndDownstream, const CaloHitList *const pViewHitList,
158 CartesianPointVector &runningFitPositionVector, CaloHitList &unavailableHitList, CaloHitList &showerSpineHitList) const
159{
160 float extrapolatedStartL(0.f), extrapolatedStartT(0.f);
161 extrapolatedFit.GetLocalPosition(extrapolatedStartPosition, extrapolatedStartL, extrapolatedStartT);
162
163 float extrapolatedEndL(0.f), extrapolatedEndT(0.f);
164 extrapolatedFit.GetLocalPosition(extrapolatedEndPosition, extrapolatedEndL, extrapolatedEndT);
165
166 CaloHitList collectedHits;
167
168 for (const CaloHit *const pCaloHit : *pViewHitList)
169 {
170 if (std::find(showerSpineHitList.begin(), showerSpineHitList.end(), pCaloHit) != showerSpineHitList.end())
171 continue;
172
173 if (std::find(unavailableHitList.begin(), unavailableHitList.end(), pCaloHit) != unavailableHitList.end())
174 continue;
175
176 const CartesianVector &hitPosition(pCaloHit->GetPositionVector());
177
178 float hitL(0.f), hitT(0.f);
179 extrapolatedFit.GetLocalPosition(hitPosition, hitL, hitT);
180
181 // Assess whether hit is within section boundaries
182 if (isEndDownstream && ((hitL < extrapolatedStartL) || (hitL > extrapolatedEndL)))
183 continue;
184
185 if (!isEndDownstream && ((hitL > extrapolatedStartL) || (hitL < extrapolatedEndL)))
186 continue;
187
188 // Assess whether hit is close to connecting line - taking account hit width if necessary
189 if (this->IsCloseToLine(hitPosition, extrapolatedStartPosition, extrapolatedDirection, m_distanceToLine))
190 {
191 collectedHits.push_back(pCaloHit);
192 }
193 else
194 {
195 const CartesianVector closestPointInHit(
196 LArHitWidthHelper::GetClosestPointToLine2D(extrapolatedStartPosition, extrapolatedDirection, pCaloHit));
197
198 if (this->IsCloseToLine(closestPointInHit, extrapolatedStartPosition, extrapolatedDirection, m_distanceToLine))
199 collectedHits.push_back(pCaloHit);
200 }
201 }
202
203 const int nInitialHits(showerSpineHitList.size());
204
205 // Now find a continuous path of collected hits
206 this->CollectConnectedHits(collectedHits, extrapolatedStartPosition, extrapolatedDirection, runningFitPositionVector, showerSpineHitList);
207
208 const int nFinalHits(showerSpineHitList.size());
209
210 return (nFinalHits != nInitialHits);
211}
212
213//------------------------------------------------------------------------------------------------------------------------------------------
214
216 const CartesianVector &lineDirection, const float distanceToLine) const
217{
218 const float transverseDistanceFromLine(lineDirection.GetCrossProduct(hitPosition - lineStart).GetMagnitude());
219
220 if (transverseDistanceFromLine > distanceToLine)
221 return false;
222
223 return true;
224}
225
226//------------------------------------------------------------------------------------------------------------------------------------------
227
228void ShowerSpineFinderTool::CollectConnectedHits(const CaloHitList &collectedHits, const CartesianVector &extrapolatedStartPosition,
229 const CartesianVector &extrapolatedDirection, CartesianPointVector &runningFitPositionVector, CaloHitList &showerSpineHitList) const
230{
231 bool found(true);
232
233 while (found)
234 {
235 found = false;
236
237 for (const CaloHit *const pCaloHit : collectedHits)
238 {
239 if (std::find(showerSpineHitList.begin(), showerSpineHitList.end(), pCaloHit) != showerSpineHitList.end())
240 continue;
241
242 CartesianVector hitPosition(pCaloHit->GetPositionVector());
243
244 if (this->GetClosestDistance(hitPosition, runningFitPositionVector) > m_hitConnectionDistance)
245 {
246 if (LArHitWidthHelper::GetClosestDistance(pCaloHit, showerSpineHitList) > m_hitConnectionDistance)
247 continue;
248
249 hitPosition = LArHitWidthHelper::GetClosestPointToLine2D(extrapolatedStartPosition, extrapolatedDirection, pCaloHit);
250 }
251
252 found = true;
253
254 runningFitPositionVector.push_back(hitPosition);
255 showerSpineHitList.push_back(pCaloHit);
256 }
257 }
258}
259
260//------------------------------------------------------------------------------------------------------------------------------------------
261
263{
264 float closestDistanceSqaured(std::numeric_limits<float>::max());
265
266 for (const CartesianVector &testPosition : testPositions)
267 {
268 const float separationSquared((testPosition - position).GetMagnitudeSquared());
269
270 if (separationSquared < closestDistanceSqaured)
271 closestDistanceSqaured = separationSquared;
272 }
273
274 return std::sqrt(closestDistanceSqaured);
275}
276
277//------------------------------------------------------------------------------------------------------------------------------------------
278
280{
282 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitThresholdForSpine", m_hitThresholdForSpine));
283
284 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
285 XmlHelper::ReadValue(xmlHandle, "GrowingFitInitialLength", m_growingFitInitialLength));
286
287 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
288 XmlHelper::ReadValue(xmlHandle, "InitialFitDistanceToLine", m_initialFitDistanceToLine));
289
291 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinInitialHitsFound", m_minInitialHitsFound));
292
293 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxFittingHits", m_maxFittingHits));
294
296 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "LocalSlidingFitWindow", m_localSlidingFitWindow));
297
298 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
299 XmlHelper::ReadValue(xmlHandle, "GrowingFitSegmentLength", m_growingFitSegmentLength));
300
301 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
302 XmlHelper::ReadValue(xmlHandle, "HighResolutionSlidingFitWindow", m_highResolutionSlidingFitWindow));
303
304 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "DistanceToLine", m_distanceToLine));
305
307 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "HitConnectionDistance", m_hitConnectionDistance));
308
309 return STATUS_CODE_SUCCESS;
310}
311
312} // 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 connection pathway helper class.
Header file for the geometry helper class.
Header file for the lar hit width helper class.
Header file for the lar two dimensional sliding fit result 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 float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
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 pandora::CartesianVector GetClosestPointToLine2D(const pandora::CartesianVector &lineStart, const pandora::CartesianVector &lineDirection, const pandora::CaloHit *const pCaloHit)
Consider the hit width to find the closest position of a calo hit to a specified line.
static float GetClosestDistance(const pandora::CaloHit *const pThisCaloHit, const pandora::CaloHitList &caloHitList)
Find the smallest separation between a hit and a list of hits, with the consideration of their hit wi...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
unsigned int m_hitThresholdForSpine
The hit threshold for a significant spine.
float m_growingFitInitialLength
The first step distance.
unsigned int m_localSlidingFitWindow
The standard sliding fit window for spine fits.
unsigned int m_maxFittingHits
The number of hits to consider in the running fit.
float m_initialFitDistanceToLine
The max. proximity to the spine projection for collection in the first step.
bool CollectSubsectionHits(const TwoDSlidingFitResult &extrapolatedFit, const pandora::CartesianVector &extrapolatedStartPosition, const pandora::CartesianVector &extrapolatedEndPosition, const pandora::CartesianVector &extrapolatedDirection, const bool isEndDownstream, const pandora::CaloHitList *const pViewHitList, pandora::CartesianPointVector &runningFitPositionVector, pandora::CaloHitList &unavailableHitList, pandora::CaloHitList &showerSpineHitList) const
Perform a running fit step: collect hits which lie close to the shower spine projection.
bool IsCloseToLine(const pandora::CartesianVector &hitPosition, const pandora::CartesianVector &lineStart, const pandora::CartesianVector &lineDirection, const float distanceToLine) const
Determine whether a hit lies close to the shower spine projection.
void CollectConnectedHits(const pandora::CaloHitList &collectedHits, const pandora::CartesianVector &extrapolatedStartPosition, const pandora::CartesianVector &extrapolatedDirection, pandora::CartesianPointVector &runningFitPositionVector, pandora::CaloHitList &showerSpineHitList) const
Add to the shower spine the connecting hits.
float m_distanceToLine
The max. proximity to the spine projection for collection.
pandora::StatusCode Run(const pandora::CartesianVector &nuVertex3D, const pandora::CaloHitList *const pViewHitList, const pandora::HitType hitType, const pandora::CartesianVector &peakDirection, pandora::CaloHitList &unavailableHitList, pandora::CaloHitList &showerSpineHitList)
unsigned int m_minInitialHitsFound
The min. number of hits collected in the first step for continuation.
unsigned int m_highResolutionSlidingFitWindow
The high resolution sliding fit window for spine fits.
float m_growingFitSegmentLength
The standard step distance.
void FindShowerSpine(const pandora::CaloHitList *const pViewHitList, const pandora::CartesianVector &nuVertex2D, const pandora::CartesianVector &initialDirection, pandora::CaloHitList &unavailableHitList, pandora::CaloHitList &showerSpineHitList) const
Perform a running fit to collect the hits of the shower spine.
float GetClosestDistance(const pandora::CartesianVector &position, const pandora::CartesianPointVector &testPositions) const
Find the smallest distance between a position and a list of other positions.
float m_hitConnectionDistance
The max. separation between connected hits.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
pandora::CartesianVector GetGlobalMinLayerDirection() const
Get global direction corresponding to the fit result in minimum fit layer.
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
pandora::CartesianVector GetGlobalMaxLayerDirection() const
Get global direction corresponding to the fit result in maximum fit layer.
CaloHit class.
Definition CaloHit.h:26
CartesianVector class.
float GetZ() const
Get the cartesian z coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
float GetMagnitude() const
Get the magnitude.
CartesianVector GetCrossProduct(const CartesianVector &rhs) const
Get the cross product of the cartesian vector with a second cartesian vector.
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
StatusCodeException class.
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< CartesianVector > CartesianPointVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.