All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 (!m_inputVertexListName.empty())
68  this->AddInputVertices();
69 
70  if (!pVertexList->empty())
71  {
72  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_outputVertexListName));
73 
75  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Vertex>(*this, m_outputVertexListName));
76  }
77  }
78  catch (StatusCodeException &statusCodeException)
79  {
80  this->TidyUp();
81  throw statusCodeException;
82  }
83 
84  this->TidyUp();
85 
86  return STATUS_CODE_SUCCESS;
87 }
88 
89 //------------------------------------------------------------------------------------------------------------------------------------------
90 
91 void CandidateVertexCreationAlgorithm::SelectClusters(ClusterVector &clusterVectorU, ClusterVector &clusterVectorV, ClusterVector &clusterVectorW)
92 {
93  for (const std::string &clusterListName : m_inputClusterListNames)
94  {
95  const ClusterList *pClusterList(NULL);
96  PANDORA_THROW_RESULT_IF_AND_IF(
97  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, clusterListName, pClusterList));
98 
99  if (!pClusterList || pClusterList->empty())
100  {
101  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
102  std::cout << "CandidateVertexCreationAlgorithm: unable to find cluster list " << clusterListName << std::endl;
103 
104  continue;
105  }
106 
107  const HitType hitType(LArClusterHelper::GetClusterHitType(*(pClusterList->begin())));
108 
109  if ((TPC_VIEW_U != hitType) && (TPC_VIEW_V != hitType) && (TPC_VIEW_W != hitType))
110  throw StatusCodeException(STATUS_CODE_INVALID_PARAMETER);
111 
112  ClusterVector &selectedClusterVector((TPC_VIEW_U == hitType) ? clusterVectorU : (TPC_VIEW_V == hitType) ? clusterVectorV : clusterVectorW);
113 
114  if (!selectedClusterVector.empty())
115  throw StatusCodeException(STATUS_CODE_FAILURE);
116 
117  ClusterVector sortedClusters(pClusterList->begin(), pClusterList->end());
118  std::sort(sortedClusters.begin(), sortedClusters.end(), LArClusterHelper::SortByNHits);
119 
120  unsigned int nClustersPassingMaxCuts(0);
122  {
123  for (const Cluster *const pCluster : sortedClusters)
124  {
125  float selectionCutFactor(1.f);
126 
127  if (pCluster->GetParticleId() == E_MINUS)
128  selectionCutFactor = m_selectionCutFactorMax;
129 
130  if (pCluster->GetNCaloHits() < m_minClusterCaloHits * selectionCutFactor)
131  continue;
132 
133  if (LArClusterHelper::GetLengthSquared(pCluster) < m_minClusterLengthSquared * selectionCutFactor * selectionCutFactor)
134  continue;
135 
136  nClustersPassingMaxCuts++;
137  }
138  }
139 
140  for (const Cluster *const pCluster : sortedClusters)
141  {
142  float selectionCutFactor(1.f);
143 
144  if (pCluster->GetParticleId() == E_MINUS && m_reducedCandidates)
145  {
146  selectionCutFactor = (m_selectionCutFactorMax + 1.f) * 0.5f +
147  (m_selectionCutFactorMax - 1.f) * 0.5f *
148  std::tanh(static_cast<float>(nClustersPassingMaxCuts) - m_nClustersPassingMaxCutsPar);
149  }
150 
151  if (pCluster->GetNCaloHits() < m_minClusterCaloHits * selectionCutFactor)
152  continue;
153 
154  if (LArClusterHelper::GetLengthSquared(pCluster) < m_minClusterLengthSquared * selectionCutFactor * selectionCutFactor)
155  continue;
156 
157  try
158  {
159  this->AddToSlidingFitCache(pCluster);
160  selectedClusterVector.push_back(pCluster);
161  }
162  catch (StatusCodeException &statusCodeException)
163  {
164  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
165  throw statusCodeException;
166  }
167  }
168  }
169 }
170 
171 //------------------------------------------------------------------------------------------------------------------------------------------
172 
173 void CandidateVertexCreationAlgorithm::CreateEndpointCandidates(const ClusterVector &clusterVector1, const ClusterVector &clusterVector2) const
174 {
175  for (const Cluster *const pCluster1 : clusterVector1)
176  {
177  const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
178 
179  const TwoDSlidingFitResult &fitResult1(this->GetCachedSlidingFitResult(pCluster1));
180  const CartesianVector minLayerPosition1(fitResult1.GetGlobalMinLayerPosition());
181  const CartesianVector maxLayerPosition1(fitResult1.GetGlobalMaxLayerPosition());
182 
183  for (const Cluster *const pCluster2 : clusterVector2)
184  {
185  const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
186 
187  const TwoDSlidingFitResult &fitResult2(this->GetCachedSlidingFitResult(pCluster2));
188  const CartesianVector minLayerPosition2(fitResult2.GetGlobalMinLayerPosition());
189  const CartesianVector maxLayerPosition2(fitResult2.GetGlobalMaxLayerPosition());
190 
191  this->CreateEndpointVertex(maxLayerPosition1, hitType1, fitResult2);
192  this->CreateEndpointVertex(minLayerPosition1, hitType1, fitResult2);
193  this->CreateEndpointVertex(maxLayerPosition2, hitType2, fitResult1);
194  this->CreateEndpointVertex(minLayerPosition2, hitType2, fitResult1);
195  }
196  }
197 }
198 
199 //------------------------------------------------------------------------------------------------------------------------------------------
200 
202  const CartesianVector &position1, const HitType hitType1, const TwoDSlidingFitResult &fitResult2) const
203 {
204  const CartesianVector minLayerPosition2(fitResult2.GetGlobalMinLayerPosition());
205  const CartesianVector maxLayerPosition2(fitResult2.GetGlobalMaxLayerPosition());
206 
207  if ((((position1.GetX() < minLayerPosition2.GetX()) && (position1.GetX() < maxLayerPosition2.GetX())) ||
208  ((position1.GetX() > minLayerPosition2.GetX()) && (position1.GetX() > maxLayerPosition2.GetX()))) &&
209  (std::fabs(position1.GetX() - minLayerPosition2.GetX()) > m_maxEndpointXDiscrepancy) &&
210  (std::fabs(position1.GetX() - maxLayerPosition2.GetX()) > m_maxEndpointXDiscrepancy))
211  {
212  return;
213  }
214 
215  CartesianVector position2(0.f, 0.f, 0.f);
216  if (STATUS_CODE_SUCCESS != fitResult2.GetExtrapolatedPositionAtX(position1.GetX(), position2))
217  return;
218 
219  const HitType hitType2(LArClusterHelper::GetClusterHitType(fitResult2.GetCluster()));
220 
221  float chiSquared(0.f);
222  CartesianVector position3D(0.f, 0.f, 0.f);
223  LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), hitType1, hitType2, position1, position2, position3D, chiSquared);
224 
225  if (chiSquared > m_chiSquaredCut)
226  return;
227 
229  parameters.m_position = position3D;
230  parameters.m_vertexLabel = VERTEX_INTERACTION;
231  parameters.m_vertexType = VERTEX_3D;
232 
233  const Vertex *pVertex(NULL);
234  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
235 }
236 
237 //------------------------------------------------------------------------------------------------------------------------------------------
238 
240  const ClusterVector &clusterVectorU, const ClusterVector &clusterVectorV, const ClusterVector &clusterVectorW) const
241 {
242  CartesianPointVector crossingsU, crossingsV, crossingsW;
243  this->FindCrossingPoints(clusterVectorU, crossingsU);
244  this->FindCrossingPoints(clusterVectorV, crossingsV);
245  this->FindCrossingPoints(clusterVectorW, crossingsW);
246 
247  unsigned int nCrossingCandidates(0);
248  this->CreateCrossingVertices(crossingsU, crossingsV, TPC_VIEW_U, TPC_VIEW_V, nCrossingCandidates);
249  this->CreateCrossingVertices(crossingsU, crossingsW, TPC_VIEW_U, TPC_VIEW_W, nCrossingCandidates);
250  this->CreateCrossingVertices(crossingsV, crossingsW, TPC_VIEW_V, TPC_VIEW_W, nCrossingCandidates);
251 }
252 
253 //------------------------------------------------------------------------------------------------------------------------------------------
254 
255 void CandidateVertexCreationAlgorithm::FindCrossingPoints(const ClusterVector &clusterVector, CartesianPointVector &crossingPoints) const
256 {
257  ClusterToSpacepointsMap clusterToSpacepointsMap;
258 
259  for (const Cluster *const pCluster : clusterVector)
260  {
261  ClusterToSpacepointsMap::iterator mapIter(clusterToSpacepointsMap.emplace(pCluster, CartesianPointVector()).first);
262  this->GetSpacepoints(pCluster, mapIter->second);
263  }
264 
265  for (const Cluster *const pCluster1 : clusterVector)
266  {
267  for (const Cluster *const pCluster2 : clusterVector)
268  {
269  if (pCluster1 == pCluster2)
270  continue;
271 
272  this->FindCrossingPoints(clusterToSpacepointsMap.at(pCluster1), clusterToSpacepointsMap.at(pCluster2), crossingPoints);
273  }
274  }
275 }
276 
277 //------------------------------------------------------------------------------------------------------------------------------------------
278 
279 void CandidateVertexCreationAlgorithm::GetSpacepoints(const Cluster *const pCluster, CartesianPointVector &spacepoints) const
280 {
281  LArClusterHelper::GetCoordinateVector(pCluster, spacepoints);
282 
283  const TwoDSlidingFitResult &fitResult(this->GetCachedSlidingFitResult(pCluster));
284  const float minLayerRL(fitResult.GetL(fitResult.GetMinLayer()));
285  const float maxLayerRL(fitResult.GetL(fitResult.GetMaxLayer()));
286 
287  for (unsigned int iStep = 0; iStep < m_extrapolationNSteps; ++iStep)
288  {
289  const float deltaRL(static_cast<float>(iStep) * m_extrapolationStepSize);
290 
291  CartesianVector positionPositive(0.f, 0.f, 0.f), positionNegative(0.f, 0.f, 0.f);
292  fitResult.GetExtrapolatedPosition(maxLayerRL + deltaRL, positionPositive);
293  fitResult.GetExtrapolatedPosition(minLayerRL - deltaRL, positionNegative);
294 
295  spacepoints.push_back(positionPositive);
296  spacepoints.push_back(positionNegative);
297  }
298 
299  std::sort(spacepoints.begin(), spacepoints.end(), LArClusterHelper::SortCoordinatesByPosition);
300 }
301 
302 //------------------------------------------------------------------------------------------------------------------------------------------
303 
305  const CartesianPointVector &spacepoints1, const CartesianPointVector &spacepoints2, CartesianPointVector &crossingPoints) const
306 {
307  bool bestCrossingFound(false);
308  float bestSeparationSquared(m_maxCrossingSeparationSquared);
309  CartesianVector bestPosition1(0.f, 0.f, 0.f), bestPosition2(0.f, 0.f, 0.f);
310 
311  for (const CartesianVector &position1 : spacepoints1)
312  {
313  for (const CartesianVector &position2 : spacepoints2)
314  {
315  const float separationSquared((position1 - position2).GetMagnitudeSquared());
316 
317  if (separationSquared < bestSeparationSquared)
318  {
319  bestCrossingFound = true;
320  bestSeparationSquared = separationSquared;
321  bestPosition1 = position1;
322  bestPosition2 = position2;
323  }
324  }
325  }
326 
327  if (bestCrossingFound)
328  {
329  bool alreadyPopulated(false);
330 
331  for (const CartesianVector &existingPosition : crossingPoints)
332  {
333  if (((existingPosition - bestPosition1).GetMagnitudeSquared() < m_minNearbyCrossingDistanceSquared) ||
334  ((existingPosition - bestPosition2).GetMagnitudeSquared() < m_minNearbyCrossingDistanceSquared))
335  {
336  alreadyPopulated = true;
337  break;
338  }
339  }
340 
341  if (!alreadyPopulated)
342  {
343  crossingPoints.push_back(bestPosition1);
344  crossingPoints.push_back(bestPosition2);
345  }
346  }
347 }
348 
349 //------------------------------------------------------------------------------------------------------------------------------------------
350 
351 void CandidateVertexCreationAlgorithm::CreateCrossingVertices(const CartesianPointVector &crossingPoints1,
352  const CartesianPointVector &crossingPoints2, const HitType hitType1, const HitType hitType2, unsigned int &nCrossingCandidates) const
353 {
354 
355  for (const CartesianVector &position1 : crossingPoints1)
356  {
357  for (const CartesianVector &position2 : crossingPoints2)
358  {
359  if (nCrossingCandidates > m_nMaxCrossingCandidates)
360  return;
361 
362  if (std::fabs(position1.GetX() - position2.GetX()) > m_maxCrossingXDiscrepancy)
363  continue;
364 
365  float chiSquared(0.f);
366  CartesianVector position3D(0.f, 0.f, 0.f);
367  LArGeometryHelper::MergeTwoPositions3D(this->GetPandora(), hitType1, hitType2, position1, position2, position3D, chiSquared);
368 
369  if (chiSquared > m_chiSquaredCut)
370  continue;
371 
373  parameters.m_position = position3D;
374  parameters.m_vertexLabel = VERTEX_INTERACTION;
375  parameters.m_vertexType = VERTEX_3D;
376 
377  const Vertex *pVertex(NULL);
378  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
379  ++nCrossingCandidates;
380  }
381  }
382 }
383 
384 //------------------------------------------------------------------------------------------------------------------------------------------
385 
387 {
388  const VertexList *pInputVertexList{nullptr};
389  try
390  { // ATTN - No guarantee the list has been initialised, but silent failure here is ok
391  PandoraContentApi::GetList(*this, m_inputVertexListName, pInputVertexList);
392  if (!pInputVertexList)
393  return;
394 
395  for (const Vertex *pInputVertex : *pInputVertexList)
396  {
398  parameters.m_position = pInputVertex->GetPosition();
399  parameters.m_vertexLabel = VERTEX_INTERACTION;
400  parameters.m_vertexType = VERTEX_3D;
401 
402  const Vertex *pVertex(nullptr);
403  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
404  }
405  }
406  catch (const StatusCodeException &)
407  {
408  return;
409  }
410 }
411 
412 //------------------------------------------------------------------------------------------------------------------------------------------
413 
415 {
416  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
417  const TwoDSlidingFitResult slidingFitResult(pCluster, m_slidingFitWindow, slidingFitPitch);
418 
419  if (!m_slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(pCluster, slidingFitResult)).second)
420  throw StatusCodeException(STATUS_CODE_FAILURE);
421 }
422 
423 //------------------------------------------------------------------------------------------------------------------------------------------
424 
426 {
427  TwoDSlidingFitResultMap::const_iterator iter = m_slidingFitResultMap.find(pCluster);
428 
429  if (m_slidingFitResultMap.end() == iter)
430  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
431 
432  return iter->second;
433 }
434 
435 //------------------------------------------------------------------------------------------------------------------------------------------
436 
438 {
439  m_slidingFitResultMap.clear();
440 }
441 
442 //------------------------------------------------------------------------------------------------------------------------------------------
443 
444 StatusCode CandidateVertexCreationAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
445 {
446  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "InputClusterListNames", m_inputClusterListNames));
447 
448  PANDORA_RETURN_RESULT_IF_AND_IF(
449  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "InputVertexListName", m_inputVertexListName));
450 
451  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputVertexListName", m_outputVertexListName));
452 
453  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
454  XmlHelper::ReadValue(xmlHandle, "ReplaceCurrentVertexList", m_replaceCurrentVertexList));
455 
456  PANDORA_RETURN_RESULT_IF_AND_IF(
457  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitWindow", m_slidingFitWindow));
458 
459  PANDORA_RETURN_RESULT_IF_AND_IF(
460  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterCaloHits", m_minClusterCaloHits));
461 
462  float minClusterLength = std::sqrt(m_minClusterLengthSquared);
463  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinClusterLength", minClusterLength));
464  m_minClusterLengthSquared = minClusterLength * minClusterLength;
465 
466  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ChiSquaredCut", m_chiSquaredCut));
467 
468  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
469  XmlHelper::ReadValue(xmlHandle, "EnableEndpointCandidates", m_enableEndpointCandidates));
470 
471  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
472  XmlHelper::ReadValue(xmlHandle, "MaxEndpointXDiscrepancy", m_maxEndpointXDiscrepancy));
473 
474  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
475  XmlHelper::ReadValue(xmlHandle, "EnableCrossingCandidates", m_enableCrossingCandidates));
476 
477  PANDORA_RETURN_RESULT_IF_AND_IF(
478  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "NMaxCrossingCandidates", m_nMaxCrossingCandidates));
479 
480  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
481  XmlHelper::ReadValue(xmlHandle, "MaxCrossingXDiscrepancy", m_maxCrossingXDiscrepancy));
482 
483  PANDORA_RETURN_RESULT_IF_AND_IF(
484  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ExtrapolationNSteps", m_extrapolationNSteps));
485 
486  PANDORA_RETURN_RESULT_IF_AND_IF(
487  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ExtrapolationStepSize", m_extrapolationStepSize));
488 
489  PANDORA_RETURN_RESULT_IF_AND_IF(
490  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ReducedCandidates", m_reducedCandidates));
491 
492  PANDORA_RETURN_RESULT_IF_AND_IF(
493  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SelectionCutFactorMax", m_selectionCutFactorMax));
494 
495  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
496  XmlHelper::ReadValue(xmlHandle, "NClustersPassingMaxCutsPar", m_nClustersPassingMaxCutsPar));
497 
498  float maxCrossingSeparation = std::sqrt(m_maxCrossingSeparationSquared);
499  PANDORA_RETURN_RESULT_IF_AND_IF(
500  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxCrossingSeparation", maxCrossingSeparation));
501  m_maxCrossingSeparationSquared = maxCrossingSeparation * maxCrossingSeparation;
502 
503  float minNearbyCrossingDistance = std::sqrt(m_minNearbyCrossingDistanceSquared);
504  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
505  XmlHelper::ReadValue(xmlHandle, "MinNearbyCrossingDistance", minNearbyCrossingDistance));
506  m_minNearbyCrossingDistanceSquared = minNearbyCrossingDistance * minNearbyCrossingDistance;
507 
508  return STATUS_CODE_SUCCESS;
509 }
510 
511 } // namespace lar_content
bool m_reducedCandidates
Whether to reduce the number of candidates.
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.
pandora::StatusCode GetExtrapolatedPositionAtX(const float x, pandora::CartesianVector &position) const
Get extrapolated position (beyond span) for a given input x coordinate.
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.
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.
std::string m_inputVertexListName
The list name for existing candidate vertices.
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.
fhicl::Table< sbnd::crt::CRTDetSimParams > Parameters
const pandora::Cluster * GetCluster() const
Get the address of the cluster, if originally provided.
std::unordered_map< const pandora::Cluster *, pandora::CartesianPointVector > ClusterToSpacepointsMap
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
Definition: reco_sbnd.fcl:182
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.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
void AddInputVertices() const
Add candidate vertices from any input vertices.
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.
BEGIN_PROLOG don t mess with this pandoraTrackGausCryoW true
BEGIN_PROLOG could also be cout
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.