9 #include "Pandora/AlgorithmHeaders.h"
18 LayerSplittingAlgorithm::LayerSplittingAlgorithm() :
19 m_minClusterLayers(20),
21 m_maxScatterRms(0.35f),
22 m_maxScatterCosTheta(0.5f),
23 m_maxSlidingCosTheta(0.866f)
31 unsigned int splitLayer(0);
34 return this->
DivideCaloHits(pCluster, splitLayer, firstHitList, secondHitList);
36 return STATUS_CODE_NOT_FOUND;
43 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
46 return STATUS_CODE_NOT_FOUND;
48 bool foundSplit(
false);
50 float bestCosTheta(1.f);
51 CartesianVector bestPosition(0.f, 0.f, 0.f);
53 for (
unsigned int iLayer = pCluster->GetInnerPseudoLayer() + 4; iLayer + 4 <= pCluster->GetOuterPseudoLayer(); ++iLayer)
55 if (orderedCaloHitList.find(iLayer) == orderedCaloHitList.end())
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);
61 for (; innerLayer >= pCluster->GetInnerPseudoLayer(); --innerLayer)
63 if (orderedCaloHitList.find(innerLayer) != orderedCaloHitList.end())
67 for (; outerLayer <= pCluster->GetOuterPseudoLayer(); ++outerLayer)
69 if (orderedCaloHitList.find(outerLayer) != orderedCaloHitList.end())
73 const CartesianVector splitPosition(pCluster->GetCentroid(iLayer));
74 const CartesianVector innerPosition(pCluster->GetCentroid(innerLayer));
75 const CartesianVector outerPosition(pCluster->GetCentroid(outerLayer));
77 const CartesianVector r1(innerPosition - splitPosition);
78 const CartesianVector r2(outerPosition - splitPosition);
79 const CartesianVector
p1(r1.GetUnitVector());
80 const CartesianVector p2(r2.GetUnitVector());
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));
87 float rmsCut(std::numeric_limits<float>::max());
99 if (rms < rmsCut && cosTheta < bestCosTheta)
101 bestCosTheta = cosTheta;
102 bestPosition = splitPosition;
110 return STATUS_CODE_NOT_FOUND;
112 return STATUS_CODE_SUCCESS;
119 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
121 const unsigned int innerLayer(std::min(firstLayer, secondLayer));
122 const unsigned int outerLayer(std::max(firstLayer, secondLayer));
124 const CartesianVector innerPosition(pCluster->GetCentroid(innerLayer));
125 const CartesianVector outerPosition(pCluster->GetCentroid(outerLayer));
126 const CartesianVector predictedDirection((outerPosition - innerPosition).GetUnitVector());
128 float totalChi2(0.f);
129 float totalLayers(0.f);
131 for (
unsigned int iLayer = innerLayer + 1; iLayer + 1 < outerLayer; ++iLayer)
133 if (orderedCaloHitList.find(iLayer) == orderedCaloHitList.end())
136 const CartesianVector hitPosition(pCluster->GetCentroid(iLayer));
137 const CartesianVector predictedPosition(innerPosition + predictedDirection * predictedDirection.GetDotProduct(hitPosition - innerPosition));
139 totalChi2 += (predictedPosition - hitPosition).GetMagnitudeSquared();
143 if (totalLayers > 0.f)
144 return std::sqrt(totalChi2 / totalLayers);
152 const Cluster *
const pCluster,
const unsigned int &splitLayer, CaloHitList &firstHitList, CaloHitList &secondHitList)
const
154 const OrderedCaloHitList &orderedCaloHitList(pCluster->GetOrderedCaloHitList());
156 for (OrderedCaloHitList::const_iterator iter = orderedCaloHitList.begin(); iter != orderedCaloHitList.end(); ++iter)
158 const unsigned int thisLayer(iter->first);
160 for (CaloHitList::const_iterator hitIter = iter->second->begin(), hitIterEnd = iter->second->end(); hitIter != hitIterEnd; ++hitIter)
162 const CaloHit *
const pCaloHit = *hitIter;
164 if (thisLayer < splitLayer)
166 firstHitList.push_back(pCaloHit);
170 secondHitList.push_back(pCaloHit);
175 if (firstHitList.empty() || secondHitList.empty())
176 return STATUS_CODE_NOT_FOUND;
178 return STATUS_CODE_SUCCESS;
185 PANDORA_RETURN_RESULT_IF_AND_IF(
186 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinClusterLayers",
m_minClusterLayers));
188 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"LayerWindow",
m_layerWindow));
190 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxScatterRms",
m_maxScatterRms));
192 PANDORA_RETURN_RESULT_IF_AND_IF(
193 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxScatterCosTheta",
m_maxScatterCosTheta));
195 PANDORA_RETURN_RESULT_IF_AND_IF(
196 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxSlidingCosTheta",
m_maxSlidingCosTheta));
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)
unsigned int m_minClusterLayers
float m_maxScatterCosTheta
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
unsigned int m_layerWindow
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.
physics associatedGroupsWithLeft p1
float m_maxSlidingCosTheta
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...