Public Member Functions | Private Member Functions | Private Attributes | List of all members
lar_content::CosmicRaySplittingAlgorithm Class Reference

CosmicRaySplittingAlgorithm class. More...

#include <CosmicRaySplittingAlgorithm.h>

Inheritance diagram for lar_content::CosmicRaySplittingAlgorithm:

Public Member Functions

 CosmicRaySplittingAlgorithm ()
 Default constructor. More...
 

Private Member Functions

pandora::StatusCode Run ()
 
pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 
void GetListOfCleanClusters (const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
 Populate cluster vector with subset of cluster list, containing clusters judged to be clean. More...
 
void BuildSlidingFitResultMap (const pandora::ClusterVector &clusterVector, TwoDSlidingFitResultMap &slidingFitResultMap) const
 Build the map of sliding fit results. More...
 
pandora::StatusCode FindBestSplitPosition (const TwoDSlidingFitResult &slidingFitResult, pandora::CartesianVector &splitPosition, pandora::CartesianVector &splitDirection1, pandora::CartesianVector &splitDirection2) const
 Find the position of greatest scatter along a sliding linear fit. More...
 
pandora::StatusCode ConfirmSplitPosition (const TwoDSlidingFitResult &branchSlidingFitResult, const TwoDSlidingFitResult &replacementSlidingFitResult, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &splitDirection1, const pandora::CartesianVector &splitDirection2, float &lengthSquared1, float &lengthSquared2) const
 Find a second replacement cluster that aligns with the scatter of the first branch cluster. More...
 
pandora::StatusCode PerformSingleSplit (const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &forwardDirection, const pandora::CartesianVector &backwardDirection) const
 Split a branch cluster for case of one replacement cluster. More...
 
pandora::StatusCode PerformDoubleSplit (const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster1, const pandora::Cluster *const pReplacementCluster2, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &splitDirection1, const pandora::CartesianVector &splitDirection2) const
 Split a branch cluster for case of two replacement clusters. More...
 
void GetCaloHitListToMove (const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &forwardDirection, const pandora::CartesianVector &backwardDirection, pandora::CaloHitList &caloHitList) const
 Get list of calo hits to move in order to split a branch cluster into two segments for case of one replacement cluster. More...
 
void GetCaloHitListsToMove (const pandora::Cluster *const pBranchCluster, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &splitDirection1, const pandora::CartesianVector &splitDirection2, pandora::CaloHitList &caloHitList1, pandora::CaloHitList &caloHitList2) const
 Get lists of calo hits to move in order to split a branch cluster into two segments for case of two replacement clusters. More...
 
bool IdentifyCrossedTracks (const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster1, const pandora::Cluster *const pReplacementCluster2, const pandora::CartesianVector &splitPosition) const
 Identify crossed tracks formed from the branch cluster and its replacement cluster. More...
 
pandora::StatusCode GetCaloHitListToKeep (const pandora::Cluster *const pBranchCluster, const pandora::CaloHitList &caloHitListToMove, pandora::CaloHitList &caloHitListToKeep) const
 Split the branch cluster and add hits to the replacement cluster. More...
 
pandora::StatusCode SplitCluster (const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster, const pandora::CaloHitList &caloHitListToMove) const
 Split the branch cluster and add hits to the replacement cluster. More...
 

Private Attributes

float m_clusterMinLength
 minimum length of clusters for this algorithm More...
 
unsigned int m_halfWindowLayers
 number of layers to use for half-window of sliding fit More...
 
float m_samplingPitch
 sampling pitch for walking along sliding linear fit More...
 
float m_maxCosSplittingAngle
 smallest scatter angle allowed when splitting cluster More...
 
float m_minCosMergingAngle
 largest relative angle allowed when merging clusters More...
 
float m_maxTransverseDisplacement
 maximum transverse displacement of associated clusters More...
 
float m_maxLongitudinalDisplacement
 maximum longitudinal displacement of associated clusters More...
 
float m_maxLongitudinalDisplacementSquared
 longitudinal displacement squared More...
 

Detailed Description

CosmicRaySplittingAlgorithm class.

Definition at line 21 of file CosmicRaySplittingAlgorithm.h.

Constructor & Destructor Documentation

lar_content::CosmicRaySplittingAlgorithm::CosmicRaySplittingAlgorithm ( )

Default constructor.

Definition at line 22 of file CosmicRaySplittingAlgorithm.cc.

22  :
25  m_samplingPitch(1.f),
31 {
32 }
float m_maxLongitudinalDisplacement
maximum longitudinal displacement of associated clusters
float m_clusterMinLength
minimum length of clusters for this algorithm
float m_minCosMergingAngle
largest relative angle allowed when merging clusters
float m_maxCosSplittingAngle
smallest scatter angle allowed when splitting cluster
float m_maxLongitudinalDisplacementSquared
longitudinal displacement squared
float m_maxTransverseDisplacement
maximum transverse displacement of associated clusters
unsigned int m_halfWindowLayers
number of layers to use for half-window of sliding fit
float m_samplingPitch
sampling pitch for walking along sliding linear fit

Member Function Documentation

void lar_content::CosmicRaySplittingAlgorithm::BuildSlidingFitResultMap ( const pandora::ClusterVector &  clusterVector,
TwoDSlidingFitResultMap slidingFitResultMap 
) const
private

Build the map of sliding fit results.

Parameters
clusterVectorthe input cluster vector
slidingFitResultMapthe output sliding fit result map

Definition at line 181 of file CosmicRaySplittingAlgorithm.cc.

182 {
183  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
184 
185  for (ClusterVector::const_iterator iter = clusterVector.begin(), iterEnd = clusterVector.end(); iter != iterEnd; ++iter)
186  {
187  if (slidingFitResultMap.end() == slidingFitResultMap.find(*iter))
188  {
189  try
190  {
191  const TwoDSlidingFitResult slidingFitResult(*iter, m_halfWindowLayers, slidingFitPitch);
192 
193  if (!slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(*iter, slidingFitResult)).second)
194  throw StatusCodeException(STATUS_CODE_FAILURE);
195  }
196  catch (StatusCodeException &statusCodeException)
197  {
198  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
199  throw statusCodeException;
200  }
201  }
202  }
203 }
intermediate_table::const_iterator const_iterator
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
unsigned int m_halfWindowLayers
number of layers to use for half-window of sliding fit
StatusCode lar_content::CosmicRaySplittingAlgorithm::ConfirmSplitPosition ( const TwoDSlidingFitResult branchSlidingFitResult,
const TwoDSlidingFitResult replacementSlidingFitResult,
const pandora::CartesianVector &  splitPosition,
const pandora::CartesianVector &  splitDirection1,
const pandora::CartesianVector &  splitDirection2,
float &  lengthSquared1,
float &  lengthSquared2 
) const
private

