9 #include "Pandora/AlgorithmHeaders.h"    21 TwoDSlidingFitSplittingAndSwitchingAlgorithm::TwoDSlidingFitSplittingAndSwitchingAlgorithm() :
    22     m_halfWindowLayers(25),
    23     m_minClusterLength(10.
f)
    31     const ClusterList *pClusterList = NULL;
    32     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*
this, pClusterList));
    43     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->
PreparationStep(clusterVector));
    46     for (
ClusterVector::iterator iter1 = clusterVector.begin(), iterEnd1 = clusterVector.end(); iter1 != iterEnd1; ++iter1)
    53         if (slidingFitResultMap.end() == sIter1)
    65             if (slidingFitResultMap.end() == sIter2)
    73             CartesianVector splitPosition(0.
f, 0.
f, 0.
f);
    74             CartesianVector firstDirection(0.
f, 0.
f, 0.
f);
    75             CartesianVector secondDirection(0.
f, 0.
f, 0.
f);
    77             if (STATUS_CODE_SUCCESS != this->
FindBestSplitPosition(slidingFitResult1, slidingFitResult2, splitPosition, firstDirection, secondDirection))
    80             const Cluster *
const pCluster1 = slidingFitResult1.
GetCluster();
    81             const Cluster *
const pCluster2 = slidingFitResult2.
GetCluster();
    83             if (STATUS_CODE_SUCCESS != this->
ReplaceClusters(pCluster1, pCluster2, splitPosition, firstDirection, secondDirection))
    86             slidingFitResultMap.erase(sIter1);
    87             slidingFitResultMap.erase(sIter2);
   103     return STATUS_CODE_SUCCESS;
   110     return STATUS_CODE_SUCCESS;
   119         const Cluster *
const pCluster = *iter;
   124         clusterVector.push_back(pCluster);
   139         if (slidingFitResultMap.end() == slidingFitResultMap.find(*iter))
   145                 if (!slidingFitResultMap.insert(TwoDSlidingFitResultMap::value_type(*iter, slidingFitResult)).second)
   146                     throw StatusCodeException(STATUS_CODE_FAILURE);
   148             catch (StatusCodeException &statusCodeException)
   150                 if (STATUS_CODE_FAILURE == statusCodeException.GetStatusCode())
   151                     throw statusCodeException;
   160     const CartesianVector &splitDirection, CaloHitList &firstCaloHitList, CaloHitList &secondCaloHitList)
 const   162     CaloHitList caloHitsToDistribute;
   163     pCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitsToDistribute);
   165     for (
CaloHitList::const_iterator iter = caloHitsToDistribute.begin(), iterEnd = caloHitsToDistribute.end(); iter != iterEnd; ++iter)
   167         const CaloHit *
const pCaloHit = *iter;
   169         if (splitDirection.GetDotProduct((pCaloHit->GetPositionVector() - splitPosition)) > 0.f)
   171             firstCaloHitList.push_back(pCaloHit);
   175             secondCaloHitList.push_back(pCaloHit);
   183     const CartesianVector &splitPosition, 
const CartesianVector &firstDirection, 
const CartesianVector &secondDirection)
 const   186     PandoraContentApi::Cluster::Parameters firstParameters, secondParameters;
   188     this->
SplitCluster(pCluster1, splitPosition, firstDirection, firstParameters.m_caloHitList, secondParameters.m_caloHitList);
   189     this->
SplitCluster(pCluster2, splitPosition, secondDirection, secondParameters.m_caloHitList, firstParameters.m_caloHitList);
   191     if (firstParameters.m_caloHitList.empty() || secondParameters.m_caloHitList.empty())
   192         return STATUS_CODE_NOT_ALLOWED;
   195     ClusterList clusterList;
   196     clusterList.push_back(pCluster1);
   197     clusterList.push_back(pCluster2);
   199     std::string clusterListToSaveName, clusterListToDeleteName;
   200     PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
   201         PandoraContentApi::InitializeFragmentation(*
this, clusterList, clusterListToDeleteName, clusterListToSaveName));
   204     const Cluster *pFirstCluster(NULL), *pSecondCluster(NULL);
   205     PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, firstParameters, pFirstCluster));
   206     PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Cluster::Create(*
this, secondParameters, pSecondCluster));
   209     PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::EndFragmentation(*
this, clusterListToSaveName, clusterListToDeleteName));
   211     return STATUS_CODE_SUCCESS;
   218     PANDORA_RETURN_RESULT_IF_AND_IF(
   219         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"HalfWindowLayers", 
m_halfWindowLayers));
   221     PANDORA_RETURN_RESULT_IF_AND_IF(
   222         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MinClusterLength", 
m_minClusterLength));
   224     return STATUS_CODE_SUCCESS;
 
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. 
 
unsigned int m_halfWindowLayers
half window layers for sliding linear fot 
 
static float GetWireZPitch(const pandora::Pandora &pandora, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch. 
 
virtual pandora::StatusCode FindBestSplitPosition(const TwoDSlidingFitResult &slidingFit1, const TwoDSlidingFitResult &slidingFit2, pandora::CartesianVector &splitPosition, pandora::CartesianVector &direction1, pandora::CartesianVector &direction2) const  =0
Find the best split position and direction for a pair of clusters. 
 
virtual pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
 
Header file for the geometry helper class. 
 
float m_minClusterLength
minimum length of clusters 
 
virtual pandora::StatusCode TidyUpStep()
Tidy up any information cached in e.g. the preparation step. 
 
pandora::StatusCode ReplaceClusters(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &firstDirection, const pandora::CartesianVector &secondDirection) const 
Replace crossed clusters with un-crossed clusters. 
 
Header file for the cluster helper class. 
 
void SplitCluster(const pandora::Cluster *const pCluster, const pandora::CartesianVector &splitPosition, const pandora::CartesianVector &splitDirection, pandora::CaloHitList &firstCaloHitList, pandora::CaloHitList &secondCaloHitList) const 
Split cluster at a given position and direction. 
 
std::unordered_map< const pandora::Cluster *, TwoDSlidingFitResult > TwoDSlidingFitResultMap
 
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...
 
const pandora::Cluster * GetCluster() const 
Get the address of the cluster, if originally provided. 
 
static float GetLengthSquared(const pandora::Cluster *const pCluster)
Get length squared of cluster. 
 
std::vector< art::Ptr< recob::Cluster > > ClusterVector
 
virtual pandora::StatusCode Run()
 
virtual pandora::StatusCode PreparationStep(const pandora::ClusterVector &clusterVector)
Perform any preparatory actions, such as caching information for subsequent expensive calculations...
 
void BuildSlidingFitResultMap(const pandora::ClusterVector &clusterVector, TwoDSlidingFitResultMap &slidingFitResultMap) const 
Build the map of sliding fit results. 
 
Header file for the two dimensional sliding fit splitting and switching algorithm class...
 
TwoDSlidingFitResult class.