CandidateVertexCreationAlgorithm.cc
Go to the documentation of this file.
1 /**
2  * @file larpandoracontent/LArVertex/CandidateVertexCreationAlgorithm.cc
3  *
4  * @brief Implementation of the candidate vertex creation algorithm class.
5  *
6  * $Log: $
7  */
8 
9 #include "Pandora/AlgorithmHeaders.h"
10 
13 
15 
16 #include <utility>
17 
18 using namespace pandora;
19 
20 namespace lar_content
21 {
22 
23 CandidateVertexCreationAlgorithm::CandidateVertexCreationAlgorithm() :
24  m_replaceCurrentVertexList(true),
25  m_slidingFitWindow(20),
26  m_minClusterCaloHits(5),
27  m_minClusterLengthSquared(3.f * 3.f),
28  m_chiSquaredCut(2.f),
29  m_enableEndpointCandidates(true),
30  m_maxEndpointXDiscrepancy(4.f),
31  m_enableCrossingCandidates(false),
32  m_nMaxCrossingCandidates(500),
33  m_maxCrossingXDiscrepancy(0.5f),
34  m_extrapolationNSteps(200),
35  m_extrapolationStepSize(0.1f),
36  m_maxCrossingSeparationSquared(2.f * 2.f),
37  m_minNearbyCrossingDistanceSquared(0.5f * 0.5f),
38  m_reducedCandidates(false),
39  m_selectionCutFactorMax(2.f),
40  m_nClustersPassingMaxCutsPar(26.f)
41 {
42 }
43 
44 //------------------------------------------------------------------------------------------------------------------------------------------
45 
47 {
48  try
49  {
50  ClusterVector clusterVectorU, clusterVectorV, clusterVectorW;
51  this->SelectClusters(clusterVectorU, clusterVectorV, clusterVectorW);
52 
53  const VertexList *pVertexList(NULL);
54  std::string temporaryListName;
55  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, temporaryListName));
56 
58  {
59  this->CreateEndpointCandidates(clusterVectorU, clusterVectorV);
60  this->CreateEndpointCandidates(clusterVectorU, clusterVectorW);
61  this->CreateEndpointCandidates(clusterVectorV, clusterVectorW);
62  }
63 
65  this->CreateCrossingCandidates(clusterVectorU, clusterVectorV, clusterVectorW);
66 
67  if (!pVertexList->empty())
68  {
69  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_outputVertexListName));
70 
72  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Vertex>(*this, m_outputVertexListName));
73  }
74  }
75  catch (StatusCodeException &statusCodeException)
76  {
77  this->TidyUp();
78  throw statusCodeException;
79  }
80 
81  this->TidyUp();
82 
83  return STATUS_CODE_SUCCESS;
84 }
85 
86 //------------------------------------------------------------------------------------------------------------------------------------------
87 
88 void CandidateVertexCreationAlgorithm::SelectClusters(ClusterVector &clusterVectorU, ClusterVector &clusterVectorV, ClusterVector &clusterVectorW)
89 {
90  for (const std::string &clusterListName : m_inputClusterListNames)
91  {
92  const ClusterList *pClusterList(NULL);
93  PANDORA_THROW_RESULT_IF_AND_IF(
94  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, clusterListName, pClusterList));
95 
96  if (!pClusterList || pClusterList->empty())
97  {
98  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
99  std::cout << "CandidateVertexCreationAlgorithm: unable to find cluster list " << clusterListName << std::endl;
100 
101  continue;
102  }
103 
104  const HitType hitType(LArClusterHelper::GetClusterHitType(*(pClusterList->begin())));
105 
106  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
107  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
108 
109  ClusterVector &selectedClusterVector((TPC_VIEW_U == hitType) ? clusterVectorU : (TPC_VIEW_V == hitType) ? clusterVectorV : clusterVectorW);
110 
111  if (!selectedClusterVector.empty())
112  throw StatusCodeException(STATUS_CODE_FAILURE);
113 
114  ClusterVector sortedClusters(pClusterList->begin(), pClusterList->end());
115  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
116 
117  unsigned int nClustersPassingMaxCuts(0);
119  {
120  for (const Cluster *const pCluster : sortedClusters)
121  {
122  float selectionCutFactor(1.f);
123 
124  if (pCluster->GetParticleId() == E_MINUS)
125  selectionCutFactor = m_selectionCutFactorMax;
126 
127  if (pCluster->GetNCaloHits() < m_minClusterCaloHits * selectionCutFactor)
128  continue;
129 
130  if (LArClusterHelper::GetLengthSquared(pCluster) < m_minClusterLengthSquared * selectionCutFactor * selectionCutFactor)
131  continue;
132 
133  nClustersPassingMaxCuts++;
134  }
135  }
136 
137  for (const Cluster *const pCluster : sortedClusters)
138  {
139  float selectionCutFactor(1.f);
140 
141  if (pCluster->GetParticleId() == E_MINUS && m_reducedCandidates)
142  {
143  selectionCutFactor = (m_selectionCutFactorMax + 1.f) * 0.5f +
144  (m_selectionCutFactorMax - 1.f) * 0.5f *
145  std::tanh(static_cast<float>(nClustersPassingMaxCuts) - m_nClustersPassingMaxCutsPar);
146  }
147 
148  if (pCluster->GetNCaloHits() < m_minClusterCaloHits * selectionCutFactor)
149  continue;
150 
151  if (LArClusterHelper::GetLengthSquared(pCluster) < m_minClusterLengthSquared * selectionCutFactor * selectionCutFactor)
152  continue;
153 
154  try
155  {
156  this->AddToSlidingFitCache(pCluster);
157  selectedClusterVector.push_back(pCluster);
158  }
159  catch (StatusCodeException &statusCodeException)
160  {
161  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
162  throw statusCodeException;
163  }
164  }
165  }
166 }
167 
168 //------------------------------------------------------------------------------------------------------------------------------------------
169 
170 void CandidateVertexCreationAlgorithm::CreateEndpointCandidates(const ClusterVector &clusterVector1, const ClusterVector &clusterVector2) const
171 {
172  for (const Cluster *const pCluster1 : clusterVector1)
173  {
174  const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
175 
176  const TwoDSlidingFitResult &fitResult1(this->GetCachedSlidingFitResult(pCluster1));
177  const CartesianVector minLayerPosition1(fitResult1.GetGlobalMinLayerPosition());
178  const CartesianVector maxLayerPosition1(fitResult1.GetGlobalMaxLayerPosition());
179 
180  for (const Cluster *const pCluster2 : clusterVector2)
181  {
182  const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
183 
184  const TwoDSlidingFitResult &fitResult2(this->GetCachedSlidingFitResult(pCluster2));
185  const CartesianVector minLayerPosition2(fitResult2.GetGlobalMinLayerPosition());
186  const CartesianVector maxLayerPosition2(fitResult2.GetGlobalMaxLayerPosition());
187 
188  this->CreateEndpointVertex(maxLayerPosition1, hitType1, fitResult2);
189  this->CreateEndpointVertex(minLayerPosition1, hitType1, fitResult2);
190  this->CreateEndpointVertex(maxLayerPosition2, hitType2, fitResult1);
191  this->CreateEndpointVertex(minLayerPosition2, hitType2, fitResult1);
192  }
193  }
194 }
195 
196 //------------------------------------------------------------------------------------------------------------------------------------------
197 
199  const CartesianVector &position1, const HitType hitType1, const TwoDSlidingFitResult &fitResult2) const
200 {
201  const CartesianVector minLayerPosition2(fitResult2.GetGlobalMinLayerPosition());
202  const CartesianVector maxLayerPosition2(fitResult2.GetGlobalMaxLayerPosition());
203 
204  if ((((position1.GetX() < minLayerPosition2.GetX()) && (position1.GetX() < maxLayerPosition2.GetX())) ||
205  ((position1.GetX() > minLayerPosition2.GetX()) && (position1.GetX() > maxLayerPosition2.GetX()))) &&
206  (std::fabs(position1.GetX() - minLayerPosition2.GetX()) > m_maxEndpointXDiscrepancy) &&
207  (std::fabs(position1.GetX() - maxLayerPosition2.GetX()) > m_maxEndpointXDiscrepancy))
208  {
209  return;
210  }
211 
212  CartesianVector position2(0.f, 0.f, 0.f);
213  if (STATUS_CODE_SUCCESS != fitResult2.GetExtrapolatedPositionAtX(position1.GetX(), position2))
214  return;
215 
216  const HitType hitType2(LArClusterHelper::GetClusterHitType(fitResult2.GetCluster()));
217 
218  float chiSquared(0.f);
219  CartesianVector position3D(0.f, 0.f, 0.f);
220  LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), hitType1, hitType2, position1, position2, position3D, chiSquared);
221 
222  if (chiSquared > m_chiSquaredCut)
223  return;
224 
225  PandoraContentApi::Vertex::Parameters parameters;
226  parameters.m_position = position3D;
227  parameters.m_vertexLabel = VERTEX_INTERACTION;
228  parameters.m_vertexType = VERTEX_3D;
229 
230  const Vertex *pVertex(NULL);
231  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
232 }
233 
234 //------------------------------------------------------------------------------------------------------------------------------------------
235 
237  const ClusterVector &clusterVectorU, const ClusterVector &clusterVectorV, const ClusterVector &clusterVectorW) const
238 {
239  CartesianPointVector crossingsU, crossingsV, crossingsW;
240  this->FindCrossingPoints(clusterVectorU, crossingsU);
241  this->FindCrossingPoints(clusterVectorV, crossingsV);
242  this->FindCrossingPoints(clusterVectorW, crossingsW);
243 
244  unsigned int nCrossingCandidates(0);
245  this->CreateCrossingVertices(crossingsU, crossingsV, TPC_VIEW_U, TPC_VIEW_V, nCrossingCandidates);
246  this->CreateCrossingVertices(crossingsU, crossingsW, TPC_VIEW_U, TPC_VIEW_W, nCrossingCandidates);
247  this->CreateCrossingVertices(crossingsV, crossingsW, TPC_VIEW_V, TPC_VIEW_W, nCrossingCandidates);
248 }
249 
250 //------------------------------------------------------------------------------------------------------------------------------------------
251 
252 void CandidateVertexCreationAlgorithm::FindCrossingPoints(const ClusterVector &clusterVector, CartesianPointVector &crossingPoints) const
253 {
254  ClusterToSpacepointsMap clusterToSpacepointsMap;
255 
256  for (const Cluster *const pCluster : clusterVector)
257  {
258  ClusterToSpacepointsMap::iterator mapIter(clusterToSpacepointsMap.emplace(pCluster, CartesianPointVector()).first);
259  this->GetSpacepoints(pCluster, mapIter->second);
260  }
261 
262  for (const Cluster *const pCluster1 : clusterVector)
263  {
264  for (const Cluster *const pCluster2 : clusterVector)
265  {
266  if (pCluster1 == pCluster2)
267  continue;
268 
269  this->FindCrossingPoints(clusterToSpacepointsMap.at(pCluster1), clusterToSpacepointsMap.at(pCluster2), crossingPoints);
270  }
271  }
272 }
273 
274 //------------------------------------------------------------------------------------------------------------------------------------------
275 
276 void CandidateVertexCreationAlgorithm::GetSpacepoints(const Cluster *const pCluster, CartesianPointVector &spacepoints) const
277 {
278  LArClusterHelper::GetCoordinateVector(pCluster, spacepoints);
279 
280  const TwoDSlidingFitResult &fitResult(this->GetCachedSlidingFitResult(pCluster));
281  const float minLayerRL(fitResult.GetL(fitResult.GetMinLayer()));
282  const float maxLayerRL(fitResult.GetL(fitResult.GetMaxLayer()));
283 
284  for (unsigned int iStep = 0; iStep < m_extrapolationNSteps; ++iStep)
285  {
286  const float deltaRL(static_cast<float>(iStep) * m_extrapolationStepSize);
287 
288  CartesianVector positionPositive(0.f, 0.f, 0.f), positionNegative(0.f, 0.f, 0.f);
289  fitResult.GetExtrapolatedPosition(maxLayerRL + deltaRL, positionPositive);
290  fitResult.GetExtrapolatedPosition(minLayerRL - deltaRL, positionNegative);
291 
292  spacepoints.push_back(positionPositive);
293  spacepoints.push_back(positionNegative);
294  }
295 
296  std::sort(spacepoints.begin(), spacepoints.end(), LArClusterHelper::SortCoordinatesByPosition);
297 }
298 
299 //------------------------------------------------------------------------------------------------------------------------------------------
300 
302  const CartesianPointVector &spacepoints1, const CartesianPointVector &spacepoints2, CartesianPointVector &crossingPoints) const
303 {
304  bool bestCrossingFound(false);
305  float bestSeparationSquared(m_maxCrossingSeparationSquared);
306  CartesianVector bestPosition1(0.f, 0.f, 0.f), bestPosition2(0.f, 0.f, 0.f);
307 
308  for (const CartesianVector &position1 : spacepoints1)
309  {
310  for (const CartesianVector &position2 : spacepoints2)
311  {
312  const float separationSquared((position1 - position2).GetMagnitudeSquared());
313 
314  if (separationSquared < bestSeparationSquared)
315  {
316  bestCrossingFound = true;
317  bestSeparationSquared = separationSquared;
318  bestPosition1 = position1;
319  bestPosition2 = position2;
320  }
321  }
322  }
323 
324  if (bestCrossingFound)
325  {
326  bool alreadyPopulated(false);
327 
328  for (const CartesianVector &existingPosition : crossingPoints)
329  {
330  if (((existingPosition - bestPosition1).GetMagnitudeSquared() < m_minNearbyCrossingDistanceSquared) ||
331  ((existingPosition - bestPosition2).GetMagnitudeSquared() < m_minNearbyCrossingDistanceSquared))
332  {
333  alreadyPopulated = true;
334  break;
335  }
336  }
337 
338  if (!alreadyPopulated)
339  {
340  crossingPoints.push_back(bestPosition1);
341  crossingPoints.push_back(bestPosition2);
342  }
343  }
344 }
345 
346 //------------------------------------------------------------------------------------------------------------------------------------------
347 
348 void CandidateVertexCreationAlgorithm::CreateCrossingVertices(const CartesianPointVector &crossingPoints1,
349  const CartesianPointVector &crossingPoints2, const HitType hitType1, const HitType hitType2, unsigned int &nCrossingCandidates) const
350 {
351 
352  for (const CartesianVector &position1 : crossingPoints1)
353  {
354  for (const CartesianVector &position2 : crossingPoints2)
355  {
356  if (nCrossingCandidates > m_nMaxCrossingCandidates)
357  return;
358 
359  if (std::fabs(position1.GetX() - position2.GetX()) > m_maxCrossingXDiscrepancy)
360  continue;
361 
362  float chiSquared(0.f);
363  CartesianVector position3D(0.f, 0.f, 0.f);
364  LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), hitType1, hitType2, position1, position2, position3D, chiSquared);
365 
366  if (chiSquared > m_chiSquaredCut)
367  continue;
368 
369  PandoraContentApi::Vertex::Parameters parameters;
370  parameters.m_position = position3D;
371  parameters.m_vertexLabel = VERTEX_INTERACTION;
372  parameters.m_vertexType = VERTEX_3D;
373 
374  const Vertex *pVertex(NULL);
375  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
376  ++nCrossingCandidates;
377  }
378  }
379 }
380 
381 //------------------------------------------------------------------------------------------------------------------------------------------
382 
384 {
385  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
386  const TwoDSlidingFitResult slidingFitResult(pCluster, m_slidingFitWindow, slidingFitPitch);
387 
388  if (!m_slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult)).second)
389  throw StatusCodeException(STATUS_CODE_FAILURE);
390 }
391 
392 //------------------------------------------------------------------------------------------------------------------------------------------
393 
395 {
397 
398  if (m_slidingFitResultMap.end() == iter)
399  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
400 
401  return iter->second;
402 }
403 
404 //------------------------------------------------------------------------------------------------------------------------------------------
405 
407 {
408  m_slidingFitResultMap.clear();
409 }
410 
411 //------------------------------------------------------------------------------------------------------------------------------------------
412 
413 StatusCode CandidateVertexCreationAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
414 {
415  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputClusterListNames", m_inputClusterListNames));
416 
417  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputVertexListName", m_outputVertexListName));
418 
419  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
420  XmlHelper::ReadValue(xmlHandle, "ReplaceCurrentVertexList", m_replaceCurrentVertexList));
421 
422  PANDORA_RETURN_RESULT_IF_AND_IF(
423  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
424 
425  PANDORA_RETURN_RESULT_IF_AND_IF(
426  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterCaloHits", m_minClusterCaloHits));
427 
428  float minClusterLength = std::sqrt(m_minClusterLengthSquared);
429  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterLength", minClusterLength));
430  m_minClusterLengthSquared = minClusterLength * minClusterLength;
431 
432  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ChiSquaredCut", m_chiSquaredCut));
433 
434  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
435  XmlHelper::ReadValue(xmlHandle, "EnableEndpointCandidates", m_enableEndpointCandidates));
436 
437  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
438  XmlHelper::ReadValue(xmlHandle, "MaxEndpointXDiscrepancy", m_maxEndpointXDiscrepancy));
439 
440  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
441  XmlHelper::ReadValue(xmlHandle, "EnableCrossingCandidates", m_enableCrossingCandidates));
442 
443  PANDORA_RETURN_RESULT_IF_AND_IF(
444  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NMaxCrossingCandidates", m_nMaxCrossingCandidates));
445 
446  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
447  XmlHelper::ReadValue(xmlHandle, "MaxCrossingXDiscrepancy", m_maxCrossingXDiscrepancy));
448 
449  PANDORA_RETURN_RESULT_IF_AND_IF(
450  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ExtrapolationNSteps", m_extrapolationNSteps));
451 
452  PANDORA_RETURN_RESULT_IF_AND_IF(
453  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ExtrapolationStepSize", m_extrapolationStepSize));
454 
455  PANDORA_RETURN_RESULT_IF_AND_IF(
456  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ReducedCandidates", m_reducedCandidates));
457 
458  PANDORA_RETURN_RESULT_IF_AND_IF(
459  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SelectionCutFactorMax", m_selectionCutFactorMax));
460 
461  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
462  XmlHelper::ReadValue(xmlHandle, "NClustersPassingMaxCutsPar", m_nClustersPassingMaxCutsPar));
463 
464  float maxCrossingSeparation = std::sqrt(m_maxCrossingSeparationSquared);
465  PANDORA_RETURN_RESULT_IF_AND_IF(
466  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxCrossingSeparation", maxCrossingSeparation));
467  m_maxCrossingSeparationSquared = maxCrossingSeparation * maxCrossingSeparation;
468 
469  float minNearbyCrossingDistance = std::sqrt(m_minNearbyCrossingDistanceSquared);
470  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
471  XmlHelper::ReadValue(xmlHandle, "MinNearbyCrossingDistance", minNearbyCrossingDistance));
472  m_minNearbyCrossingDistanceSquared = minNearbyCrossingDistance * minNearbyCrossingDistance;
473 
474  return STATUS_CODE_SUCCESS;
475 }
476 
477 } // namespace lar_content
bool m_reducedCandidates
Whether to reduce the number of candidates.
intermediate_table::iterator iterator
static bool SortByNHits(const pandora::Cluster *const pLhs, const pandora::Cluster *const pRhs)
Sort clusters by number of hits, then layer span, then inner layer, then position, then pulse-height.
float m_minClusterLengthSquared
The min length (squared) in base cluster selection method.
void CreateEndpointVertex(const pandora::CartesianVector &position1, const pandora::HitType hitType1, const TwoDSlidingFitResult &fitResult2) const
Create a candidate vertex position, using an end-point position from one cluster and sliding fit to a...
void CreateCrossingCandidates(const pandora::ClusterVector &clusterVectorU, const pandora::ClusterVector &clusterVectorV, const pandora::ClusterVector &clusterVectorW) const
Extrapolate 2D clusters, find where they cross, and match crossing points between views to create ver...
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.
void GetSpacepoints(const pandora::Cluster *const pCluster, pandora::CartesianPointVector &spacePoints) const
Get a list of spacepoints representing cluster 2D hit positions and extrapolated positions.
float m_extrapolationStepSize
The extrapolation step size in cm.
float m_maxCrossingSeparationSquared
The separation (squared) between spacepoints below which a crossing can be identified.
enum cvn::HType HitType
pandora::StatusCode GetExtrapolatedPositionAtX(const float x, pandora::CartesianVector &position) const
Get extrapolated position (beyond span) for a given input x coordinate.
std::string string
Definition: nybbler.cc:12
bool m_enableEndpointCandidates
Whether to create endpoint-based candidates.
void AddToSlidingFitCache(const pandora::Cluster *const pCluster)
Creates a 2D sliding fit of a cluster and stores it for later use.
intermediate_table::const_iterator const_iterator
bool m_replaceCurrentVertexList
Whether to replace the current vertex list with the output list.
float m_maxEndpointXDiscrepancy
The max cluster endpoint discrepancy.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
void FindCrossingPoints(const pandora::ClusterVector &clusterVector, pandora::CartesianPointVector &crossingPoints) const
Identify where (extrapolated) clusters plausibly cross in 2D.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
static bool SortCoordinatesByPosition(const pandora::CartesianVector &lhs, const pandora::CartesianVector &rhs)
Sort cartesian vectors by their position (use Z, followed by X, followed by Y)
Header file for the geometry helper class.
Header file for the candidate vertex creation algorithm class.
int GetMaxLayer() const
Get the maximum occupied layer in the sliding fit.
int GetMinLayer() const
Get the minimum occupied layer in the sliding fit.
Header file for the cluster helper class.
bool m_enableCrossingCandidates
Whether to create crossing vertex candidates.
float m_maxCrossingXDiscrepancy
The max cluster endpoint discrepancy.
TwoDSlidingFitResultMap m_slidingFitResultMap
The sliding fit result map.
void CreateEndpointCandidates(const pandora::ClusterVector &clusterVector1, const pandora::ClusterVector &clusterVector2) const
Create candidate vertex positions by comparing pairs of cluster end positions.
float m_nClustersPassingMaxCutsPar
Parameter for number of clusters passing the max base cluster selection cuts.
pandora::StatusCode GetExtrapolatedPosition(const float rL, pandora::CartesianVector &position) const
Get extrapolated position (beyond span) for a given input coordinate.
float m_minNearbyCrossingDistanceSquared
The minimum allowed distance between identified crossing positions.
unsigned int m_minClusterCaloHits
The min number of hits in base cluster selection method.
void TidyUp()
Clear relevant algorithm member variables between events.
pandora::CartesianVector GetGlobalMinLayerPosition() const
Get global position corresponding to the fit result in minimum fit layer.
unsigned int m_extrapolationNSteps
Number of extrapolation steps, at each end of cluster, of specified size.
std::string m_outputVertexListName
The name under which to save the output vertex list.
const TwoDSlidingFitResult & GetCachedSlidingFitResult(const pandora::Cluster *const pCluster) const
Get a sliding fit result from the algorithm cache.
pandora::StringVector m_inputClusterListNames
The list of cluster list names.
unsigned int m_nMaxCrossingCandidates
The max number of crossing candidates to create.
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > ClusterToSpacepointsMap
float m_selectionCutFactorMax
Maximum factor to multiply the base cluster selection cuts.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
void SelectClusters(pandora::ClusterVector &clusterVectorU, pandora::ClusterVector &clusterVectorV, pandora::ClusterVector &clusterVectorW)
Select a subset of input clusters (contained in the input list names) for processing in this algorith...
float m_chiSquaredCut
The chi squared cut (accept only 3D vertex positions with values below cut)
float GetL(const int layer) const
Get longitudinal coordinate for a given sliding linear fit layer number.
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
static void GetCoordinateVector(const pandora::Cluster *const pCluster, pandora::CartesianPointVector &coordinateVector)
Get vector of hit coordinates from an input cluster.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void CreateCrossingVertices(const pandora::CartesianPointVector &crossingPoints1, const pandora::CartesianPointVector &crossingPoints2, const pandora::HitType hitType1, const pandora::HitType hitType2, unsigned int &nCrossingCandidates) const
Attempt to create candidate vertex positions, using 2D crossing points in 2 views.
std::list< Vertex > VertexList
Definition: DCEL.h:182
pandora::CartesianVector GetGlobalMaxLayerPosition() const
Get global position corresponding to the fit result in maximum fit layer.
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
QTextStream & endl(QTextStream &s)