Find a second replacement cluster that aligns with the scatter of the first branch cluster.

Parameters
branchSlidingFitResultthe sliding fit result for the branch cluster
replacementSlidingFitResultthe sliding fit result for the replacement cluster
splitPositionthe candidate split position on the branch cluster
splitDirection1the first track direction just above the split position
splitDirection2the second track direction just below the split position
lengthSquared1figure of merit for association with first track direction
lengthSquared2figure of merit for association with second track direction

Definition at line 270 of file CosmicRaySplittingAlgorithm.cc.

273 {
274  // Check if the replacement cluster points to the split position on the branch cluster
275  bestLengthSquared1 = std::numeric_limits<float>::max();
276  bestLengthSquared2 = std::numeric_limits<float>::max();
277 
278  bool foundMatch(false);
279 
280  const CartesianVector minPosition(replacementSlidingFitResult.GetGlobalMinLayerPosition());
281  const CartesianVector maxPosition(replacementSlidingFitResult.GetGlobalMaxLayerPosition());
282  const CartesianVector minDirection(replacementSlidingFitResult.GetGlobalMinLayerDirection());
283  const CartesianVector maxDirection(replacementSlidingFitResult.GetGlobalMaxLayerDirection());
284 
285  const CartesianVector branchVertex1(branchSlidingFitResult.GetGlobalMinLayerPosition());
286  const CartesianVector branchVertex2(branchSlidingFitResult.GetGlobalMaxLayerPosition());
287  const CartesianVector branchDirection1(splitDirection1 * -1.f);
288  const CartesianVector branchDirection2(splitDirection2 * -1.f);
289 
290  const float cosSplittingAngle(-splitDirection1.GetDotProduct(splitDirection2));
291  const float branchLengthSquared((branchVertex2 - branchVertex1).GetMagnitudeSquared());
292  const float replacementLengthSquared((maxPosition - minPosition).GetMagnitudeSquared());
293 
294  // Loop over each end of the replacement cluster
295  for (unsigned int iFwd = 0; iFwd < 2; ++iFwd)
296  {
297  const CartesianVector pAxis((0 == iFwd) ? (maxPosition - minPosition) : (minPosition - maxPosition));
298  const CartesianVector vtxPosition((0 == iFwd) ? minPosition : maxPosition);
299  const CartesianVector endPosition((0 == iFwd) ? maxPosition : minPosition);
300  const CartesianVector vtxDirection((0 == iFwd) ? (pAxis.GetDotProduct(minDirection) > 0 ? minDirection : minDirection * -1.f)
301  : (pAxis.GetDotProduct(maxDirection) > 0 ? maxDirection : maxDirection * -1.f));
302 
303  // Choose the correct end of the replacement cluster and require proximity to the branch cluster
304  const float vtxDisplacement(LArClusterHelper::GetClosestDistance(vtxPosition, branchSlidingFitResult.GetCluster()));
305  const float endDisplacement(LArClusterHelper::GetClosestDistance(endPosition, branchSlidingFitResult.GetCluster()));
306 
307  const float lengthSquared((vtxPosition - splitPosition).GetMagnitudeSquared());
308  const float lengthSquared1((vtxPosition - branchVertex1).GetMagnitudeSquared());
309  const float lengthSquared2((vtxPosition - branchVertex2).GetMagnitudeSquared());
310 
311  if (vtxDisplacement > endDisplacement)
312  continue;
313 
314  if (std::min(lengthSquared, std::min(lengthSquared1, lengthSquared2)) > std::min(branchLengthSquared, replacementLengthSquared))
315  continue;
316 
317  // Require good pointing information between replacement cluster and candidate split position
318  float impactL(0.f), impactT(0.f);
319  LArPointingClusterHelper::GetImpactParameters(vtxPosition, vtxDirection, splitPosition, impactL, impactT);
320 
321  if (impactT > m_maxTransverseDisplacement || impactL > m_maxLongitudinalDisplacement || impactL < -1.f ||
322  impactT > std::max(1.5f, 0.577f * (1.f + impactL)))
323  continue;
324 
325  // Check the segment of the branch cluster above the split position
326  if (vtxDirection.GetDotProduct(branchDirection1) > std::max(m_minCosMergingAngle, cosSplittingAngle))
327  {
328  if (lengthSquared < bestLengthSquared1)
329  {
330  bestLengthSquared1 = lengthSquared;
331  foundMatch = true;
332  }
333  }
334 
335  // Check the segment of the branch cluster below the split position
336  if (vtxDirection.GetDotProduct(branchDirection2) > std::max(m_minCosMergingAngle, cosSplittingAngle))
337  {
338  if (lengthSquared < bestLengthSquared2)
339  {
340  bestLengthSquared2 = lengthSquared;
341  foundMatch = true;
342  }
343  }
344  }
345 
346  if (!foundMatch)
347  return STATUS_CODE_NOT_FOUND;
348 
349  return STATUS_CODE_SUCCESS;
350 }
float m_maxLongitudinalDisplacement
maximum longitudinal displacement of associated clusters
static void GetImpactParameters(const LArPointingCluster::Vertex &pointingVertex, const LArPointingCluster::Vertex &targetVertex, float &longitudinal, float &transverse)
Calculate impact parameters between a pair of pointing vertices.
float m_minCosMergingAngle
largest relative angle allowed when merging clusters
static int max(int a, int b)
float m_maxTransverseDisplacement
maximum transverse displacement of associated clusters
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
StatusCode lar_content::CosmicRaySplittingAlgorithm::FindBestSplitPosition ( const TwoDSlidingFitResult slidingFitResult,
pandora::CartesianVector &  splitPosition,
pandora::CartesianVector &  splitDirection1,
pandora::CartesianVector &  splitDirection2 
) const
private

