LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
LayerSplittingAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
13 using namespace pandora;
14 
15 namespace lar_content
16 {
17 
18 LayerSplittingAlgorithm::LayerSplittingAlgorithm() :
19  m_minClusterLayers(20),
20  m_layerWindow(10),
21  m_maxScatterRms(0.35f),
22  m_maxScatterCosTheta(0.5f),
23  m_maxSlidingCosTheta(0.866f)
24 {
25 }
26 
27 //------------------------------------------------------------------------------------------------------------------------------------------
28 
29 StatusCode LayerSplittingAlgorithm::DivideCaloHits(const Cluster *const pCluster, CaloHitList &firstHitList, CaloHitList &secondHitList) const
30 {
31  unsigned int splitLayer(0);
32 
33  if (STATUS_CODE_SUCCESS == this->FindBestSplitLayer(pCluster, splitLayer))
34  return this->DivideCaloHits(pCluster, splitLayer, firstHitList, secondHitList);
35 
36  return STATUS_CODE_NOT_FOUND;
37 }
38 
39 //------------------------------------------------------------------------------------------------------------------------------------------
40 
41 StatusCode LayerSplittingAlgorithm::FindBestSplitLayer(const Cluster *const pCluster, unsigned int &splitLayer) const
42 {
43  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
44 
45  if (orderedCaloHitList.size() < m_minClusterLayers)
46  return STATUS_CODE_NOT_FOUND;
47 
48  bool foundSplit(false);
49 
50  float bestCosTheta(1.f);
51  CartesianVector bestPosition(0.f,0.f,0.f);
52 
53  for (unsigned int iLayer = pCluster->GetInnerPseudoLayer() + 4; iLayer + 4 <= pCluster->GetOuterPseudoLayer(); ++iLayer)
54  {
55  if (orderedCaloHitList.find(iLayer) == orderedCaloHitList.end())
56  continue;
57 
58  unsigned int innerLayer((pCluster->GetInnerPseudoLayer() + m_layerWindow > iLayer) ? pCluster->GetInnerPseudoLayer() : iLayer - m_layerWindow);
59  unsigned int outerLayer((iLayer + m_layerWindow > pCluster->GetOuterPseudoLayer()) ? pCluster->GetOuterPseudoLayer() : iLayer + m_layerWindow);
60 
61  for ( ; innerLayer >= pCluster->GetInnerPseudoLayer(); --innerLayer)
62  {
63  if (orderedCaloHitList.find(innerLayer) != orderedCaloHitList.end())
64  break;
65  }
66 
67  for ( ; outerLayer <= pCluster->GetOuterPseudoLayer(); ++outerLayer)
68  {
69  if (orderedCaloHitList.find(outerLayer) != orderedCaloHitList.end())
70  break;
71  }
72 
73  const CartesianVector splitPosition(pCluster->GetCentroid(iLayer));
74  const CartesianVector innerPosition(pCluster->GetCentroid(innerLayer));
75  const CartesianVector outerPosition(pCluster->GetCentroid(outerLayer));
76 
77  const CartesianVector r1(innerPosition - splitPosition);
78  const CartesianVector r2(outerPosition - splitPosition);
79  const CartesianVector p1(r1.GetUnitVector());
80  const CartesianVector p2(r2.GetUnitVector());
81 
82  const float cosTheta(-p1.GetDotProduct(p2));
83  const float rms1(this->CalculateRms(pCluster, innerLayer, iLayer));
84  const float rms2(this->CalculateRms(pCluster, outerLayer, iLayer));
85  const float rms(std::max(rms1, rms2));
86 
87  float rmsCut(std::numeric_limits<float>::max());
88 
89  if (cosTheta > 0.f)
90  {
91  rmsCut = m_maxScatterRms;
92 
93  if (cosTheta > m_maxScatterCosTheta)
94  {
95  rmsCut *= ((m_maxSlidingCosTheta > cosTheta) ? (m_maxSlidingCosTheta - cosTheta) /
97  }
98  }
99 
100  if (rms < rmsCut && cosTheta < bestCosTheta)
101  {
102  bestCosTheta = cosTheta;
103  bestPosition = splitPosition;
104 
105  splitLayer = iLayer;
106  foundSplit = true;
107  }
108  }
109 
110  if (!foundSplit)
111  return STATUS_CODE_NOT_FOUND;
112 
113  return STATUS_CODE_SUCCESS;
114 }
115 
116 //------------------------------------------------------------------------------------------------------------------------------------------
117 
118 float LayerSplittingAlgorithm::CalculateRms(const Cluster *const pCluster, const unsigned int &firstLayer, const unsigned int& secondLayer) const
119 {
120  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
121 
122  const unsigned int innerLayer(std::min(firstLayer, secondLayer));
123  const unsigned int outerLayer(std::max(firstLayer, secondLayer));
124 
125  const CartesianVector innerPosition(pCluster->GetCentroid(innerLayer));
126  const CartesianVector outerPosition(pCluster->GetCentroid(outerLayer));
127  const CartesianVector predictedDirection((outerPosition - innerPosition).GetUnitVector());
128 
129  float totalChi2(0.f);
130  float totalLayers(0.f);
131 
132  for (unsigned int iLayer = innerLayer + 1; iLayer + 1 < outerLayer; ++iLayer)
133  {
134  if (orderedCaloHitList.find(iLayer) == orderedCaloHitList.end())
135  continue;
136 
137  const CartesianVector hitPosition(pCluster->GetCentroid(iLayer));
138  const CartesianVector predictedPosition(innerPosition + predictedDirection * predictedDirection.GetDotProduct(hitPosition - innerPosition));
139 
140  totalChi2 += (predictedPosition - hitPosition).GetMagnitudeSquared();
141  totalLayers += 1.f;
142  }
143 
144  if (totalLayers > 0.f)
145  return std::sqrt(totalChi2/totalLayers);
146 
147  return 0.f;
148 }
149 
150 //------------------------------------------------------------------------------------------------------------------------------------------
151 
152 StatusCode LayerSplittingAlgorithm::DivideCaloHits(const Cluster *const pCluster, const unsigned int &splitLayer, CaloHitList &firstHitList, CaloHitList &secondHitList) const
153 {
154  const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
155 
156  for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(); iter != orderedCaloHitList.end(); ++iter)
157  {
158  const unsigned int thisLayer(iter->first);
159 
160  for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
161  {
162  const CaloHit *const pCaloHit = *hitIter;
163 
164  if (thisLayer < splitLayer)
165  {
166  firstHitList.push_back(pCaloHit);
167  }
168  else
169  {
170  secondHitList.push_back(pCaloHit);
171  }
172  }
173  }
174 
175  if (firstHitList.empty() || secondHitList.empty())
176  return STATUS_CODE_NOT_FOUND;
177 
178  return STATUS_CODE_SUCCESS;
179 }
180 
181 //------------------------------------------------------------------------------------------------------------------------------------------
182 
183 StatusCode LayerSplittingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
184 {
185  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
186  "MinClusterLayers", m_minClusterLayers));
187 
188  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
189  "LayerWindow", m_layerWindow));
190 
191  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
192  "MaxScatterRms", m_maxScatterRms));
193 
194  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
195  "MaxScatterCosTheta", m_maxScatterCosTheta));
196 
197  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
198  "MaxSlidingCosTheta", m_maxSlidingCosTheta));
199 
200  return ClusterSplittingAlgorithm::ReadSettings(xmlHandle);
201 }
202 
203 } // namespace lar_content
pandora::StatusCode FindBestSplitLayer(const pandora::Cluster *const pCluster, unsigned int &splitLayer) const
Find the best layer for splitting the cluster.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
TFile f
Definition: plotHisto.C:6
Int_t max
Definition: plot.C:27
intermediate_table::const_iterator const_iterator
Int_t min
Definition: plot.C:26
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
float CalculateRms(const pandora::Cluster *const pCluster, const unsigned int &firstLayer, const unsigned int &secondLayer) const
Calculate rms deviation of cluster centroids between two extremal layers.
pandora::StatusCode DivideCaloHits(const pandora::Cluster *const pCluster, pandora::CaloHitList &firstCaloHitList, pandora::CaloHitList &secondCaloHitList) const
Divide calo hits in a cluster into two lists, each associated with a separate fragment cluster...