Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
UndershootTracksTool.cc
Go to the documentation of this file.
1
10
14
16
18
19using namespace pandora;
20
21namespace lar_content
22{
23
26 m_splitMode(false),
27 m_maxTransverseImpactParameter(5.f),
28 m_minImpactParameterCosTheta(0.5f),
29 m_cosThetaCutForKinkSearch(0.75f)
30{
31}
32
33//------------------------------------------------------------------------------------------------------------------------------------------
34
36 ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const IteratorList &iteratorList, ModificationList &modificationList) const
37{
38 for (IteratorList::const_iterator iIter1 = iteratorList.begin(), iIter1End = iteratorList.end(); iIter1 != iIter1End; ++iIter1)
39 {
40 for (IteratorList::const_iterator iIter2 = iIter1; iIter2 != iIter1End; ++iIter2)
41 {
42 if (iIter1 == iIter2)
43 continue;
44
45 try
46 {
47 const unsigned int nMatchedSamplingPoints1((*iIter1)->GetOverlapResult().GetNMatchedSamplingPoints());
48 const unsigned int nMatchedSamplingPoints2((*iIter2)->GetOverlapResult().GetNMatchedSamplingPoints());
49 IteratorList::const_iterator iIterA((nMatchedSamplingPoints1 >= nMatchedSamplingPoints2) ? iIter1 : iIter2);
50 IteratorList::const_iterator iIterB((nMatchedSamplingPoints1 >= nMatchedSamplingPoints2) ? iIter2 : iIter1);
51
52 Particle particle(*(*iIterA), *(*iIterB));
53 const LArPointingCluster pointingClusterA(pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterA));
54 const LArPointingCluster pointingClusterB(pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterB));
55
56 LArPointingCluster::Vertex vertexA, vertexB;
57 LArPointingClusterHelper::GetClosestVertices(pointingClusterA, pointingClusterB, vertexA, vertexB);
58
59 float transverseAB(std::numeric_limits<float>::max()), transverseBA(std::numeric_limits<float>::max());
60 float longitudinalAB(-std::numeric_limits<float>::max()), longitudinalBA(-std::numeric_limits<float>::max());
61
62 LArPointingClusterHelper::GetImpactParameters(vertexA, vertexB, longitudinalAB, transverseAB);
63 LArPointingClusterHelper::GetImpactParameters(vertexB, vertexA, longitudinalBA, transverseBA);
64
65 if (std::min(longitudinalAB, longitudinalBA) < m_minLongitudinalImpactParameter)
66 continue;
67
68 if (std::min(transverseAB, transverseBA) > m_maxTransverseImpactParameter)
69 continue;
70
71 const float cosTheta(-vertexA.GetDirection().GetCosOpeningAngle(vertexB.GetDirection()));
72
73 if (cosTheta < m_minImpactParameterCosTheta)
74 continue;
75
76 const bool isALowestInX(this->IsALowestInX(pointingClusterA, pointingClusterB));
77 const CartesianVector splitPosition((vertexA.GetPosition() + vertexB.GetPosition()) * 0.5f);
78 const bool isThreeDKink(m_majorityRulesMode ? false : this->IsThreeDKink(pAlgorithm, particle, splitPosition, isALowestInX));
79
80 if (isThreeDKink != m_splitMode)
81 continue;
82
83 // Construct the modification object
84 Modification modification;
85
86 if (m_splitMode)
87 {
88 const TwoDSlidingFitResult &fitResult1(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCommonCluster1));
89 const TwoDSlidingFitResult &fitResult2(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCommonCluster2));
90
91 CartesianVector splitPosition1(0.f, 0.f, 0.f), splitPosition2(0.f, 0.f, 0.f);
92 if ((STATUS_CODE_SUCCESS != fitResult1.GetGlobalFitPositionAtX(splitPosition.GetX(), splitPosition1)) ||
93 (STATUS_CODE_SUCCESS != fitResult2.GetGlobalFitPositionAtX(splitPosition.GetX(), splitPosition2)))
94 {
95 continue;
96 }
97
98 modification.m_splitPositionMap[particle.m_pCommonCluster1].push_back(splitPosition1);
99 modification.m_splitPositionMap[particle.m_pCommonCluster2].push_back(splitPosition2);
100 }
101 else
102 {
103 const bool vertexAIsLowX(vertexA.GetPosition().GetX() < vertexB.GetPosition().GetX());
104 const Cluster *const pLowXCluster(vertexAIsLowX ? particle.m_pClusterA : particle.m_pClusterB);
105 const Cluster *const pHighXCluster(vertexAIsLowX ? particle.m_pClusterB : particle.m_pClusterA);
106 modification.m_clusterMergeMap[pLowXCluster].push_back(pHighXCluster);
107 }
108
109 modification.m_affectedClusters.push_back(particle.m_pClusterA);
110 modification.m_affectedClusters.push_back(particle.m_pClusterB);
111 modification.m_affectedClusters.push_back(particle.m_pCommonCluster1);
112 modification.m_affectedClusters.push_back(particle.m_pCommonCluster2);
113
114 modificationList.push_back(modification);
115 }
116 catch (StatusCodeException &statusCodeException)
117 {
118 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
119 throw statusCodeException;
120
121 continue;
122 }
123 }
124 }
125}
126
127//------------------------------------------------------------------------------------------------------------------------------------------
128
130 const CartesianVector &splitPosition, const bool isALowestInX) const
131{
132 try
133 {
134 const TwoDSlidingFitResult &fitResultCommon1(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCommonCluster1));
135 const TwoDSlidingFitResult &fitResultCommon2(pAlgorithm->GetCachedSlidingFitResult(particle.m_pCommonCluster2));
136 const TwoDSlidingFitResult &lowXFitResult(isALowestInX ? pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterA)
137 : pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterB));
138 const TwoDSlidingFitResult &highXFitResult(isALowestInX ? pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterB)
139 : pAlgorithm->GetCachedSlidingFitResult(particle.m_pClusterA));
140
141 const float minusX(this->GetXSamplingPoint(splitPosition, false, lowXFitResult, fitResultCommon1, fitResultCommon2));
142 const float plusX(this->GetXSamplingPoint(splitPosition, true, highXFitResult, fitResultCommon1, fitResultCommon2));
143 const float splitX(splitPosition.GetX());
144
145 CartesianVector minus1(0.f, 0.f, 0.f), split1(0.f, 0.f, 0.f), plus1(0.f, 0.f, 0.f);
146 CartesianVector minus2(0.f, 0.f, 0.f), split2(0.f, 0.f, 0.f), plus2(0.f, 0.f, 0.f);
147 CartesianVector minus3(0.f, 0.f, 0.f), split3(splitPosition), plus3(0.f, 0.f, 0.f);
148
149 if ((STATUS_CODE_SUCCESS != fitResultCommon1.GetGlobalFitPositionAtX(minusX, minus1)) ||
150 (STATUS_CODE_SUCCESS != fitResultCommon1.GetGlobalFitPositionAtX(splitX, split1)) ||
151 (STATUS_CODE_SUCCESS != fitResultCommon1.GetGlobalFitPositionAtX(plusX, plus1)) ||
152 (STATUS_CODE_SUCCESS != fitResultCommon2.GetGlobalFitPositionAtX(minusX, minus2)) ||
153 (STATUS_CODE_SUCCESS != fitResultCommon2.GetGlobalFitPositionAtX(splitX, split2)) ||
154 (STATUS_CODE_SUCCESS != fitResultCommon2.GetGlobalFitPositionAtX(plusX, plus2)) ||
155 (STATUS_CODE_SUCCESS != lowXFitResult.GetGlobalFitPositionAtX(minusX, minus3)) ||
156 (STATUS_CODE_SUCCESS != highXFitResult.GetGlobalFitPositionAtX(plusX, plus3)))
157 {
158 return false; // majority rules, by default
159 }
160
161 // Extract results
165
166 CartesianVector minus(0.f, 0.f, 0.f), split(0.f, 0.f, 0.f), plus(0.f, 0.f, 0.f);
167 float chi2Minus(std::numeric_limits<float>::max()), chi2Split(std::numeric_limits<float>::max()),
168 chi2Plus(std::numeric_limits<float>::max());
169 LArGeometryHelper::MergeThreePositions3D(this->GetPandora(), hitType1, hitType2, hitType3, minus1, minus2, minus3, minus, chi2Minus);
170 LArGeometryHelper::MergeThreePositions3D(this->GetPandora(), hitType1, hitType2, hitType3, split1, split2, split3, split, chi2Split);
171 LArGeometryHelper::MergeThreePositions3D(this->GetPandora(), hitType1, hitType2, hitType3, plus1, plus2, plus3, plus, chi2Plus);
172
173 // Apply final cuts
174 const CartesianVector minusToSplit((split - minus).GetUnitVector());
175 const CartesianVector splitToPlus((plus - split).GetUnitVector());
176 const float dotProduct(minusToSplit.GetDotProduct(splitToPlus));
177
178 if (dotProduct < m_cosThetaCutForKinkSearch)
179 return true;
180 }
181 catch (StatusCodeException &s)
182 {
183 }
184
185 return false;
186}
187
188//------------------------------------------------------------------------------------------------------------------------------------------
189//------------------------------------------------------------------------------------------------------------------------------------------
190
191UndershootTracksTool::Particle::Particle(const TensorType::Element &elementA, const TensorType::Element &elementB)
192{
193 m_pClusterA = (elementA.GetClusterU() != elementB.GetClusterU())
194 ? elementA.GetClusterU()
195 : (elementA.GetClusterV() != elementB.GetClusterV()) ? elementA.GetClusterV() : elementA.GetClusterW();
196 m_pClusterB = (elementA.GetClusterU() != elementB.GetClusterU())
197 ? elementB.GetClusterU()
198 : (elementA.GetClusterV() != elementB.GetClusterV()) ? elementB.GetClusterV() : elementB.GetClusterW();
199 m_pCommonCluster1 = (elementA.GetClusterU() == elementB.GetClusterU())
200 ? elementA.GetClusterU()
201 : (elementA.GetClusterV() == elementB.GetClusterV()) ? elementA.GetClusterV() : elementA.GetClusterW();
202 m_pCommonCluster2 = ((m_pClusterA != elementA.GetClusterU()) && (m_pCommonCluster1 != elementA.GetClusterU()))
203 ? elementA.GetClusterU()
204 : ((m_pClusterA != elementA.GetClusterV()) && (m_pCommonCluster1 != elementA.GetClusterV()))
205 ? elementA.GetClusterV()
206 : elementA.GetClusterW();
207
209 throw StatusCodeException(STATUS_CODE_FAILURE);
210}
211
212//------------------------------------------------------------------------------------------------------------------------------------------
213//------------------------------------------------------------------------------------------------------------------------------------------
214
216{
217 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SplitMode", m_splitMode));
218
219 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
220 XmlHelper::ReadValue(xmlHandle, "MaxTransverseImpactParameter", m_maxTransverseImpactParameter));
221
222 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
223 XmlHelper::ReadValue(xmlHandle, "MinImpactParameterCosTheta", m_minImpactParameterCosTheta));
224
225 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
226 XmlHelper::ReadValue(xmlHandle, "CosThetaCutForKinkSearch", m_cosThetaCutForKinkSearch));
227
228 return ThreeDKinkBaseTool::ReadSettings(xmlHandle);
229}
230
231} // 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 lar pointing cluster class.
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
Header file for the undershoot tracks tool class.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
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.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
static void GetClosestVertices(const bool useX, const bool useY, const bool useZ, const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ, LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
Given a pair of pointing clusters, receive the closest or farthest pair of vertices.
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
LArPointingCluster class.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
ThreeDKinkBaseTool class.
static bool IsALowestInX(const LArPointingCluster &pointingClusterA, const LArPointingCluster &pointingClusterB)
Whether pointing cluster labelled A extends to lowest x positions (as opposed to that labelled B)
float GetXSamplingPoint(const pandora::CartesianVector &splitPosition1, const bool isForwardInX, const TwoDSlidingFitResult &fitResult1, const TwoDSlidingFitResult &fitResult2, const TwoDSlidingFitResult &fitResult3) const
Get a sampling point in x that is common to sliding linear fit objects in three views.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
pandora::ClusterList m_affectedClusters
The list of affected clusters.
float m_minLongitudinalImpactParameter
The min longitudinal impact parameter for connecting accompanying clusters.
bool m_majorityRulesMode
Whether to run in majority rules mode (always split overshoots, always merge undershoots)
std::vector< Modification > ModificationList
ClusterMergeMap m_clusterMergeMap
The cluster merge map.
SplitPositionMap m_splitPositionMap
The split position map.
std::vector< TensorType::ElementList::const_iterator > IteratorList
pandora::StatusCode GetGlobalFitPositionAtX(const float x, pandora::CartesianVector &position) const
Get global fit position for a given input x coordinate.
const pandora::Cluster * m_pClusterA
Address of non-shared cluster in element A.
const pandora::Cluster * m_pCommonCluster1
Address of the common cluster in view 1.
const pandora::Cluster * m_pClusterB
Address of non-shared cluster in element B.
const pandora::Cluster * m_pCommonCluster2
Address of the common cluster in view 2.
Particle(const TensorType::Element &elementA, const TensorType::Element &elementB)
Constructor.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
float m_maxTransverseImpactParameter
The maximum transverse impact parameter for connecting broken clusters.
void GetIteratorListModifications(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const IteratorList &iteratorList, ModificationList &modificationList) const
Get modification objects for a specific elements of the tensor, identifying required splits and merge...
bool m_splitMode
Whether to run in cluster splitting mode, as opposed to cluster merging mode.
bool IsThreeDKink(ThreeViewTransverseTracksAlgorithm *const pAlgorithm, const Particle &particle, const pandora::CartesianVector &splitPosition, const bool isALowestInX) const
Whether the provided particle is consistent with being a kink, when examined in three dimensions at t...
float m_minImpactParameterCosTheta
The minimum cos theta (angle between vertex directions) for connecting broken clusters.
float m_cosThetaCutForKinkSearch
The cos theta cut used for the kink search in three dimensions.
CartesianVector class.
float GetCosOpeningAngle(const CartesianVector &rhs) const
Get the cosine of the opening angle of the cartesian vector with respect to a second cartesian vector...
float GetX() const
Get the cartesian x coordinate.
float GetDotProduct(const CartesianVector &rhs) const
Get the dot product of the cartesian vector with a second cartesian vector.
Cluster class.
Definition Cluster.h:31
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
StatusCodeException class.
StatusCode GetStatusCode() const
Get status code.
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.
StatusCode
The StatusCode enum.