Find the position of greatest scatter along a sliding linear fit.

Parameters
slidingFitResultthe input sliding linear fit result
splitPositionthe position of greatest scatter
splitDirection1the direction vector just above the scatter position
splitDirection2the direction vector just below the scatter position

Definition at line 207 of file CosmicRaySplittingAlgorithm.cc.

209 {
210  // Find position of greatest scatter for this cluster
211  float splitCosTheta(m_maxCosSplittingAngle);
212  bool foundSplit(false);
213 
214  const CartesianVector &minPosition(branchSlidingFitResult.GetGlobalMinLayerPosition());
215  const CartesianVector &maxPosition(branchSlidingFitResult.GetGlobalMaxLayerPosition());
216  const float halfWindowLength(branchSlidingFitResult.GetLayerFitHalfWindowLength());
217 
218  float minL(0.f), maxL(0.f), minT(0.f), maxT(0.f);
219  branchSlidingFitResult.GetLocalPosition(minPosition, minL, minT);
220  branchSlidingFitResult.GetLocalPosition(maxPosition, maxL, maxT);
221 
222  const unsigned int nSamplingPoints = static_cast<unsigned int>((maxL - minL) / m_samplingPitch);
223 
224  for (unsigned int n = 0; n < nSamplingPoints; ++n)
225  {
226  const float alpha((0.5f + static_cast<float>(n)) / static_cast<float>(nSamplingPoints));
227  const float rL(minL + (maxL - minL) * alpha);
228 
229  CartesianVector centralPosition(0.f, 0.f, 0.f), forwardDirection(0.f, 0.f, 0.f), backwardDirection(0.f, 0.f, 0.f);
230 
231  if ((STATUS_CODE_SUCCESS != branchSlidingFitResult.GetGlobalFitPosition(rL, centralPosition)) ||
232  (STATUS_CODE_SUCCESS != branchSlidingFitResult.GetGlobalFitDirection(rL + halfWindowLength, forwardDirection)) ||
233  (STATUS_CODE_SUCCESS != branchSlidingFitResult.GetGlobalFitDirection(rL - halfWindowLength, backwardDirection)))
234  {
235  continue;
236  }
237 
238  const float cosTheta(forwardDirection.GetDotProduct(backwardDirection));
239 
240  if (cosTheta < splitCosTheta)
241  {
242  CartesianVector forwardPosition(0.f, 0.f, 0.f);
243  CartesianVector backwardPosition(0.f, 0.f, 0.f);
244 
245  if ((STATUS_CODE_SUCCESS != branchSlidingFitResult.GetGlobalFitPosition(rL + halfWindowLength, forwardPosition)) ||
246  (STATUS_CODE_SUCCESS != branchSlidingFitResult.GetGlobalFitPosition(rL - halfWindowLength, backwardPosition)))
247  {
248  continue;
249  }
250 
251  CartesianVector forwardVectorOutwards(forwardPosition - centralPosition);
252  CartesianVector backwardVectorOutwards(backwardPosition - centralPosition);
253 
254  splitPosition = centralPosition;
255  splitDirection1 = (forwardDirection.GetDotProduct(forwardVectorOutwards) > 0.f) ? forwardDirection : forwardDirection * -1.f;
256  splitDirection2 = (backwardDirection.GetDotProduct(backwardVectorOutwards) > 0.f) ? backwardDirection : backwardDirection * -1.f;
257  splitCosTheta = cosTheta;
258  foundSplit = true;
259  }
260  }
261 
262  if (!foundSplit)
263  return STATUS_CODE_NOT_FOUND;
264 
265  return STATUS_CODE_SUCCESS;
266 }
std::void_t< T > n
float m_maxCosSplittingAngle
smallest scatter angle allowed when splitting cluster
double alpha
Definition: doAna.cpp:15
float m_samplingPitch
sampling pitch for walking along sliding linear fit
void lar_content::CosmicRaySplittingAlgorithm::GetCaloHitListsToMove ( const pandora::Cluster *const  pBranchCluster,
const pandora::CartesianVector &  splitPosition,
const pandora::CartesianVector &  splitDirection1,
const pandora::CartesianVector &  splitDirection2,
pandora::CaloHitList &  caloHitList1,
pandora::CaloHitList &  caloHitList2 
) const
private

