Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
VertexRefinementAlgorithm.cc
Go to the documentation of this file.
1
10
14
16
17#include <Eigen/Dense>
18
19using namespace pandora;
20
21namespace lar_content
22{
23
25 m_chiSquaredCut(2.f),
26 m_distanceCut(5.f),
27 m_minimumHitsCut(5),
28 m_twoDDistanceCut(10.f)
29{
30}
31
32//------------------------------------------------------------------------------------------------------------------------------------------
33
35{
36 const VertexList *pInputVertexList(nullptr);
37 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pInputVertexList));
38
39 if (!pInputVertexList || pInputVertexList->empty())
40 {
42 std::cout << "VertexRefinementAlgorithm: unable to find current vertex list " << std::endl;
43
44 return STATUS_CODE_SUCCESS;
45 }
46
47 const VertexList *pOutputVertexList(NULL);
48 std::string temporaryListName;
49 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pOutputVertexList, temporaryListName));
50
51 ClusterList clusterListU, clusterListV, clusterListW;
52 this->GetClusterLists(m_inputClusterListNames, clusterListU, clusterListV, clusterListW);
53
54 this->RefineVertices(pInputVertexList, clusterListU, clusterListV, clusterListW);
55
56 if (!pOutputVertexList->empty())
57 {
60 }
61
62 return STATUS_CODE_SUCCESS;
63}
64
65//------------------------------------------------------------------------------------------------------------------------------------------
66
68 const StringVector &inputClusterListNames, ClusterList &clusterListU, ClusterList &clusterListV, ClusterList &clusterListW) const
69{
70 for (const std::string &clusterListName : inputClusterListNames)
71 {
72 const ClusterList *pClusterList(nullptr);
74 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, clusterListName, pClusterList));
75
76 if (!pClusterList || pClusterList->empty())
77 {
79 std::cout << "VertexRefinementAlgorithm: unable to find cluster list " << clusterListName << std::endl;
80
81 continue;
82 }
83
84 const HitType hitType(LArClusterHelper::GetClusterHitType(pClusterList->front()));
85
86 if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
87 throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
88
89 ClusterList &outputClusterList((TPC_VIEW_U == hitType) ? clusterListU : (TPC_VIEW_V == hitType) ? clusterListV : clusterListW);
90 outputClusterList.insert(outputClusterList.end(), pClusterList->begin(), pClusterList->end());
91 }
92}
93
94//------------------------------------------------------------------------------------------------------------------------------------------
95
96void VertexRefinementAlgorithm::RefineVertices(const VertexList *const pVertexList, const ClusterList &clusterListU,
97 const ClusterList &clusterListV, const ClusterList &clusterListW) const
98{
99 for (const Vertex *const pVertex : *pVertexList)
100 {
101 const CartesianVector originalPosition(pVertex->GetPosition());
102
103 const CartesianVector vtxU(
104 this->RefineVertexTwoD(clusterListU, LArGeometryHelper::ProjectPosition(this->GetPandora(), originalPosition, TPC_VIEW_U)));
105 const CartesianVector vtxV(
106 this->RefineVertexTwoD(clusterListV, LArGeometryHelper::ProjectPosition(this->GetPandora(), originalPosition, TPC_VIEW_V)));
107 const CartesianVector vtxW(
108 this->RefineVertexTwoD(clusterListW, LArGeometryHelper::ProjectPosition(this->GetPandora(), originalPosition, TPC_VIEW_W)));
109
110 CartesianVector vtxUV(0.f, 0.f, 0.f), vtxUW(0.f, 0.f, 0.f), vtxVW(0.f, 0.f, 0.f), vtx3D(0.f, 0.f, 0.f), position3D(0.f, 0.f, 0.f);
111 float chi2UV(0.f), chi2UW(0.f), chi2VW(0.f), chi23D(0.f), chi2(0.f);
112
113 LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), TPC_VIEW_U, TPC_VIEW_V, vtxU, vtxV, vtxUV, chi2UV);
114 LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), TPC_VIEW_U, TPC_VIEW_W, vtxU, vtxW, vtxUW, chi2UW);
115 LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), TPC_VIEW_V, TPC_VIEW_W, vtxV, vtxW, vtxVW, chi2VW);
116 LArGeometryHelper::MergeThreePositions3D(this->GetPandora(), TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W, vtxU, vtxV, vtxW, vtx3D, chi23D);
117
118 if (chi2UV < chi2UW && chi2UV < chi2VW && chi2UV < chi23D)
119 {
120 position3D = vtxUV;
121 chi2 = chi2UV;
122 }
123 else if (chi2UW < chi2VW && chi2UW < chi23D)
124 {
125 position3D = vtxUW;
126 chi2 = chi2UW;
127 }
128 else if (chi2VW < chi23D)
129 {
130 position3D = vtxVW;
131 chi2 = chi2VW;
132 }
133 else
134 {
135 position3D = vtx3D;
136 chi2 = chi23D;
137 }
138
139 if (chi2 > m_chiSquaredCut)
140 position3D = originalPosition;
141
142 if ((position3D - originalPosition).GetMagnitude() > m_distanceCut)
143 position3D = originalPosition;
144
145 PandoraContentApi::Vertex::Parameters parameters;
146 parameters.m_position = position3D;
147 parameters.m_vertexLabel = VERTEX_INTERACTION;
148 parameters.m_vertexType = VERTEX_3D;
149
150 const Vertex *pNewVertex(NULL);
151 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pNewVertex));
152 }
153}
154
155//------------------------------------------------------------------------------------------------------------------------------------------
156
158{
159 CartesianPointVector intercepts, directions;
160 FloatVector weights;
161
162 for (const Cluster *const pCluster : clusterList)
163 {
164 if (LArClusterHelper::GetClosestDistance(originalVtxPos, pCluster) > 10)
165 continue;
166
167 if (pCluster->GetNCaloHits() < m_minimumHitsCut)
168 continue;
169
170 CartesianVector centroid(0.f, 0.f, 0.f);
171 LArPcaHelper::EigenValues eigenValues(0.f, 0.f, 0.f);
172 LArPcaHelper::EigenVectors eigenVectors;
173 CartesianPointVector pointVector;
174
175 LArClusterHelper::GetCoordinateVector(pCluster, pointVector);
176 LArPcaHelper::RunPca(pointVector, centroid, eigenValues, eigenVectors);
177
178 intercepts.push_back(LArClusterHelper::GetClosestPosition(originalVtxPos, pCluster));
179 directions.push_back(eigenVectors.at(0).GetUnitVector());
180 weights.push_back(1.f / ((LArClusterHelper::GetClosestPosition(originalVtxPos, pCluster) - originalVtxPos).GetMagnitudeSquared() + 1));
181 }
182
183 CartesianVector newVtxPos(originalVtxPos);
184 if (intercepts.size() > 1)
185 GetBestFitPoint(intercepts, directions, weights, newVtxPos);
186
187 if ((newVtxPos - originalVtxPos).GetMagnitude() > m_twoDDistanceCut)
188 return originalVtxPos;
189
190 return newVtxPos;
191}
192
193//------------------------------------------------------------------------------------------------------------------------------------------
194
196 const FloatVector &weights, CartesianVector &bestFitPoint) const
197{
198 const int n(intercepts.size());
199
200 Eigen::VectorXd d = Eigen::VectorXd::Zero(3 * n);
201 Eigen::MatrixXd G = Eigen::MatrixXd::Zero(3 * n, n + 3);
202
203 for (int i = 0; i < n; ++i)
204 {
205 d(3 * i) = intercepts[i].GetX() * weights[i];
206 d(3 * i + 1) = intercepts[i].GetY() * weights[i];
207 d(3 * i + 2) = intercepts[i].GetZ() * weights[i];
208
209 G(3 * i, 0) = weights[i];
210 G(3 * i + 1, 1) = weights[i];
211 G(3 * i + 2, 2) = weights[i];
212
213 G(3 * i, i + 3) = -directions[i].GetX();
214 G(3 * i + 1, i + 3) = -directions[i].GetY();
215 G(3 * i + 2, i + 3) = -directions[i].GetZ();
216 }
217
218 if ((G.transpose() * G).determinant() < std::numeric_limits<float>::epsilon())
219 {
220 bestFitPoint = CartesianVector(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
221 return;
222 }
223
224 Eigen::VectorXd m = (G.transpose() * G).inverse() * G.transpose() * d;
225
226 bestFitPoint = CartesianVector(m[0], m[1], m[2]);
227}
228
229//------------------------------------------------------------------------------------------------------------------------------------------
230
232{
233 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputClusterListNames", m_inputClusterListNames));
234
235 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputVertexListName", m_inputVertexListName));
236
237 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputVertexListName", m_outputVertexListName));
238
239 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ChiSquaredCut", m_chiSquaredCut));
240
241 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "DistanceCut", m_distanceCut));
242
243 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinimumHitsCut", m_minimumHitsCut));
244
245 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TwoDDistanceCut", m_twoDDistanceCut));
246
247 return STATUS_CODE_SUCCESS;
248}
249
250} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the cluster helper class.
Header file for the geometry helper class.
Header file for the principal curve analysis helper class.
#define PANDORA_THROW_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:55
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:19
Header file for the vertex refinement algorithm class.
static pandora::StatusCode ReplaceCurrentList(const pandora::Algorithm &algorithm, const std::string &newListName)
Replace the current list with a pre-saved list; use this new list as a permanent replacement for the ...
static pandora::StatusCode CreateTemporaryListAndSetCurrent(const pandora::Algorithm &algorithm, const T *&pT, std::string &temporaryListName)
Create a temporary list and set it to be the current list, enabling object creation.
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static void GetCoordinateVector(const pandora::Cluster *const pCluster, pandora::CartesianPointVector &coordinateVector)
Get vector of hit coordinates from an input cluster.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
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 MergeTwoPositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from two views to give unified 3D position.
static void MergeThreePositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::HitType view3, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, const pandora::CartesianVector &position3, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from three views to give unified 3D position.
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...
void RefineVertices(const pandora::VertexList *const pVertexList, const pandora::ClusterList &clusterListU, const pandora::ClusterList &clusterListV, const pandora::ClusterList &clusterListW) const
Perform the refinement proceduce on a list of vertices.
pandora::StringVector m_inputClusterListNames
The list of input cluster list names.
void GetBestFitPoint(const pandora::CartesianPointVector &intercepts, const pandora::CartesianPointVector &directions, const pandora::FloatVector &weights, pandora::CartesianVector &bestFitPoint) const
Calculate the best fit point of a set of lines using a matrix equation.
std::string m_outputVertexListName
The refined vertex list to be outputted.
pandora::StatusCode Run()
Run the algorithm.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float m_distanceCut
The maximum distance a refined vertex can be from the original position to be kept.
unsigned int m_minimumHitsCut
The minimum size of a cluster to be used in refinement.
float m_twoDDistanceCut
The maximum distance a cluster can be from the original position to be used in refinement.
void GetClusterLists(const pandora::StringVector &inputClusterListNames, pandora::ClusterList &clusterListU, pandora::ClusterList &clusterListV, pandora::ClusterList &clusterListW) const
Get the input cluster lists.
pandora::CartesianVector RefineVertexTwoD(const pandora::ClusterList &clusterList, const pandora::CartesianVector &originalVtxPos) const
Refine the position of a two dimensional projection of a vertex using the clusters in that view.
float m_chiSquaredCut
The maximum chi2 value a refined vertex can have to be kept.
std::string m_inputVertexListName
The initial vertex list.
CartesianVector class.
Cluster class.
Definition Cluster.h:31
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
StatusCodeException class.
Vertex class.
Definition Vertex.h:26
static StatusCode ReadVectorOfValues(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, std::vector< T > &vector)
Read a vector of values from a (space separated) list in an xml element.
Definition XmlHelper.h:229
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.
MANAGED_CONTAINER< const Cluster * > ClusterList
std::vector< std::string > StringVector
std::vector< CartesianVector > CartesianPointVector
std::vector< float > FloatVector
MANAGED_CONTAINER< const Vertex * > VertexList
StatusCode
The StatusCode enum.