LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
ConeClusterMopUpAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
13 
15 
17 
18 using namespace pandora;
19 
20 namespace lar_content
21 {
22 
23 ConeClusterMopUpAlgorithm::ConeClusterMopUpAlgorithm() :
24  m_slidingFitWindow(20),
25  m_showerEdgeMultiplier(1.5f),
26  m_coneAngleCentile(0.85f),
27  m_maxConeLengthMultiplier(1.5f),
28  m_minBoundedFraction(0.5f)
29 {
30 }
31 
32 //------------------------------------------------------------------------------------------------------------------------------------------
33 
34 void ConeClusterMopUpAlgorithm::ClusterMopUp(const ClusterList &pfoClusters, const ClusterList &remnantClusters) const
35 {
36  ClusterAssociationMap clusterAssociationMap;
37  const float slidingFitPitch(LArGeometryHelper::GetWireZPitch(this->GetPandora()));
38 
39  const VertexList *pVertexList(NULL);
40  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pVertexList));
41 
42  if ((pVertexList->size() != 1) || (VERTEX_3D != (*(pVertexList->begin()))->GetVertexType()))
43  return;
44 
45  const Vertex *const pVertex(*(pVertexList->begin()));
46 
47  ClusterVector sortedPfoClusters(pfoClusters.begin(), pfoClusters.end());
48  std::sort(sortedPfoClusters.begin(), sortedPfoClusters.end(), LArClusterHelper::SortByNHits);
49 
50  ClusterVector sortedRemnantClusters(remnantClusters.begin(), remnantClusters.end());
51  std::sort(sortedRemnantClusters.begin(), sortedRemnantClusters.end(), LArClusterHelper::SortByNHits);
52 
53  for (const Cluster *const pPfoCluster : sortedPfoClusters)
54  {
55  try
56  {
57  const TwoDSlidingShowerFitResult showerFitResult(pPfoCluster, m_slidingFitWindow, slidingFitPitch, m_showerEdgeMultiplier);
58 
59  const LayerFitResultMap &layerFitResultMapS(showerFitResult.GetShowerFitResult().GetLayerFitResultMap());
60  const LayerFitResultMap &layerFitResultMapP(showerFitResult.GetPositiveEdgeFitResult().GetLayerFitResultMap());
61  const LayerFitResultMap &layerFitResultMapN(showerFitResult.GetNegativeEdgeFitResult().GetLayerFitResultMap());
62 
63  if (layerFitResultMapS.size() < 2)
64  continue;
65 
66  // Cone direction
67  CartesianVector minLayerPositionOnAxis(0.f, 0.f, 0.f), maxLayerPositionOnAxis(0.f, 0.f, 0.f);
68  showerFitResult.GetShowerFitResult().GetGlobalPosition(layerFitResultMapS.begin()->second.GetL(), 0.f, minLayerPositionOnAxis);
69  showerFitResult.GetShowerFitResult().GetGlobalPosition(layerFitResultMapS.rbegin()->second.GetL(), 0.f, maxLayerPositionOnAxis);
70 
71  const HitType hitType(LArClusterHelper::GetClusterHitType(pPfoCluster));
72  const CartesianVector vertexPosition2D(LArGeometryHelper::ProjectPosition(this->GetPandora(), pVertex->GetPosition(), hitType));
73  const bool vertexAtMinL((vertexPosition2D - minLayerPositionOnAxis).GetMagnitudeSquared() < (vertexPosition2D - maxLayerPositionOnAxis).GetMagnitudeSquared());
74 
75  // Cone edges
76  CoordinateList coordinateListP, coordinateListN;
77 
78  for (LayerFitResultMap::const_iterator iterS = layerFitResultMapS.begin(); iterS != layerFitResultMapS.end(); ++iterS)
79  {
80  LayerFitResultMap::const_iterator iterP = layerFitResultMapP.find(iterS->first);
81  LayerFitResultMap::const_iterator iterN = layerFitResultMapN.find(iterS->first);
82 
83  if (layerFitResultMapP.end() != iterP)
84  coordinateListP.push_back(Coordinate(iterP->second.GetL(), iterP->second.GetFitT()));
85 
86  if (layerFitResultMapN.end() != iterN)
87  coordinateListN.push_back(Coordinate(iterN->second.GetL(), iterN->second.GetFitT()));
88  }
89 
90  if (coordinateListP.empty() || coordinateListN.empty())
91  continue;
92 
93  std::sort(coordinateListP.begin(), coordinateListP.end(), ConeClusterMopUpAlgorithm::SortCoordinates);
94  std::sort(coordinateListN.begin(), coordinateListN.end(), ConeClusterMopUpAlgorithm::SortCoordinates);
95 
96  const Coordinate maxP(coordinateListP.at(m_coneAngleCentile * coordinateListP.size()));
97  const Coordinate minP(vertexAtMinL ? Coordinate(layerFitResultMapP.begin()->second.GetL(), layerFitResultMapP.begin()->second.GetFitT()) :
98  Coordinate(layerFitResultMapP.rbegin()->second.GetL(), layerFitResultMapP.rbegin()->second.GetFitT()));
99 
100  const Coordinate maxN(coordinateListN.at((1.f - m_coneAngleCentile) * coordinateListN.size()));
101  const Coordinate minN(vertexAtMinL ? Coordinate(layerFitResultMapN.begin()->second.GetL(), layerFitResultMapN.begin()->second.GetFitT()) :
102  Coordinate(layerFitResultMapN.rbegin()->second.GetL(), layerFitResultMapN.rbegin()->second.GetFitT()));
103 
104  const float minL(layerFitResultMapS.begin()->second.GetL());
105  const float maxL(minL + m_maxConeLengthMultiplier * std::fabs(layerFitResultMapS.rbegin()->second.GetL() - minL));
106 
107  if ((std::fabs(maxP.first - minP.first) < std::numeric_limits<float>::epsilon()) ||
108  (std::fabs(maxN.first - minN.first) < std::numeric_limits<float>::epsilon()) ||
109  (std::fabs(maxL - minL) < std::numeric_limits<float>::epsilon()))
110  {
111  continue;
112  }
113 
114  // Bounded fraction calculation
115  for (const Cluster *const pRemnantCluster : sortedRemnantClusters)
116  {
117  const unsigned int nHits(pRemnantCluster->GetNCaloHits());
118 
119  unsigned int nMatchedHits(0);
120  const OrderedCaloHitList &orderedCaloHitList(pRemnantCluster->GetOrderedCaloHitList());
121 
122  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(), iterEnd = orderedCaloHitList.end(); iter != iterEnd; ++iter)
123  {
124  for (CaloHitList::const_iterator hIter = iter->second->begin(), hIterEnd = iter->second->end(); hIter != hIterEnd; ++hIter)
125  {
126  float rL(0.f), rT(0.f);
127  showerFitResult.GetShowerFitResult().GetLocalPosition((*hIter)->GetPositionVector(), rL, rT);
128 
129  if ((rL < minL) || (rL > maxL))
130  continue;
131 
132  const float rTP(minP.second + (rL - minP.first) * ((maxP.second - minP.second) / (maxP.first - minP.first)));
133  const float rTN(minN.second + (rL - minN.first) * ((maxN.second - minN.second) / (maxN.first - minN.first)));
134 
135  if ((rT > rTP) || (rT < rTN))
136  continue;
137 
138  ++nMatchedHits;
139  }
140  }
141 
142  const float boundedFraction((nHits > 0) ? static_cast<float>(nMatchedHits) / static_cast<float>(nHits) : 0.f);
143 
144  if (boundedFraction < m_minBoundedFraction)
145  continue;
146 
147  AssociationDetails &associationDetails(clusterAssociationMap[pRemnantCluster]);
148 
149  if (!associationDetails.insert(AssociationDetails::value_type(pPfoCluster, boundedFraction)).second)
150  throw StatusCodeException(STATUS_CODE_FAILURE);
151  }
152  }
153  catch (StatusCodeException &statusCodeException)
154  {
155  if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
156  throw statusCodeException;
157  }
158  }
159 
160  this->MakeClusterMerges(clusterAssociationMap);
161 }
162 
163 //------------------------------------------------------------------------------------------------------------------------------------------
164 
166 {
167  return (lhs.second < rhs.second);
168 }
169 
170 //------------------------------------------------------------------------------------------------------------------------------------------
171 
172 StatusCode ConeClusterMopUpAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
173 {
174  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
175  "SlidingFitWindow", m_slidingFitWindow));
176 
177  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
178  "ShowerEdgeMultiplier", m_showerEdgeMultiplier));
179 
180  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
181  "ConeAngleCentile", m_coneAngleCentile));
182 
183  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
184  "MaxConeLengthMultiplier", m_maxConeLengthMultiplier));
185 
186  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
187  "MinBoundedFraction", m_minBoundedFraction));
188 
189  return ClusterMopUpBaseAlgorithm::ReadSettings(xmlHandle);
190 }
191 
192 } // namespace lar_content
Header file for the lar two dimensional sliding shower fit result class.
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.
virtual void MakeClusterMerges(const ClusterAssociationMap &clusterAssociationMap) const
Make the cluster merges specified in the cluster association map, using list name information in the ...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
std::unordered_map< const pandora::Cluster *, float > AssociationDetails
static bool SortCoordinates(const Coordinate &lhs, const Coordinate &rhs)
Sort coordinates by increasing transverse displacement.
std::unordered_map< const pandora::Cluster *, AssociationDetails > ClusterAssociationMap
const TwoDSlidingFitResult & GetShowerFitResult() const
Get the sliding fit result for the full shower cluster.
static pandora::CartesianVector ProjectPosition(const pandora::Pandora &pandora, const pandora::CartesianVector &position3D, const pandora::HitType view)
Project 3D position into a given 2D view.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
float m_maxConeLengthMultiplier
Consider hits as bound if inside cone, with projected distance less than N times cone length...
float m_minBoundedFraction
The minimum cluster bounded fraction for merging.
TFile f
Definition: plotHisto.C:6
Header file for the geometry helper class.
Header file for the cone cluster mop up algorithm class.
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
intermediate_table::const_iterator const_iterator
Header file for the cluster helper class.
float m_showerEdgeMultiplier
Artificially tune width of shower envelope so as to make it more/less inclusive.
std::map< int, LayerFitResult > LayerFitResultMap
const TwoDSlidingFitResult & GetPositiveEdgeFitResult() const
Get the sliding fit result for the positive shower edge.
const LayerFitResultMap & GetLayerFitResultMap() const
Get the layer fit result map.
std::vector< art::Ptr< recob::Cluster > > ClusterVector
const TwoDSlidingFitResult & GetNegativeEdgeFitResult() const
Get the sliding fit result for the negative shower edge.
void GetGlobalPosition(const float rL, const float rT, pandora::CartesianVector &position) const
Get global coordinates for given sliding linear fit coordinates.
void ClusterMopUp(const pandora::ClusterList &pfoClusters, const pandora::ClusterList &remnantClusters) const
Cluster mop up for a single view. This function is responsible for instructing pandora to make cluste...
float m_coneAngleCentile
Cluster cone angle is defined using specified centile of distribution of hit half angles...
unsigned int m_slidingFitWindow
The layer window for the sliding linear fits.
void GetLocalPosition(const pandora::CartesianVector &position, float &rL, float &rT) const
Get local sliding fit coordinates for a given global position.
std::list< Vertex > VertexList
Definition: DCEL.h:178