Get lists of calo hits to move in order to split a branch cluster into two segments for case of two replacement clusters.

Parameters
pBranchClusterthe branch cluster
splitPositionthe split position
splitDirection1the direction of the branch cluster just above the split position
splitDirection2the direction of the branch cluster just below the split position
caloHitList1the first segment to be split from the branch cluster
caloHitList2the second segment to be split from the branch cluster

Definition at line 449 of file CosmicRaySplittingAlgorithm.cc.

451 {
452  CaloHitList caloHitListToSort;
453  pBranchCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitListToSort);
454 
455  for (CaloHitList::const_iterator iter = caloHitListToSort.begin(), iterEnd = caloHitListToSort.end(); iter != iterEnd; ++iter)
456  {
457  const CaloHit *const pCaloHit = *iter;
458 
459  const float displacement1(splitDirection1.GetDotProduct(pCaloHit->GetPositionVector() - splitPosition));
460  const float displacement2(splitDirection2.GetDotProduct(pCaloHit->GetPositionVector() - splitPosition));
461 
462  if (displacement1 > displacement2)
463  {
464  caloHitListToMove1.push_back(pCaloHit);
465  }
466  else
467  {
468  caloHitListToMove2.push_back(pCaloHit);
469  }
470  }
471 }
intermediate_table::const_iterator const_iterator
StatusCode lar_content::CosmicRaySplittingAlgorithm::GetCaloHitListToKeep ( const pandora::Cluster *const  pBranchCluster,
const pandora::CaloHitList &  caloHitListToMove,
pandora::CaloHitList &  caloHitListToKeep 
) const
private

Split the branch cluster and add hits to the replacement cluster.

Parameters
pBranchClusterthe branch cluster
caloHitListToMovethe list of hits to be removed from the branch cluster and added to the replacement cluster
caloHitListToKeepto receive the list of calo hits to keep

Definition at line 491 of file CosmicRaySplittingAlgorithm.cc.

493 {
494  if (caloHitListToMove.empty())
495  return STATUS_CODE_FAILURE;
496 
497  CaloHitList caloHitList;
498  pBranchCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
499 
500  for (CaloHitList::const_iterator iter = caloHitList.begin(), iterEnd = caloHitList.end(); iter != iterEnd; ++iter)
501  {
502  const CaloHit *const pCaloHit = *iter;
503 
504  if (caloHitListToMove.end() == std::find(caloHitListToMove.begin(), caloHitListToMove.end(), pCaloHit))
505  caloHitListToKeep.push_back(pCaloHit);
506  }
507 
508  return STATUS_CODE_SUCCESS;
509 }
intermediate_table::const_iterator const_iterator
void lar_content::CosmicRaySplittingAlgorithm::GetCaloHitListToMove ( const pandora::Cluster *const  pBranchCluster,
const pandora::Cluster *const  pReplacementCluster,
const pandora::CartesianVector &  splitPosition,
const pandora::CartesianVector &  forwardDirection,
const pandora::CartesianVector &  backwardDirection,
pandora::CaloHitList &  caloHitList 
) const
private

Get list of calo hits to move in order to split a branch cluster into two segments for case of one replacement cluster.

Parameters
pBranchClusterthe branch cluster
pReplacementClusterthe replacement cluster
splitPositionthe split position
forwardDirectionthe direction of the branch cluster just above the split position
backwardDirectionthe direction of the branch cluster just below the split position
caloHitListthe output hits to be removed from the branch cluster

Definition at line 397 of file CosmicRaySplittingAlgorithm.cc.

