LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
LArPointingClusterHelper.cc
Go to the documentation of this file.
1 
11 
12 using namespace pandora;
13 
14 namespace lar_content
15 {
16 
17 float LArPointingClusterHelper::GetLengthSquared(const LArPointingCluster &pointingCluster)
18 {
19  const LArPointingCluster::Vertex &innerVertex(pointingCluster.GetInnerVertex());
20  const LArPointingCluster::Vertex &outerVertex(pointingCluster.GetOuterVertex());
21  return (innerVertex.GetPosition() - outerVertex.GetPosition()).GetMagnitudeSquared();
22 }
23 
24 //------------------------------------------------------------------------------------------------------------------------------------------
25 
26 float LArPointingClusterHelper::GetLength(const LArPointingCluster &pointingCluster)
27 {
28  return std::sqrt(LArPointingClusterHelper::GetLengthSquared(pointingCluster));
29 }
30 
31 //------------------------------------------------------------------------------------------------------------------------------------------
32 
33 bool LArPointingClusterHelper::IsNode(const CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex,
34  const float minLongitudinalDistance, const float maxTransverseDistance)
35 {
36  float rL(0.f), rT(0.f);
37  LArPointingClusterHelper::GetImpactParameters(daughterVertex.GetPosition(), daughterVertex.GetDirection(), parentVertex, rL, rT);
38 
39  if (std::fabs(rL) > std::fabs(minLongitudinalDistance) || rT > maxTransverseDistance)
40  return false;
41 
42  return true;
43 }
44 
45 //------------------------------------------------------------------------------------------------------------------------------------------
46 
47 bool LArPointingClusterHelper::IsEmission(const CartesianVector &parentVertex, const LArPointingCluster::Vertex &daughterVertex,
48  const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance)
49 {
50  float rL(0.f), rT(0.f);
51  LArPointingClusterHelper::GetImpactParameters(daughterVertex.GetPosition(), daughterVertex.GetDirection(), parentVertex, rL, rT);
52 
53  if (std::fabs(rL) > std::fabs(minLongitudinalDistance) && (rL < 0 || rL > maxLongitudinalDistance))
54  return false;
55 
56  const float tanSqTheta(std::pow(std::tan(M_PI * angularAllowance / 180.f), 2.0));
57 
58  if (rT * rT > maxTransverseDistance * maxTransverseDistance + rL * rL * tanSqTheta)
59  return false;
60 
61  return true;
62 }
63 
64 //------------------------------------------------------------------------------------------------------------------------------------------
65 
66 CartesianVector LArPointingClusterHelper::GetProjectedPosition(const CartesianVector &vertexPosition, const CartesianVector &vertexDirection,
67  const pandora::Cluster *const pCluster, const float projectionAngularAllowance)
68 {
69  const CaloHit *pClosestCaloHit(nullptr);
70  float closestDistanceSquared(std::numeric_limits<float>::max());
71  const float minCosTheta(std::cos(M_PI * projectionAngularAllowance / 180.f));
72 
73  for (const OrderedCaloHitList::value_type &layerEntry : pCluster->GetOrderedCaloHitList())
74  {
75  for (const CaloHit *const pCaloHit : *layerEntry.second)
76  {
77  const CartesianVector hitProjection(pCaloHit->GetPositionVector() - vertexPosition);
78  const float distanceSquared(hitProjection.GetMagnitudeSquared());
79 
80  if (distanceSquared > std::numeric_limits<float>::epsilon())
81  {
82  // TODO Try to give more weight to on-axis projections
83  if (distanceSquared < closestDistanceSquared)
84  {
85  if (-hitProjection.GetUnitVector().GetDotProduct(vertexDirection) > minCosTheta)
86  {
87  pClosestCaloHit = pCaloHit;
88  closestDistanceSquared = distanceSquared;
89  }
90  }
91  }
92  else
93  {
94  return pCaloHit->GetPositionVector();
95  }
96  }
97  }
98 
99  if (pClosestCaloHit)
100  return pClosestCaloHit->GetPositionVector();
101 
102  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
103 }
104 
105 //------------------------------------------------------------------------------------------------------------------------------------------
106 
107 void LArPointingClusterHelper::GetClosestVertices(const bool useX, const bool useY, const bool useZ,
108  const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ,
109  LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
110 {
111  if (pointingClusterI.GetCluster() == pointingClusterJ.GetCluster())
112  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
113 
114  if (!useX && !useY && !useZ)
115  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
116 
117  for (unsigned int useInnerI = 0; useInnerI < 2; ++useInnerI)
118  {
119  const LArPointingCluster::Vertex &vtxI(useInnerI == 1 ? pointingClusterI.GetInnerVertex() : pointingClusterI.GetOuterVertex());
120  const LArPointingCluster::Vertex &endI(useInnerI == 0 ? pointingClusterI.GetInnerVertex() : pointingClusterI.GetOuterVertex());
121 
122  for (unsigned int useInnerJ = 0; useInnerJ < 2; ++useInnerJ)
123  {
124  const LArPointingCluster::Vertex &vtxJ(useInnerJ == 1 ? pointingClusterJ.GetInnerVertex() : pointingClusterJ.GetOuterVertex());
125  const LArPointingCluster::Vertex &endJ(useInnerJ == 0 ? pointingClusterJ.GetInnerVertex() : pointingClusterJ.GetOuterVertex());
126 
127  const float vtxI_vtxJ_dx(useX ? (vtxI.GetPosition().GetX() - vtxJ.GetPosition().GetX()) : 0.f);
128  const float vtxI_vtxJ_dy(useY ? (vtxI.GetPosition().GetY() - vtxJ.GetPosition().GetY()) : 0.f);
129  const float vtxI_vtxJ_dz(useZ ? (vtxI.GetPosition().GetZ() - vtxJ.GetPosition().GetZ()) : 0.f);
130  const float vtxI_vtxJ(vtxI_vtxJ_dx * vtxI_vtxJ_dx + vtxI_vtxJ_dy * vtxI_vtxJ_dy + vtxI_vtxJ_dz * vtxI_vtxJ_dz);
131 
132  const float vtxI_endJ_dx(useX ? (vtxI.GetPosition().GetX() - endJ.GetPosition().GetX()) : 0.f);
133  const float vtxI_endJ_dy(useY ? (vtxI.GetPosition().GetY() - endJ.GetPosition().GetY()) : 0.f);
134  const float vtxI_endJ_dz(useZ ? (vtxI.GetPosition().GetZ() - endJ.GetPosition().GetZ()) : 0.f);
135  const float vtxI_endJ(vtxI_endJ_dx * vtxI_endJ_dx + vtxI_endJ_dy * vtxI_endJ_dy + vtxI_endJ_dz * vtxI_endJ_dz);
136 
137  const float endI_vtxJ_dx(useX ? (endI.GetPosition().GetX() - vtxJ.GetPosition().GetX()) : 0.f);
138  const float endI_vtxJ_dy(useY ? (endI.GetPosition().GetY() - vtxJ.GetPosition().GetY()) : 0.f);
139  const float endI_vtxJ_dz(useZ ? (endI.GetPosition().GetZ() - vtxJ.GetPosition().GetZ()) : 0.f);
140  const float endI_vtxJ(endI_vtxJ_dx * endI_vtxJ_dx + endI_vtxJ_dy * endI_vtxJ_dy + endI_vtxJ_dz * endI_vtxJ_dz);
141 
142  const float endI_endJ_dx(useX ? (endI.GetPosition().GetX() - endJ.GetPosition().GetX()) : 0.f);
143  const float endI_endJ_dy(useY ? (endI.GetPosition().GetY() - endJ.GetPosition().GetY()) : 0.f);
144  const float endI_endJ_dz(useZ ? (endI.GetPosition().GetZ() - endJ.GetPosition().GetZ()) : 0.f);
145  const float endI_endJ(endI_endJ_dx * endI_endJ_dx + endI_endJ_dy * endI_endJ_dy + endI_endJ_dz * endI_endJ_dz);
146 
147  if ((vtxI_vtxJ < std::min(vtxI_endJ, std::min(endI_vtxJ, endI_endJ))) &&
148  (endI_endJ > std::max(vtxI_endJ, std::max(endI_vtxJ, vtxI_vtxJ))))
149  {
150  closestVertexI = vtxI;
151  closestVertexJ = vtxJ;
152  return;
153  }
154  }
155  }
156 
157  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
158 }
159 
160 //------------------------------------------------------------------------------------------------------------------------------------------
161 
162 void LArPointingClusterHelper::GetClosestVertices(const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ,
163  LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
164 {
165  return LArPointingClusterHelper::GetClosestVertices(true, true, true, pointingClusterI, pointingClusterJ, closestVertexI, closestVertexJ);
166 }
167 
168 //------------------------------------------------------------------------------------------------------------------------------------------
169 
170 void LArPointingClusterHelper::GetClosestVerticesInX(const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ,
171  LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
172 {
173  return LArPointingClusterHelper::GetClosestVertices(true, false, false, pointingClusterI, pointingClusterJ, closestVertexI, closestVertexJ);
174 }
175 
176 //------------------------------------------------------------------------------------------------------------------------------------------
177 
178 void LArPointingClusterHelper::GetClosestVerticesInYZ(const LArPointingCluster &pointingClusterI, const LArPointingCluster &pointingClusterJ,
179  LArPointingCluster::Vertex &closestVertexI, LArPointingCluster::Vertex &closestVertexJ)
180 {
181  return LArPointingClusterHelper::GetClosestVertices(false, true, true, pointingClusterI, pointingClusterJ, closestVertexI, closestVertexJ);
182 }
183 
184 //------------------------------------------------------------------------------------------------------------------------------------------
185 
186 void LArPointingClusterHelper::GetImpactParametersInYZ(const LArPointingCluster::Vertex &initialVertex,
187  const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
188 {
189  if (std::fabs(initialVertex.GetDirection().GetX()) > 1.f - std::numeric_limits<float>::epsilon())
190  throw pandora::StatusCodeException(pandora::STATUS_CODE_NOT_FOUND);
191 
192  const pandora::CartesianVector initialPosition(0.f, initialVertex.GetPosition().GetY(), initialVertex.GetPosition().GetZ());
193  const pandora::CartesianVector initialDirection(0.f, initialVertex.GetDirection().GetY(), initialVertex.GetDirection().GetZ());
194  const pandora::CartesianVector targetPosition(0.f, targetVertex.GetPosition().GetY(), targetVertex.GetPosition().GetZ());
195 
196  return LArPointingClusterHelper::GetImpactParameters(initialPosition, initialDirection.GetUnitVector(),
197  targetPosition, longitudinal, transverse);
198 }
199 
200 //------------------------------------------------------------------------------------------------------------------------------------------
201 
202 void LArPointingClusterHelper::GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex,
203  const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
204 {
205  return LArPointingClusterHelper::GetImpactParameters(pointingVertex.GetPosition(), pointingVertex.GetDirection(),
206  targetVertex.GetPosition(), longitudinal, transverse);
207 }
208 
209 //------------------------------------------------------------------------------------------------------------------------------------------
210 
211 void LArPointingClusterHelper::GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex,
212  const CartesianVector &targetPosition, float &longitudinal, float &transverse)
213 {
214  return LArPointingClusterHelper::GetImpactParameters(pointingVertex.GetPosition(), pointingVertex.GetDirection(),
215  targetPosition, longitudinal, transverse);
216 }
217 
218 //------------------------------------------------------------------------------------------------------------------------------------------
219 
220 void LArPointingClusterHelper::GetImpactParameters(const CartesianVector &initialPosition, const CartesianVector &initialDirection,
221  const CartesianVector &targetPosition, float &longitudinal, float &transverse)
222 {
223  // sign convention for longitudinal distance:
224  // -positive value means initial position is downstream of target position
225  transverse = initialDirection.GetCrossProduct(targetPosition-initialPosition).GetMagnitude();
226  longitudinal = -initialDirection.GetDotProduct(targetPosition-initialPosition);
227 }
228 
229 //------------------------------------------------------------------------------------------------------------------------------------------
230 
231 void LArPointingClusterHelper::GetAverageDirection(const LArPointingCluster::Vertex &firstVertex,
232  const LArPointingCluster::Vertex &secondVertex, CartesianVector &averageDirection)
233 {
234  const Cluster *const pFirstCluster(firstVertex.GetCluster());
235  const Cluster *const pSecondCluster(secondVertex.GetCluster());
236 
237  if (pFirstCluster == pSecondCluster)
238  throw pandora::StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
239 
240  const float energy1(pFirstCluster->GetHadronicEnergy());
241  const float energy2(pSecondCluster->GetHadronicEnergy());
242 
243  if ((energy1 < std::numeric_limits<float>::epsilon()) || (energy2 < std::numeric_limits<float>::epsilon()))
244  throw pandora::StatusCodeException(STATUS_CODE_NOT_ALLOWED);
245 
246  averageDirection = (firstVertex.GetDirection() * energy1 + secondVertex.GetDirection() * energy2).GetUnitVector();
247 }
248 
249 //------------------------------------------------------------------------------------------------------------------------------------------
250 
252  CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
253 {
254  const Cluster *const pFirstCluster(firstVertex.GetCluster());
255  const Cluster *const pSecondCluster(secondVertex.GetCluster());
256 
257  if (pFirstCluster == pSecondCluster)
258  throw pandora::StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
259 
260  LArPointingClusterHelper::GetIntersection(firstVertex.GetPosition(), firstVertex.GetDirection(), secondVertex.GetPosition(),
261  secondVertex.GetDirection(), intersectPosition, firstDisplacement, secondDisplacement );
262 }
263 
264 //------------------------------------------------------------------------------------------------------------------------------------------
265 
266 void LArPointingClusterHelper::GetIntersection(const CartesianVector &a1, const CartesianVector &a2, const CartesianVector &b1,
267  const CartesianVector &b2, CartesianVector &intersectPosition, float &firstDisplacement, float &secondDisplacement)
268 {
269  // note: input lines are r = a1 + P * a2 and r = b1 + Q * b2
270  const float cosTheta = a2.GetDotProduct(b2);
271 
272  // lines must be non-parallel
273  if (1.f - std::fabs(cosTheta) < std::numeric_limits<float>::epsilon())
274  throw pandora::StatusCodeException(STATUS_CODE_NOT_ALLOWED);
275 
276  // calculate the intersection (by minimising the distance between the lines)
277  const float P = ((a2 - b2 * cosTheta).GetDotProduct(b1 - a1)) / (1.f - cosTheta * cosTheta);
278  const float Q = ((a2 * cosTheta - b2).GetDotProduct(b1 - a1)) / (1.f - cosTheta * cosTheta);
279 
280  // position of intersection (or point of closest approach)
281  intersectPosition = (a1 + a2 * P + b1 + b2 * Q) * 0.5f;
282 
283  // displacements of intersection from input vertices
284  firstDisplacement = P;
285  secondDisplacement = Q;
286 }
287 
288 //------------------------------------------------------------------------------------------------------------------------------------------
289 
290 void LArPointingClusterHelper::GetIntersection(const LArPointingCluster::Vertex &vertexCluster, const Cluster *const pTargetCluster,
291  CartesianVector &intersectPosition, float &displacementL, float &displacementT)
292 {
293  displacementT = +std::numeric_limits<float>::max();
294  displacementL = -std::numeric_limits<float>::max();
295 
296  float rL(0.f), rT(0.f);
297  float figureOfMerit(std::numeric_limits<float>::max());
298  float foundIntersection(false);
299 
300  const OrderedCaloHitList &orderedCaloHitList(pTargetCluster->GetOrderedCaloHitList());
301 
302  for (OrderedCaloHitList::const_iterator iter1 = orderedCaloHitList.begin(), iterEnd1 = orderedCaloHitList.end(); iter1 != iterEnd1; ++iter1)
303  {
304  for (CaloHitList::const_iterator iter2 = iter1->second->begin(), iterEnd2 = iter1->second->end(); iter2 != iterEnd2; ++iter2)
305  {
306  const CartesianVector &hitPosition = (*iter2)->GetPositionVector();
307 
308  LArPointingClusterHelper::GetImpactParameters(vertexCluster.GetPosition(), vertexCluster.GetDirection(), hitPosition, rL, rT);
309 
310  if (rT < figureOfMerit)
311  {
312  figureOfMerit = rT;
313 
314  displacementL = rL;
315  displacementT = rT;
316  intersectPosition = hitPosition;
317  foundIntersection = true;
318  }
319  }
320  }
321 
322  if (!foundIntersection)
323  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
324 }
325 
326 
327 //------------------------------------------------------------------------------------------------------------------------------------------
328 
329 LArPointingCluster::Vertex LArPointingClusterHelper::GetBestVertexEstimate(const LArPointingClusterVertexList &vertexList,
330  const LArPointingClusterList &pointingClusterList, const float minLongitudinalDistance, const float maxLongitudinalDistance,
331  const float maxTransverseDistance, const float angularAllowance)
332 {
333  float bestAssociatedEnergy(0.f);
334  LArPointingClusterVertexList::const_iterator bestVertexIter(vertexList.end());
335 
336  for (LArPointingClusterVertexList::const_iterator iter = vertexList.begin(), iterEnd = vertexList.end(); iter != iterEnd; ++iter)
337  {
338  const LArPointingCluster::Vertex &vertex(*iter);
339 
340  LArPointingClusterVertexList associatedVertices;
341  LArPointingClusterHelper::CollectAssociatedClusters(vertex, pointingClusterList, minLongitudinalDistance,
342  maxLongitudinalDistance, maxTransverseDistance, angularAllowance, associatedVertices);
343 
344  const float associatedEnergy(LArPointingClusterHelper::GetAssociatedEnergy(vertex, associatedVertices));
345 
346  if (associatedEnergy > bestAssociatedEnergy)
347  {
348  bestVertexIter = iter;
349  bestAssociatedEnergy = associatedEnergy;
350  }
351  }
352 
353  if (vertexList.end() == bestVertexIter)
354  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
355 
356  return (*bestVertexIter);
357 }
358 
359 //------------------------------------------------------------------------------------------------------------------------------------------
360 
361 void LArPointingClusterHelper::CollectAssociatedClusters(const LArPointingCluster::Vertex &vertex, const LArPointingClusterList &inputList,
362  const float minLongitudinalDistance, const float maxLongitudinalDistance, const float maxTransverseDistance, const float angularAllowance,
363  LArPointingClusterVertexList &outputList)
364 {
365  for (LArPointingClusterList::const_iterator iter = inputList.begin(), iterEnd = inputList.end(); iter != iterEnd; ++iter)
366  {
367  const LArPointingCluster &pointingCluster = *iter;
368  const LArPointingCluster::Vertex &innerVertex = pointingCluster.GetInnerVertex();
369  const LArPointingCluster::Vertex &outerVertex = pointingCluster.GetOuterVertex();
370 
371  const float innerDistanceSquared = (innerVertex.GetPosition() - vertex.GetPosition()).GetMagnitudeSquared();
372  const float outerDistanceSquared = (outerVertex.GetPosition() - vertex.GetPosition()).GetMagnitudeSquared();
373 
374  const LArPointingCluster::Vertex &chosenVertex((innerDistanceSquared < outerDistanceSquared) ? innerVertex : outerVertex);
375 
376  if (LArPointingClusterHelper::IsNode(vertex.GetPosition(), chosenVertex, minLongitudinalDistance, maxTransverseDistance) ||
377  LArPointingClusterHelper::IsEmission(vertex.GetPosition(), chosenVertex, minLongitudinalDistance, maxLongitudinalDistance, maxTransverseDistance, angularAllowance))
378  {
379  outputList.push_back(chosenVertex);
380  }
381  }
382 }
383 
384 //------------------------------------------------------------------------------------------------------------------------------------------
385 
386 float LArPointingClusterHelper::GetAssociatedEnergy(const LArPointingCluster::Vertex &vertex, const LArPointingClusterVertexList &associatedVertices)
387 {
388  float associatedEnergy(0.f);
389 
390  for (LArPointingClusterVertexList::const_iterator iter = associatedVertices.begin(), iterEnd = associatedVertices.end(); iter != iterEnd; ++iter)
391  {
392  const LArPointingCluster::Vertex &clusterVertex(*iter);
393  const Cluster *const pCluster(clusterVertex.GetCluster());
394 
395  const float clusterEnergy(LArClusterHelper::GetEnergyFromLength(pCluster));
396  const float clusterLength(LArClusterHelper::GetLength(pCluster));
397  const float deltaLength(clusterVertex.GetDirection().GetDotProduct(vertex.GetPosition() - clusterVertex.GetPosition()));
398 
399  if (deltaLength < std::numeric_limits<float>::epsilon())
400  {
401  associatedEnergy += clusterEnergy;
402  }
403  else if(deltaLength < clusterLength)
404  {
405  associatedEnergy += clusterEnergy * (1.f - (deltaLength / clusterLength));
406  }
407  }
408 
409  return associatedEnergy;
410 }
411 
412 } // namespace lar_content
std::vector< LArPointingCluster > LArPointingClusterList
LArPointingCluster class.
const pandora::Cluster * GetCluster() const
Get the address of the cluster.
std::pair< float, float > GetIntersection(double Ax, double Ay, double Bx, double By, double Cx, double Cy, double Dx, double Dy)
Definition: Polygon2D.cxx:28
std::vector< LArPointingCluster::Vertex > LArPointingClusterVertexList
TFile f
Definition: plotHisto.C:6
const pandora::Cluster * GetCluster() const
Get the address of the cluster.
#define a2
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
Header file for the cluster helper class.
const Vertex & GetOuterVertex() const
Get the outer vertex.
const Vertex & GetInnerVertex() const
Get the inner vertex.
const pandora::CartesianVector & GetDirection() const
Get the vertex direction.
Int_t min
Definition: plot.C:26
const pandora::CartesianVector & GetPosition() const
Get the vertex position.
#define a1
vertex reconstruction