9 #include "Pandora/AlgorithmHeaders.h" 
   24 TwoViewDeltaRayMatchingAlgorithm::TwoViewDeltaRayMatchingAlgorithm() :
 
   25     m_nMaxMatrixToolRepeats(10),
 
   26     m_minClusterCaloHits(3),
 
   27     m_maxDistanceFromPrediction(2.f),
 
   28     m_maxGoodMatchReducedChiSquared(1.f),
 
   29     m_minDistanceFromMuon(1.f),
 
   30     m_maxDistanceToCollected(1.f)
 
   40     for (
const HitType hitType : {TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W})
 
   44         if ((hitTypeIndex != 1) && (hitTypeIndex != 2))
 
   47         hitTypeVector.push_back(hitType);
 
   59     if ((hitTypeIndex != 1) && (hitTypeIndex != 2))
 
   60         return element.GetOverlapResult().GetBestMatchedAvailableCluster();
 
   62     return hitTypeIndex == 1 ? element.GetCluster1() : element.GetCluster2();
 
   77     PANDORA_THROW_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, this->
CalculateOverlapResult(pCluster1, pCluster2, overlapResult));
 
   86     const Cluster *
const pCluster1, 
const Cluster *
const pCluster2, TwoViewDeltaRayOverlapResult &overlapResult)
 const 
   88     float xMin1(0.f), xMax1(0.f), xMin2(0.f), xMax2(0.f);
 
   89     pCluster1->GetClusterSpanX(xMin1, xMax1);
 
   90     pCluster2->GetClusterSpanX(xMin2, xMax2);
 
   92     const float xOverlap(std::min(xMax1, xMax2) - std::max(xMin1, xMin2));
 
   94     if (xOverlap < std::numeric_limits<float>::epsilon())
 
   95         return STATUS_CODE_NOT_FOUND;
 
   97     PfoList commonMuonPfoList;
 
  100     if (commonMuonPfoList.empty())
 
  101         return STATUS_CODE_NOT_FOUND;
 
  103     CartesianPointVector projectedPositions;
 
  106     if (status != STATUS_CODE_SUCCESS)
 
  110     ClusterList matchedClusterList;
 
  113     if (matchedClusterList.empty())
 
  114         return STATUS_CODE_NOT_FOUND;
 
  116     float reducedChiSquared(std::numeric_limits<float>::max());
 
  117     const Cluster *
const pBestMatchedCluster =
 
  118         this->
GetBestMatchedCluster(pCluster1, pCluster2, commonMuonPfoList, matchedClusterList, reducedChiSquared);
 
  121     if (pBestMatchedCluster && (pBestMatchedCluster->IsAvailable()))
 
  123         const unsigned int hitSum12(pCluster1->GetNCaloHits() + pCluster2->GetNCaloHits());
 
  124         const unsigned int hitSum13(pCluster1->GetNCaloHits() + pBestMatchedCluster->GetNCaloHits());
 
  126         if (hitSum13 > hitSum12)
 
  127             return STATUS_CODE_NOT_FOUND;
 
  129         const unsigned int hitSum23(pCluster2->GetNCaloHits() + pBestMatchedCluster->GetNCaloHits());
 
  131         if (hitSum23 > hitSum12)
 
  132             return STATUS_CODE_NOT_FOUND;
 
  135     TwoViewXOverlap xOverlapObject(xMin1, xMax1, xMin2, xMax2);
 
  136     overlapResult = TwoViewDeltaRayOverlapResult(xOverlapObject, commonMuonPfoList, pBestMatchedCluster, matchedClusterList, reducedChiSquared);
 
  138     return STATUS_CODE_SUCCESS;
 
  145     ClusterList consideredClusters1, consideredClusters2;
 
  146     PfoList nearbyMuonPfos1, nearbyMuonPfos2;
 
  150     if (nearbyMuonPfos1.empty())
 
  155     if (nearbyMuonPfos2.empty())
 
  158     for (
const ParticleFlowObject *
const pNearbyMuon1 : nearbyMuonPfos1)
 
  160         for (
const ParticleFlowObject *
const pNearbyMuon2 : nearbyMuonPfos2)
 
  162             if (pNearbyMuon1 == pNearbyMuon2)
 
  163                 commonMuonPfoList.push_back(pNearbyMuon1);
 
  171     const CartesianPointVector &projectedPositions, ClusterList &matchedClusters)
 const 
  173     const ClusterList *pInputClusterList(
nullptr);
 
  174     PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this, 