400 {
401  const CartesianVector forwardPosition(LArClusterHelper::GetClosestPosition(splitPosition, pBranchCluster));
402  const CartesianVector vtxPosition(LArClusterHelper::GetClosestPosition(splitPosition, pReplacementCluster));
403  const CartesianVector vtxDirection((forwardPosition - vtxPosition).GetUnitVector());
404 
405  CaloHitList caloHitListToSort, caloHitListToCheck;
406  pBranchCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitListToSort);
407 
408  for (CaloHitList::const_iterator iter = caloHitListToSort.begin(), iterEnd = caloHitListToSort.end(); iter != iterEnd; ++iter)
409  {
410  const CaloHit *const pCaloHit = *iter;
411 
412  if (forwardDirection.GetDotProduct(pCaloHit->GetPositionVector() - forwardPosition) > 0.f)
413  {
414  caloHitListToMove.push_back(pCaloHit);
415  }
416  else if (forwardDirection.GetDotProduct(pCaloHit->GetPositionVector() - vtxPosition) > -1.25f)
417  {
418  caloHitListToCheck.push_back(pCaloHit);
419  }
420  }
421 
422  float closestLengthSquared(std::numeric_limits<float>::max());
423 
424  for (CaloHitList::const_iterator iter = caloHitListToCheck.begin(), iterEnd = caloHitListToCheck.end(); iter != iterEnd; ++iter)
425  {
426  const CaloHit *const pCaloHit = *iter;
427 
428  if (vtxDirection.GetCrossProduct(pCaloHit->GetPositionVector() - forwardPosition).GetMagnitude() >
429  backwardDirection.GetCrossProduct(pCaloHit->GetPositionVector() - forwardPosition).GetMagnitude())
430  continue;
431 
432  const float lengthSquared((pCaloHit->GetPositionVector() - vtxPosition).GetMagnitudeSquared());
433 
434  if (lengthSquared < closestLengthSquared)
435  closestLengthSquared = lengthSquared;
436  }
437 
438  for (CaloHitList::const_iterator iter = caloHitListToCheck.begin(), iterEnd = caloHitListToCheck.end(); iter != iterEnd; ++iter)
439  {
440  const CaloHit *const pCaloHit = *iter;
441 
442  if ((pCaloHit->GetPositionVector() - vtxPosition).GetMagnitudeSquared() >= closestLengthSquared)
443  caloHitListToMove.push_back(pCaloHit);
444  }
445 }
intermediate_table::const_iterator const_iterator
static int max(int a, int b)
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
void lar_content::CosmicRaySplittingAlgorithm::GetListOfCleanClusters ( const pandora::ClusterList *const  pClusterList,
pandora::ClusterVector &  clusterVector 
) const
private

Populate cluster vector with subset of cluster list, containing clusters judged to be clean.

Parameters
pClusterListaddress of the cluster list
clusterVectorto receive the populated cluster vector

Definition at line 164 of file CosmicRaySplittingAlgorithm.cc.

165 {
166  for (ClusterList::const_iterator iter = pClusterList->begin(), iterEnd = pClusterList->end(); iter != iterEnd; ++iter)
167  {
168  const Cluster *const pCluster = *iter;
169 
171  continue;
172 
173  clusterVector.push_back(pCluster);
174  }
175 
176  std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
177 }
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.
intermediate_table::const_iterator const_iterator
float m_clusterMinLength
minimum length of clusters for this algorithm
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster.
bool lar_content::CosmicRaySplittingAlgorithm::IdentifyCrossedTracks ( const pandora::Cluster *const  pBranchCluster,
const pandora::Cluster *const  pReplacementCluster1,
const pandora::Cluster *const  pReplacementCluster2,
const pandora::CartesianVector &  splitPosition 
) const
private

Identify crossed tracks formed from the branch cluster and its replacement cluster.

Parameters
pBranchClusterthe branch cluster
pReplacementCluster1the first replacement cluster
pReplacementCluster2the second replacement cluster
splitPositionthe split position

Definition at line 474 of file CosmicRaySplittingAlgorithm.cc.

476 {
477  CartesianVector branchVertex1(0.f, 0.f, 0.f), branchVertex2(0.f, 0.f, 0.f);
478  LArClusterHelper::GetExtremalCoordinates(pBranchCluster, branchVertex1, branchVertex2);
479 
480  const CartesianVector replacementVertex1(LArClusterHelper::GetClosestPosition(splitPosition, pReplacementCluster1));
481  const CartesianVector replacementVertex2(LArClusterHelper::GetClosestPosition(splitPosition, pReplacementCluster2));
482 
483  if ((replacementVertex2 - replacementVertex1).GetMagnitudeSquared() > (branchVertex2 - branchVertex1).GetMagnitudeSquared())
484  return false;
485 
486  return true;
487 }
static void GetExtremalCoordinates(const pandora::ClusterList &clusterList, pandora::CartesianVector &innerCoordinate, pandora::CartesianVector &outerCoordinate)
Get positions of the two most distant calo hits in a list of cluster (ordered by Z) ...
static pandora::CartesianVector GetClosestPosition(const pandora::CartesianVector &position, const pandora::ClusterList &clusterList)
Get closest position in a list of clusters to a specified input position vector.
StatusCode lar_content::CosmicRaySplittingAlgorithm::PerformDoubleSplit ( const pandora::Cluster *const  pBranchCluster,
const pandora::Cluster *const  pReplacementCluster1,
const pandora::Cluster *const  pReplacementCluster2,
const pandora::CartesianVector &  splitPosition,
const pandora::CartesianVector &  splitDirection1,
const pandora::CartesianVector &  splitDirection2 
) const
private

Split a branch cluster for case of two replacement clusters.

Parameters
pBranchClusterthe branch cluster
pReplacementCluster1the first replacement cluster
pReplacementCluster2the second replacement cluster
splitPositionthe split position
splitDirection1the direction of the branch cluster just above the split position
splitDirection2the direction of the branch cluster just below the split position

Definition at line 371 of file CosmicRaySplittingAlgorithm.cc.

