Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
LArThreeDSlidingFitResult.cc
Go to the documentation of this file.
1
10
11#include "Objects/Cluster.h"
12
15
17
18#include <algorithm>
19#include <cmath>
20#include <limits>
21
22using namespace pandora;
23
24namespace lar_content
25{
26
27template <typename T>
28ThreeDSlidingFitResult::ThreeDSlidingFitResult(const T *const pT, const unsigned int layerWindow, const float layerPitch) :
29 m_primaryAxis(ThreeDSlidingFitResult::GetPrimaryAxis(pT, layerPitch)),
30 m_axisIntercept(m_primaryAxis.GetPosition()),
31 m_axisDirection(m_primaryAxis.GetMomentum()),
32 m_firstOrthoDirection(ThreeDSlidingFitResult::GetSeedDirection(m_axisDirection).GetCrossProduct(m_axisDirection).GetUnitVector()),
33 m_secondOrthoDirection(m_axisDirection.GetCrossProduct(m_firstOrthoDirection).GetUnitVector()),
34 m_firstFitResult(TwoDSlidingFitResult(pT, layerWindow, layerPitch, m_axisIntercept, m_axisDirection, m_firstOrthoDirection)),
35 m_secondFitResult(TwoDSlidingFitResult(pT, layerWindow, layerPitch, m_axisIntercept, m_axisDirection, m_secondOrthoDirection)),
36 m_minLayer(std::max(m_firstFitResult.GetMinLayer(), m_secondFitResult.GetMinLayer())),
37 m_maxLayer(std::min(m_firstFitResult.GetMaxLayer(), m_secondFitResult.GetMaxLayer())),
38 m_minLayerPosition(0.f, 0.f, 0.f),
39 m_maxLayerPosition(0.f, 0.f, 0.f),
40 m_minLayerDirection(0.f, 0.f, 0.f),
41 m_maxLayerDirection(0.f, 0.f, 0.f)
42{
44 throw StatusCodeException(STATUS_CODE_NOT_INITIALIZED);
45
46 const float minL(m_firstFitResult.GetL(m_minLayer));
47 const float maxL(m_firstFitResult.GetL(m_maxLayer));
48
49 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetGlobalFitPosition(minL, m_minLayerPosition));
50 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetGlobalFitPosition(maxL, m_maxLayerPosition));
51 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetGlobalFitDirection(minL, m_minLayerDirection));
52 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetGlobalFitDirection(maxL, m_maxLayerDirection));
53}
54
55//------------------------------------------------------------------------------------------------------------------------------------------
56
61
62//------------------------------------------------------------------------------------------------------------------------------------------
63
65{
66 const int firstLayer(m_firstFitResult.GetMinLayer());
67 const int secondLayer(m_secondFitResult.GetMinLayer());
68
69 return std::min(firstLayer, secondLayer);
70}
71
72//------------------------------------------------------------------------------------------------------------------------------------------
73
75{
76 const int firstLayer(m_firstFitResult.GetMaxLayer());
77 const int secondLayer(m_secondFitResult.GetMaxLayer());
78
79 return std::max(firstLayer, secondLayer);
80}
81
82//------------------------------------------------------------------------------------------------------------------------------------------
83
85{
86 const float firstRms(m_firstFitResult.GetMinLayerRms());
87 const float secondRms(m_secondFitResult.GetMinLayerRms());
88
89 return std::sqrt(firstRms * firstRms + secondRms * secondRms);
90}
91
92//------------------------------------------------------------------------------------------------------------------------------------------
93
95{
96 const float firstRms(m_firstFitResult.GetMaxLayerRms());
97 const float secondRms(m_secondFitResult.GetMaxLayerRms());
98
99 return std::sqrt(firstRms * firstRms + secondRms * secondRms);
100}
101
102//------------------------------------------------------------------------------------------------------------------------------------------
103
104float ThreeDSlidingFitResult::GetFitRms(const float rL) const
105{
106 const float firstRms(m_firstFitResult.GetFitRms(rL));
107 const float secondRms(m_secondFitResult.GetFitRms(rL));
108
109 return std::sqrt(firstRms * firstRms + secondRms * secondRms);
110}
111
112//------------------------------------------------------------------------------------------------------------------------------------------
113
118
119//------------------------------------------------------------------------------------------------------------------------------------------
120
122{
123 // Check that input coordinates are between first and last layers
124 const int layer1(m_firstFitResult.GetLayer(rL));
125 const int layer2(m_secondFitResult.GetLayer(rL));
126
127 if (std::min(layer1, layer2) < m_minLayer || std::max(layer1, layer2) > m_maxLayer)
128 return STATUS_CODE_INVALID_PARAMETER;
129
130 // Get local positions from each sliding fit (TODO: Make this more efficient)
131 CartesianVector firstPosition(0.f, 0.f, 0.f), secondPosition(0.f, 0.f, 0.f);
132 const StatusCode statusCode1(m_firstFitResult.GetGlobalFitPosition(rL, firstPosition));
133
134 if (STATUS_CODE_SUCCESS != statusCode1)
135 return statusCode1;
136
137 const StatusCode statusCode2(m_secondFitResult.GetGlobalFitPosition(rL, secondPosition));
138
139 if (STATUS_CODE_SUCCESS != statusCode2)
140 return statusCode2;
141
142 float rL1(0.f), rT1(0.f), rL2(0.f), rT2(0.f);
143 m_firstFitResult.GetLocalPosition(firstPosition, rL1, rT1);
144 m_secondFitResult.GetLocalPosition(secondPosition, rL2, rT2);
145
146 // Combine local positions to give an overall global direction
147 this->GetGlobalPosition(rL, rT1, rT2, position);
148
149 return STATUS_CODE_SUCCESS;
150}
151
152//------------------------------------------------------------------------------------------------------------------------------------------
153
155{
156 // Check that input coordinates are between first and last layers
157 const int layer1(m_firstFitResult.GetLayer(rL));
158 const int layer2(m_secondFitResult.GetLayer(rL));
159
160 if (std::min(layer1, layer2) < m_minLayer || std::max(layer1, layer2) > m_maxLayer)
161 return STATUS_CODE_INVALID_PARAMETER;
162
163 // Get local directions from each sliding fit (TODO: Make this more efficient)
164 CartesianVector firstDirection(0.f, 0.f, 0.f), secondDirection(0.f, 0.f, 0.f);
165 const StatusCode statusCode1(m_firstFitResult.GetGlobalFitDirection(rL, firstDirection));
166
167 if (STATUS_CODE_SUCCESS != statusCode1)
168 return statusCode1;
169
170 const StatusCode statusCode2(m_secondFitResult.GetGlobalFitDirection(rL, secondDirection));
171
172 if (STATUS_CODE_SUCCESS != statusCode2)
173 return statusCode2;
174
175 float dTdL1(0.f), dTdL2(0.f);
176 m_firstFitResult.GetLocalDirection(firstDirection, dTdL1);
177 m_secondFitResult.GetLocalDirection(secondDirection, dTdL2);
178
179 // Combine local directions to give an overall global direction
180 this->GetGlobalDirection(dTdL1, dTdL2, direction);
181
182 return STATUS_CODE_SUCCESS;
183}
184
185//------------------------------------------------------------------------------------------------------------------------------------------
186
187void ThreeDSlidingFitResult::GetGlobalPosition(const float rL, const float rT1, const float rT2, CartesianVector &position) const
188{
190}
191
192//------------------------------------------------------------------------------------------------------------------------------------------
193
194void ThreeDSlidingFitResult::GetGlobalDirection(const float dTdL1, const float dTdL2, CartesianVector &direction) const
195{
196 const float pL(1.f / std::sqrt(1.f + dTdL1 * dTdL1 + dTdL2 * dTdL2));
197 const float pT1(dTdL1 / std::sqrt(1.f + dTdL1 * dTdL1 + dTdL2 * dTdL2));
198 const float pT2(dTdL2 / std::sqrt(1.f + dTdL1 * dTdL1 + dTdL2 * dTdL2));
199
200 CartesianVector globalCoordinates(0.f, 0.f, 0.f);
201 this->GetGlobalPosition(pL, pT1, pT2, globalCoordinates);
202 direction = (globalCoordinates - m_axisIntercept).GetUnitVector();
203}
204
205//------------------------------------------------------------------------------------------------------------------------------------------
206
207TrackState ThreeDSlidingFitResult::GetPrimaryAxis(const Cluster *const pCluster, const float layerPitch)
208{
209 CartesianPointVector pointVector;
210 LArClusterHelper::GetCoordinateVector(pCluster, pointVector);
211 return ThreeDSlidingFitResult::GetPrimaryAxis(&pointVector, layerPitch);
212}
213
214//------------------------------------------------------------------------------------------------------------------------------------------
215
216TrackState ThreeDSlidingFitResult::GetPrimaryAxis(const CartesianPointVector *const pPointVector, const float layerPitch)
217{
218 if (pPointVector->size() < 2)
219 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
220
221 CartesianVector centroid(0.f, 0.f, 0.f);
223 LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
224 LArPcaHelper::RunPca(*pPointVector, centroid, eigenValues, eigenVecs);
225
226 float minProjection(std::numeric_limits<float>::max());
227 CartesianVector fitDirection(eigenVecs.at(0));
228
229 // By convention, the primary axis has a positive z-component.
230 // However, downstream algorithms should be independent of this convention.
231 if (fitDirection.GetZ() < 0.f)
232 fitDirection *= -1.f;
233
234 for (const CartesianVector &coordinate : *pPointVector)
235 minProjection = std::min(minProjection, fitDirection.GetDotProduct(coordinate - centroid));
236
237 // Define layers based on centroid rather than individual extremal hits
238 const float fitProjection(layerPitch * std::floor(minProjection / layerPitch));
239
240 return TrackState(centroid + (fitDirection * fitProjection), fitDirection);
241}
242
243//------------------------------------------------------------------------------------------------------------------------------------------
244
246{
247 const float px(std::fabs(axisDirection.GetX()));
248 const float py(std::fabs(axisDirection.GetY()));
249 const float pz(std::fabs(axisDirection.GetZ()));
250
251 if (px < std::min(py, pz) + std::numeric_limits<float>::epsilon())
252 {
253 return CartesianVector(1.f, 0.f, 0.f);
254 }
255
256 if (py < std::min(pz, px) + std::numeric_limits<float>::epsilon())
257 {
258 return CartesianVector(0.f, 1.f, 0.f);
259 }
260
261 if (pz < std::min(px, py) + std::numeric_limits<float>::epsilon())
262 {
263 return CartesianVector(0.f, 0.f, 1.f);
264 }
265
266 throw StatusCodeException(STATUS_CODE_FAILURE);
267}
268
269//------------------------------------------------------------------------------------------------------------------------------------------
270//------------------------------------------------------------------------------------------------------------------------------------------
271
272template ThreeDSlidingFitResult::ThreeDSlidingFitResult(const pandora::Cluster *const, const unsigned int, const float);
273template ThreeDSlidingFitResult::ThreeDSlidingFitResult(const pandora::CartesianPointVector *const, const unsigned int, const float);
274
275} // namespace lar_content
Header file for the cluster class.
Header file for the cluster fit helper class.
Header file for the cluster helper class.
Header file for the principal curve analysis helper class.
Header file for the lar three dimensional sliding fit result class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
static void GetCoordinateVector(const pandora::Cluster *const pCluster, pandora::CartesianPointVector &coordinateVector)
Get vector of hit coordinates from an input cluster.
std::vector< pandora::CartesianVector > EigenVectors
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...
const TwoDSlidingFitResult m_firstFitResult
The first sliding fit result.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
float GetMinLayerRms() const
Get rms at minimum layer.
const TwoDSlidingFitResult m_secondFitResult
The second sliding fit result.
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
pandora::CartesianVector m_minLayerDirection
The global direction at the minimum combined layer.
const int m_minLayer
The minimum combined layer.
pandora::CartesianVector m_maxLayerDirection
The global direction at the maximum combined layer.
const pandora::CartesianVector m_axisIntercept
The axis intercept position.
float GetFitRms(const float rL) const
Get fit rms for a given longitudinal coordinate.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
float GetLongitudinalDisplacement(const pandora::CartesianVector &position) const
Get longitudinal projection onto primary axis.
const pandora::Cluster * GetCluster() const
Get the address of the cluster.
const int m_maxLayer
The maximum combined layer.
const pandora::CartesianVector m_secondOrthoDirection
The orthogonal direction vector.
pandora::CartesianVector m_minLayerPosition
The global position at the minimum combined layer.
pandora::StatusCode GetGlobalFitDirection(const float rL, pandora::CartesianVector &direction) const
Get global fit direction for a given longitudinal coordinate.
const pandora::CartesianVector m_axisDirection
The axis direction vector.
float GetMaxLayerRms() const
Get rms at maximum layer.
static pandora::TrackState GetPrimaryAxis(const pandora::Cluster *const pCluster, const float slidingFitLayerPitch)
Calculate the position and direction of the primary axis.
void GetGlobalDirection(const float dTdL1, const float dTdL2, pandora::CartesianVector &direction) const
Get global direction coordinates for a given pair of sliding linear fit gradients.
pandora::CartesianVector m_maxLayerPosition
The global position at the maximum combined layer.
const pandora::CartesianVector m_firstOrthoDirection
The orthogonal direction vector.
static pandora::CartesianVector GetSeedDirection(const pandora::CartesianVector &axisDirection)
Generate a seed vector to be used in calculating the orthogonal axes.
void GetGlobalPosition(const float rL, const float rT1, const float rT2, pandora::CartesianVector &position) const
Get global coordinates for a given pair of sliding linear fit coordinates.
ThreeDSlidingFitResult(const T *const pT, const unsigned int slidingFitWindow, const float slidingFitLayerPitch)
Constructor.
void GetLocalDirection(const pandora::CartesianVector &direction, float &dTdL) const
Get local sliding fit gradient for a given global direction.
float GetMaxLayerRms() const
Get rms at maximum layer.
float GetL(const int layer) const
Get longitudinal coordinate for a given sliding linear fit layer number.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
pandora::StatusCode GetGlobalFitPosition(const float rL, pandora::CartesianVector &position) const
Get global fit position for a given longitudinal coordinate.
float GetMinLayerRms() const
Get rms at minimum layer.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
float GetFitRms(const float rL) const
Get fit rms for a given longitudinal coordinate.
pandora::StatusCode GetGlobalFitDirection(const float rL, pandora::CartesianVector &direction) const
Get global fit direction for a given longitudinal coordinate.
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
int GetLayer(const float rL) const
Get layer number for given sliding linear fit longitudinal coordinate.
CartesianVector class.
float GetX() const
Get the cartesian x coordinate.
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 GetY() const
Get the cartesian y coordinate.
Cluster class.
Definition Cluster.h:31
StatusCodeException class.
TrackState class.
Definition TrackState.h:22
std::vector< CartesianVector > CartesianPointVector
StatusCode
The StatusCode enum.