m_inputClusterListName, pInputClusterList));
 
  176     if (!pInputClusterList || pInputClusterList->empty())
 
  179     for (
const Cluster *
const pCluster : *pInputClusterList)
 
  186         float reducedChiSquared(0.f);
 
  193         matchedClusters.push_back(pCluster);
 
  200     const PfoList &commonMuonPfoList, 
const ClusterList &matchedClusters, 
float &reducedChiSquared)
 const 
  202     const Cluster *pBestMatchedCluster(
nullptr);
 
  204     if (matchedClusters.empty())
 
  205         return pBestMatchedCluster;
 
  208     ClusterList muonClusterList;
 
  210     for (
const ParticleFlowObject *
const pMuonPfo : commonMuonPfoList)
 
  213     unsigned int highestNHits(0);
 
  215     for (
const Cluster *
const pMatchedCluster : matchedClusters)
 
  217         if (!pMatchedCluster->IsAvailable())
 
  219             if (std::find(muonClusterList.begin(), muonClusterList.end(), pMatchedCluster) == muonClusterList.end())
 
  223         if (pMatchedCluster->GetNCaloHits() > highestNHits)
 
  225             highestNHits = pMatchedCluster->GetNCaloHits();
 
  226             pBestMatchedCluster = pMatchedCluster;
 
  230     if (!pBestMatchedCluster)
 
  231         return pBestMatchedCluster;
 
  233     if (this->
PerformThreeViewMatching(pCluster1, pCluster2, pBestMatchedCluster, reducedChiSquared) == STATUS_CODE_NOT_FOUND)
 
  234         throw StatusCodeException(STATUS_CODE_FAILURE);
 
  236     return pBestMatchedCluster;
 
  245     protoParticle.
m_clusterList.push_back(protoParticleElement.GetCluster1());
 
  246     protoParticle.
m_clusterList.push_back(protoParticleElement.GetCluster2());
 
  248     const Cluster *
const pBestMatchedCluster(protoParticleElement.GetOverlapResult().GetBestMatchedCluster());
 
  250     if (pBestMatchedCluster)
 
  255     return (this->
CreatePfos(protoParticleVector));
 
  262     const PfoList &commonMuonPfoList(element.GetOverlapResult().GetCommonMuonPfoList());
 
  263     const Cluster *
const pBestMatchedCluster(element.GetOverlapResult().GetBestMatchedCluster());
 
  265     const ParticleFlowObject *pMatchedMuonPfo(
nullptr);
 
  267     for (
const ParticleFlowObject *
const pMuonPfo : commonMuonPfoList)
 
  269         ClusterList muonClusterList;
 
  272         if (std::find(muonClusterList.begin(), muonClusterList.end(), pBestMatchedCluster) != muonClusterList.end())
 
  273             pMatchedMuonPfo = pMuonPfo;
 
  276     const Cluster *pThirdViewCluster(pMatchedMuonPfo ? 
nullptr : pBestMatchedCluster);
 
  280         CaloHitList deltaRayHitList;
 
  290             pThirdViewCluster = element.GetOverlapResult().GetBestMatchedAvailableCluster();
 
  294     if (!pThirdViewCluster)
 
  307     CaloHitList caloHitList1, caloHitList2;
 
  308     element.GetCluster1()->GetOrderedCaloHitList().FillCaloHitList(caloHitList1);
 
  309     element.GetCluster2()->GetOrderedCaloHitList().FillCaloHitList(caloHitList2);
 
  312     ClusterList matchedClusters(element.GetOverlapResult().GetMatchedClusterList());
 
  314     ClusterSet checkedClusters;
 
  316     if (std::find(matchedClusters.begin(), matchedClusters.end(), pSeedCluster) != matchedClusters.end())
 
  317         checkedClusters.insert(pSeedCluster);
 
  319     while (checkedClusters.size() != matchedClusters.size())
 
  321         const Cluster *pClusterToDelete(
nullptr);
 
  322         unsigned int highestHit(0);
 
  324         for (
const Cluster *
const pMatchedCluster : matchedClusters)
 
  326             if (checkedClusters.count(pMatchedCluster))
 
  329             if (pMatchedCluster->GetNCaloHits() > highestHit)
 
  331                 pClusterToDelete = pMatchedCluster;
 
  332                 highestHit = pMatchedCluster->GetNCaloHits();
 
  336         if (!pClusterToDelete)
 
  339         checkedClusters.insert(pClusterToDelete);
 
  341         if (!pClusterToDelete->IsAvailable())
 
  344         CaloHitList caloHitList3;
 
  345         pSeedCluster->GetOrderedCaloHitList().FillCaloHitList(caloHitList3);
 
  346         pClusterToDelete->GetOrderedCaloHitList().FillCaloHitList(caloHitList3);
 
  348         float reducedChiSquared(std::numeric_limits<float>::max());
 
  349         const StatusCode status(this->
PerformThreeViewMatching(caloHitList1, caloHitList2, caloHitList3, reducedChiSquared));
 
  351         if (status == STATUS_CODE_NOT_FOUND)
 
  359         PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Cluster>(*
this, this->
GetThirdViewClusterListName()));
 
  361         PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::MergeAndDeleteClusters(*
this, pSeedCluster, pClusterToDelete));
 
  371     for (
auto [pCluster1, overlapList] : theMatrix)
 
  373         for (
auto [pCluster2, overlapResult] : overlapList)
 
  375             ClusterList matchedClusters(overlapResult.GetMatchedClusterList());
 
  377             auto matchedClustersIter(std::find(matchedClusters.begin(), matchedClusters.end(), pModifiedCluster));
 
  379             if (matchedClustersIter == matchedClusters.end())
 
  382             float tempReducedChiSquared(std::numeric_limits<float>::max());
 
  388                 matchedClusters.erase(matchedClustersIter);
 
  390             float reducedChiSquared(std::numeric_limits<float>::max());
 
  391             const Cluster *
const pBestMatchedCluster =
 
  392                 this->
GetBestMatchedCluster(pCluster1, pCluster2, overlapResult.GetCommonMuonPfoList(), matchedClusters, reducedChiSquared);
 
  395                 overlapResult.GetXOverlap(), overlapResult.GetCommonMuonPfoList(), pBestMatchedCluster, matchedClusters, reducedChiSquared);
 
  396             theMatrix.ReplaceOverlapResult(pCluster1, pCluster2, newOverlapResult);
 
  406     unsigned int repeatCounter(0);
 
  411         const bool repeatTools(pTool->
Run(
this, 
this->GetMatchingControl().GetOverlapMatrix()));
 
  414         repeatCounter = repeatTools ? repeatCounter + 1 : repeatCounter;
 
  425     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, 
"InputClusterListName", 
m_inputClusterListName));
 
  427     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithm(*
this, xmlHandle, 
"ClusterRebuilding", 
m_reclusteringAlgorithmName));
 
  429     AlgorithmToolVector algorithmToolVector;
 
  430     PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ProcessAlgorithmToolList(*
this, xmlHandle, 
"DeltaRayTools", algorithmToolVector));
 
  432     for (
auto algorithmTool : algorithmToolVector)
 
  434         DeltaRayMatrixTool *
const pDeltaRayMatrixTool(dynamic_cast<DeltaRayMatrixTool *>(algorithmTool));
 
  436         if (!pDeltaRayMatrixTool)
 
  437             return STATUS_CODE_INVALID_PARAMETER;
 
  442     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  443         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"NMaxMatrixToolRepeats", 
m_nMaxMatrixToolRepeats));
 
  445     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  446         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MinClusterCaloHits", 
m_minClusterCaloHits));
 
  448     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  451     PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
 
  454     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  455         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MinDistanceFromMuon", 
m_minDistanceFromMuon));
 
  457     PANDORA_RETURN_RESULT_IF_AND_IF(
 
  458         STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, 
"MaxDistanceToCollected", 
m_maxDistanceToCollected));
 
std::vector< pandora::HitType > HitTypeVector
std::vector< ProtoParticle > ProtoParticleVector
static float GetClosestDistance(const pandora::Cluster *const pCluster, const pandora::CartesianPointVector &cartesianPointVector)
Get closest distance between a specified cluster and list of positions. 
bool IsInitialized() const 
Whether the track overlap result has been initialized. 
unsigned int m_minClusterCaloHits
The threshold number of hits for a cluster to be considered. 
std::string m_inputClusterListName
The name of the cluster list in the view in which to project into. 
Header file for the pfo helper class. 
void FormThirdViewCluster(const MatrixType::Element &element, ProtoParticle &protoParticle)
Form the third view cluster by removing hits from cosmic ray clusters and merging the matched cluster...
pandora::StatusCode GetProjectedPositions(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::CartesianPointVector &projectedPositions) const
Use two clusters from different views to calculate projected positions in the remaining third view...
unsigned int m_nMaxMatrixToolRepeats
The maximum number of repeat loops over matrix tools. 
static void GetClusters(const pandora::PfoList &pfoList, const pandora::HitType &hitType, pandora::ClusterList &clusterList)
Get a list of clusters of a particular hit type from a list of pfos. 
DeltaRayTensorTool class. 
pandora::StatusCode CollectHitsFromMuon(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pThirdViewCluster, const pandora::ParticleFlowObject *const pParentMuon, const float minDistanceFromMuon, const float maxDistanceToCollected, pandora::CaloHitList &collectedHits) const
In one view, pull out any hits from a cosmic ray cluster that belong to the child delta ray cluster...
const std::string & GetThirdViewClusterListName() const 
Get the name of the third view clusters. 
float m_maxGoodMatchReducedChiSquared
The maximum reduced chi squared value of a good 1:1:1 match. 
MatrixToolVector m_algorithmToolVector
The algorithm tool vector. 
void ExamineOverlapContainer()
Examine contents of overlap container, collect together best-matching 2D particles and modify cluster...
float m_maxDistanceFromPrediction
The maximum distance of a matched cluster from the third view projection points. 
void CalculateOverlapResult(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3)
Calculate cluster overlap result and store in container. 
float m_maxDistanceToCollected
The maximim distance of a hit from the projected delta ray hits required for removal. 
MatrixType & GetOverlapMatrix()
Get the overlap matrix. 
virtual bool DoesClusterPassTensorThreshold(const pandora::Cluster *const pCluster) const 
To check whether a given cluster meets the requirements to be added into the matching container (tens...
virtual bool Run(TwoViewDeltaRayMatchingAlgorithm *const pAlgorithm, MatrixType &matrixTensor)=0
Run the algorithm tool. 
const pandora::Cluster * GetCluster(const MatrixType::Element &element, const pandora::HitType hitType)
Get the address of the given hit type cluster. 
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster. 
const pandora::Cluster * GetBestMatchedCluster(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::PfoList &commonMuonPfoList, const pandora::ClusterList &matchedClusters, float &reducedChiSquared) const 
Determine the best matched third view cluster and calculate the reduced chi-squared value of the thre...
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
MatchingType & GetMatchingControl()
Get the matching control. 
void FindCommonMuonParents(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, pandora::PfoList &commonMuonPfoList) const 
Find the cosmic ray pfos that, in each view, lie close to the clusters of the matrix element...
HitTypeVector GetHitTypeVector()
Obtain the HitTypeVector of input views. 
pandora::StatusCode PerformThreeViewMatching(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3, float &reducedChiSquared) const
To determine how well three clusters (one in each view) map onto one another expressing this in terms...
TwoViewDeltaRayOverlapResult class. 
void CollectThirdViewClusters(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::CartesianPointVector &projectedPositions, pandora::ClusterList &matchedClusters) const 
Collect the available and unavailable third view clusters that lie close to the projected delta ray h...
float m_minDistanceFromMuon
The minimum distance of a hit from the cosmic ray track required for removal. 
Header file for the cluster helper class. 
Header file for the muon leading helper class. 
std::string m_reclusteringAlgorithmName
The name of the clustering algorithm to be used to recluster created delta ray remnants. 
void MergeThirdView(const MatrixType::Element &element, const pandora::Cluster *const pSeedCluster)
Starting with an input seed cluster, sequentially merge in matched clusters that retain a good reduce...
Header file for the lar two dimensional sliding fit result class. 
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
pandora::ClusterList m_clusterList
List of 2D clusters in a 3D proto particle. 
void SplitMuonCluster(const std::string &clusterListName, const pandora::Cluster *const pMuonCluster, const pandora::CaloHitList &collectedHits, const pandora::Cluster *&pDeltaRayCluster) const
Move a list of hits from a cosmic ray cluster into the given child delta ray cluster. 
void GetNearbyMuonPfos(const pandora::Cluster *const pCluster, pandora::ClusterList &consideredClusters, pandora::PfoList &nearbyMuonPfos) const
Use the cluster proximity map to travel along paths of nearby clusters finding the cosmic ray cluster...
void SetOverlapResult(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const OverlapResult &overlapResult)
Set overlap result. 
bool CreatePfo(const MatrixType::Element &element)
Create delta ray pfos out of a given element, merging the third view clusters together and adding in ...
required by fuzzyCluster table::sbnd_g4_services gaushitTruthMatch pandora
void UpdateForThirdViewClusterModification(const pandora::Cluster *const pModifiedCluster, const bool isMuon)
Update the matrix after a third view cluster modification - remove delta ray clusters and reassess th...
bool CreatePfos(ProtoParticleVector &protoParticleVector)
Create delta ray pfos maxmising completeness by searching for and merging in any stray clusters...