374 {
375  CaloHitList caloHitListToMove1, caloHitListToMove2;
376  this->GetCaloHitListsToMove(pBranchCluster, splitPosition, splitDirection1, splitDirection2, caloHitListToMove1, caloHitListToMove2);
377 
378  CaloHitList caloHitListToKeep1;
379  this->GetCaloHitListToKeep(pBranchCluster, caloHitListToMove1, caloHitListToKeep1);
380 
381  if (caloHitListToKeep1.empty())
382  return STATUS_CODE_FAILURE;
383 
384  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->SplitCluster(pBranchCluster, pReplacementCluster1, caloHitListToMove1));
385 
386  CaloHitList caloHitListToKeep2;
387  this->GetCaloHitListToKeep(pBranchCluster, caloHitListToMove2, caloHitListToKeep2);
388 
389  if (caloHitListToKeep2.empty())
390  return PandoraContentApi::MergeAndDeleteClusters(*this, pReplacementCluster2, pBranchCluster);
391 
392  return this->SplitCluster(pBranchCluster, pReplacementCluster2, caloHitListToMove2);
393 }
void GetCaloHitListsToMove(const pandora::Cluster *const pBranchCluster, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &splitDirection1, const pandora::CartesianVector &splitDirection2, pandora::CaloHitList &caloHitList1, pandora::CaloHitList &caloHitList2) const
Get lists of calo hits to move in order to split a branch cluster into two segments for case of two r...
pandora::StatusCode SplitCluster(const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster, const pandora::CaloHitList &caloHitListToMove) const
Split the branch cluster and add hits to the replacement cluster.
pandora::StatusCode GetCaloHitListToKeep(const pandora::Cluster *const pBranchCluster, const pandora::CaloHitList &caloHitListToMove, pandora::CaloHitList &caloHitListToKeep) const
Split the branch cluster and add hits to the replacement cluster.
StatusCode lar_content::CosmicRaySplittingAlgorithm::PerformSingleSplit ( const pandora::Cluster *const  pBranchCluster,
const pandora::Cluster *const  pReplacementCluster,
const pandora::CartesianVector &  splitPosition,
const pandora::CartesianVector &  forwardDirection,
const pandora::CartesianVector &  backwardDirection 
) const
private

Split a branch cluster for case of one replacement cluster.

Parameters
pBranchClusterthe branch cluster
pReplacementClusterthe replacement cluster
splitPositionthe split position
forwardDirectionthe direction of the branch cluster just above the split position
backwardDirectionthe direction of the branch cluster just below the split position

Definition at line 354 of file CosmicRaySplittingAlgorithm.cc.

356 {
357  CaloHitList caloHitListToMove;
358  this->GetCaloHitListToMove(pBranchCluster, pReplacementCluster, splitPosition, forwardDirection, backwardDirection, caloHitListToMove);
359 
360  CaloHitList caloHitListToKeep;
361  this->GetCaloHitListToKeep(pBranchCluster, caloHitListToMove, caloHitListToKeep);
362 
363  if (caloHitListToKeep.empty())
364  return PandoraContentApi::MergeAndDeleteClusters(*this, pReplacementCluster, pBranchCluster);
365 
366  return this->SplitCluster(pBranchCluster, pReplacementCluster, caloHitListToMove);
367 }
void GetCaloHitListToMove(const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &forwardDirection, const pandora::CartesianVector &backwardDirection, pandora::CaloHitList &caloHitList) const
Get list of calo hits to move in order to split a branch cluster into two segments for case of one re...
pandora::StatusCode SplitCluster(const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster, const pandora::CaloHitList &caloHitListToMove) const
Split the branch cluster and add hits to the replacement cluster.
pandora::StatusCode GetCaloHitListToKeep(const pandora::Cluster *const pBranchCluster, const pandora::CaloHitList &caloHitListToMove, pandora::CaloHitList &caloHitListToKeep) const
Split the branch cluster and add hits to the replacement cluster.
StatusCode lar_content::CosmicRaySplittingAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
private

Definition at line 531 of file CosmicRaySplittingAlgorithm.cc.

