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));
88 float xMin1(0.
f), xMax1(0.
f), xMin2(0.
f), xMax2(0.
f);
89 pCluster1->GetClusterSpanX(xMin1, xMax1);
90 pCluster2->GetClusterSpanX(xMin2, xMax2);
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;
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;
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);
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)
377 auto matchedClustersIter(std::find(matchedClusters.begin(), matchedClusters.end(), pModifiedCluster));
379 if (matchedClustersIter == matchedClusters.end())
388 matchedClusters.erase(matchedClustersIter);
391 const Cluster *
const pBestMatchedCluster =
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.
static int max(int a, int b)
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 ...
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
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...
const pandora::ClusterList & GetMatchedClusterList() const
Get the matched cluster list.
const pandora::PfoList & GetCommonMuonPfoList() const
Get the common muon pfo list.
const TwoViewXOverlap & GetXOverlap() const
Get the x overlap object.