532 {
533  PANDORA_RETURN_RESULT_IF_AND_IF(
534  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ClusterMinLength", m_clusterMinLength));
535 
536  PANDORA_RETURN_RESULT_IF_AND_IF(
537  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SlidingFitHalfWindow", m_halfWindowLayers));
538 
539  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SamplingPitch", m_samplingPitch));
540 
541  if (m_samplingPitch < std::numeric_limits<float>::epsilon())
542  return STATUS_CODE_INVALID_PARAMETER;
543 
544  PANDORA_RETURN_RESULT_IF_AND_IF(
545  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxCosSplittingAngle", m_maxCosSplittingAngle));
546 
547  PANDORA_RETURN_RESULT_IF_AND_IF(
548  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MinCosMergingAngle", m_minCosMergingAngle));
549 
550  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
551  XmlHelper::ReadValue(xmlHandle, "MaxTransverseDisplacement", m_maxTransverseDisplacement));
552 
553  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
554  XmlHelper::ReadValue(xmlHandle, "MaxLongitudinalDisplacement", m_maxLongitudinalDisplacement));
556 
557  return STATUS_CODE_SUCCESS;
558 }
float m_maxLongitudinalDisplacement
maximum longitudinal displacement of associated clusters
float m_clusterMinLength
minimum length of clusters for this algorithm
float m_minCosMergingAngle
largest relative angle allowed when merging clusters
float m_maxCosSplittingAngle
smallest scatter angle allowed when splitting cluster
float m_maxLongitudinalDisplacementSquared
longitudinal displacement squared
float m_maxTransverseDisplacement
maximum transverse displacement of associated clusters
unsigned int m_halfWindowLayers
number of layers to use for half-window of sliding fit
float m_samplingPitch
sampling pitch for walking along sliding linear fit
StatusCode lar_content::CosmicRaySplittingAlgorithm::Run ( )
private

Definition at line 36 of file CosmicRaySplittingAlgorithm.cc.

37 {
38  const ClusterList *pClusterList = NULL;
39  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pClusterList));
40 
41  // Get ordered list of clean clusters
42  ClusterVector clusterVector;
43  this->GetListOfCleanClusters(pClusterList, clusterVector);
44 
45  // Calculate sliding fit results for clean clusters
46  TwoDSlidingFitResultMap slidingFitResultMap;
47  this->BuildSlidingFitResultMap(clusterVector, slidingFitResultMap);
48 
49  // Loop over clusters, identify and perform splits
50  ClusterSet splitClusters;
51 
52  for (ClusterVector::const_iterator bIter = clusterVector.begin(), bIterEnd1 = clusterVector.end(); bIter != bIterEnd1; ++bIter)
53  {
54  if (splitClusters.count(*bIter) > 0)
55  continue;
56 
57  TwoDSlidingFitResultMap::const_iterator bFitIter = slidingFitResultMap.find(*bIter);
58 
59  if (slidingFitResultMap.end() == bFitIter)
60  continue;
61 
62  const TwoDSlidingFitResult &branchSlidingFitResult(bFitIter->second);
63 
64  // Find best split position for candidate branch cluster
65  CartesianVector splitPosition(0.f, 0.f, 0.f);
66  CartesianVector splitDirection1(0.f, 0.f, 0.f);
67  CartesianVector splitDirection2(0.f, 0.f, 0.f);
68 
69  if (STATUS_CODE_SUCCESS != this->FindBestSplitPosition(branchSlidingFitResult, splitPosition, splitDirection1, splitDirection2))
70  continue;
71 
72  // Find candidate replacement clusters to merge into branch cluster at the split position
73  TwoDSlidingFitResultMap::const_iterator bestReplacementIter1(slidingFitResultMap.end());
74  TwoDSlidingFitResultMap::const_iterator bestReplacementIter2(slidingFitResultMap.end());
75 
76  float bestLengthSquared1(m_maxLongitudinalDisplacementSquared);
77  float bestLengthSquared2(m_maxLongitudinalDisplacementSquared);
78 
79  for (ClusterVector::const_iterator rIter = clusterVector.begin(), rIterEnd = clusterVector.end(); rIter != rIterEnd; ++rIter)
80  {
81  if (splitClusters.count(*rIter) > 0)
82  continue;
83 
84  TwoDSlidingFitResultMap::const_iterator rFitIter = slidingFitResultMap.find(*rIter);
85 
86  if (slidingFitResultMap.end() == rFitIter)
87  continue;
88 
89  const TwoDSlidingFitResult &replacementSlidingFitResult(rFitIter->second);
90 
91  if (branchSlidingFitResult.GetCluster() == replacementSlidingFitResult.GetCluster())
92  continue;
93 
94  float lengthSquared1(std::numeric_limits<float>::max());
95  float lengthSquared2(std::numeric_limits<float>::max());
96 
97  if (STATUS_CODE_SUCCESS != this->ConfirmSplitPosition(branchSlidingFitResult, replacementSlidingFitResult, splitPosition,
98  splitDirection1, splitDirection2, lengthSquared1, lengthSquared2))
99  continue;
100 
101  if (lengthSquared1 < bestLengthSquared1)
102  {
103  bestLengthSquared1 = lengthSquared1;
104  bestReplacementIter1 = rFitIter;
105  }
106 
107  if (lengthSquared2 < bestLengthSquared2)
108  {
109  bestLengthSquared2 = lengthSquared2;
110  bestReplacementIter2 = rFitIter;
111  }
112  }
113 
114  const Cluster *pReplacementCluster1 = NULL;
115  const Cluster *pReplacementCluster2 = NULL;
116 
117  if (slidingFitResultMap.end() != bestReplacementIter1)
118  pReplacementCluster1 = bestReplacementIter1->first;
119 
120  if (slidingFitResultMap.end() != bestReplacementIter2)
121  pReplacementCluster2 = bestReplacementIter2->first;
122 
123  if (NULL == pReplacementCluster1 && NULL == pReplacementCluster2)
124  continue;
125 
126  const Cluster *const pBranchCluster = branchSlidingFitResult.GetCluster();
127 
128  // Crossed tracks
129  if (pReplacementCluster1 && pReplacementCluster2)
130  {
131  if (!(this->IdentifyCrossedTracks(pBranchCluster, pReplacementCluster1, pReplacementCluster2, splitPosition)))
132  continue;
133 
134  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
135  this->PerformDoubleSplit(pBranchCluster, pReplacementCluster1, pReplacementCluster2, splitPosition, splitDirection1, splitDirection2));
136  }
137  // Single scatter
138  else if (pReplacementCluster1)
139  {
140  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
141  this->PerformSingleSplit(pBranchCluster, pReplacementCluster1, splitPosition, splitDirection1, splitDirection2));
142  }
143  else if (pReplacementCluster2)
144  {
145  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=,
146  this->PerformSingleSplit(pBranchCluster, pReplacementCluster2, splitPosition, splitDirection2, splitDirection1));
147  }
148 
149  // Choose not to re-use clusters (for now)
150  if (pReplacementCluster1)
151  splitClusters.insert(pReplacementCluster1);
152 
153  if (pReplacementCluster2)
154  splitClusters.insert(pReplacementCluster2);
155 
156  splitClusters.insert(pBranchCluster);
157  }
158 
159  return STATUS_CODE_SUCCESS;
160 }
void GetListOfCleanClusters(const pandora::ClusterList *const pClusterList, pandora::ClusterVector &clusterVector) const
Populate cluster vector with subset of cluster list, containing clusters judged to be clean...
bool IdentifyCrossedTracks(const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster1, const pandora::Cluster *const pReplacementCluster2, const pandora::CartesianVector &splitPosition) const
Identify crossed tracks formed from the branch cluster and its replacement cluster.
intermediate_table::const_iterator const_iterator
pandora::StatusCode PerformSingleSplit(const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &forwardDirection, const pandora::CartesianVector &backwardDirection) const
Split a branch cluster for case of one replacement cluster.
float m_maxLongitudinalDisplacementSquared
longitudinal displacement squared
pandora::StatusCode PerformDoubleSplit(const pandora::Cluster *const pBranchCluster, const pandora::Cluster *const pReplacementCluster1, const pandora::Cluster *const pReplacementCluster2, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &splitDirection1, const pandora::CartesianVector &splitDirection2) const
Split a branch cluster for case of two replacement clusters.
static int max(int a, int b)
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
void BuildSlidingFitResultMap(const pandora::ClusterVector &clusterVector, TwoDSlidingFitResultMap &slidingFitResultMap) const
Build the map of sliding fit results.
pandora::StatusCode ConfirmSplitPosition(const TwoDSlidingFitResult &branchSlidingFitResult, const TwoDSlidingFitResult &replacementSlidingFitResult, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &splitDirection1, const pandora::CartesianVector &splitDirection2, float &lengthSquared1, float &lengthSquared2) const
Find a second replacement cluster that aligns with the scatter of the first branch cluster...
std::vector< art::Ptr< recob::Cluster > > ClusterVector
pandora::StatusCode FindBestSplitPosition(const TwoDSlidingFitResult &slidingFitResult, pandora::CartesianVector &splitPosition, pandora::CartesianVector &splitDirection1, pandora::CartesianVector &splitDirection2) const
Find the position of greatest scatter along a sliding linear fit.
if(!yymsg) yymsg
StatusCode lar_content::CosmicRaySplittingAlgorithm::SplitCluster ( const pandora::Cluster *const  pBranchCluster,
const pandora::Cluster *const  pReplacementCluster,
const pandora::CaloHitList &  caloHitListToMove 
) const
private

Split the branch cluster and add hits to the replacement cluster.

Parameters
pBranchClusterthe branch cluster
pReplacementClusterthe replacement cluster
caloHitListToMovethe list of hits to be removed from the branch cluster and added to the replacement cluster

Definition at line 513 of file CosmicRaySplittingAlgorithm.cc.

515 {
516  if (caloHitListToMove.empty())
517  return STATUS_CODE_FAILURE;
518 
519  for (CaloHitList::const_iterator iter = caloHitListToMove.begin(), iterEnd = caloHitListToMove.end(); iter != iterEnd; ++iter)
520  {
521  const CaloHit *const pCaloHit = *iter;
522  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::RemoveFromCluster(*this, pBranchCluster, pCaloHit));
523  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::AddToCluster(*this, pReplacementCluster, pCaloHit));
524  }
525 
526  return STATUS_CODE_SUCCESS;
527 }
intermediate_table::const_iterator const_iterator

Member Data Documentation

float lar_content::CosmicRaySplittingAlgorithm::m_clusterMinLength
private

minimum length of clusters for this algorithm

Definition at line 161 of file CosmicRaySplittingAlgorithm.h.

unsigned int lar_content::CosmicRaySplittingAlgorithm::m_halfWindowLayers
private

number of layers to use for half-window of sliding fit

Definition at line 162 of file CosmicRaySplittingAlgorithm.h.

float lar_content::CosmicRaySplittingAlgorithm::m_maxCosSplittingAngle
private

smallest scatter angle allowed when splitting cluster

Definition at line 164 of file CosmicRaySplittingAlgorithm.h.

float lar_content::CosmicRaySplittingAlgorithm::m_maxLongitudinalDisplacement
private

maximum longitudinal displacement of associated clusters

Definition at line 167 of file CosmicRaySplittingAlgorithm.h.

float lar_content::CosmicRaySplittingAlgorithm::m_maxLongitudinalDisplacementSquared
private

longitudinal displacement squared

Definition at line 168 of file CosmicRaySplittingAlgorithm.h.

float lar_content::CosmicRaySplittingAlgorithm::m_maxTransverseDisplacement
private

maximum transverse displacement of associated clusters

Definition at line 166 of file CosmicRaySplittingAlgorithm.h.

float lar_content::CosmicRaySplittingAlgorithm::m_minCosMergingAngle
private

largest relative angle allowed when merging clusters

Definition at line 165 of file CosmicRaySplittingAlgorithm.h.

float lar_content::CosmicRaySplittingAlgorithm::m_samplingPitch
private

sampling pitch for walking along sliding linear fit

Definition at line 163 of file CosmicRaySplittingAlgorithm.h.


The documentation for this class was generated from the following files: