Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
DeltaRayMergeTool.cc
Go to the documentation of this file.
1
10
14
16
17using namespace pandora;
18
19namespace lar_content
20{
21
23 m_maxDRSeparationFromTrack(1.5f),
24 m_maxClusterSeparation(3.f),
25 m_maxVertexSeparation(10.f),
26 m_maxGoodMatchReducedChiSquared(1.f)
27{
28}
29
30//------------------------------------------------------------------------------------------------------------------------------------------
31
33{
34 m_pParentAlgorithm = pAlgorithm;
35
37 std::cout << "----> Running Algorithm Tool: " << this->GetInstanceName() << ", " << this->GetType() << std::endl;
38
39 return this->ExamineConnectedElements(overlapTensor);
40}
41
42//------------------------------------------------------------------------------------------------------------------------------------------
43
45{
46 bool mergeMade(false), mergesMade(false), finishedTwoViewMerges(false);
47
48 do
49 {
50 mergeMade = false;
51
52 ClusterVector sortedKeyClusters;
53 overlapTensor.GetSortedKeyClusters(sortedKeyClusters);
54
55 ClusterSet usedKeyClusters;
56 for (const Cluster *const pKeyCluster : sortedKeyClusters)
57 {
58 if (usedKeyClusters.count(pKeyCluster))
59 continue;
60
61 TensorType::ElementList elementList;
62 overlapTensor.GetConnectedElements(pKeyCluster, true, elementList);
63
64 for (const TensorType::Element &element : elementList)
65 usedKeyClusters.insert(element.GetClusterU());
66
67 if (elementList.size() < 2)
68 continue;
69
70 if (!finishedTwoViewMerges && this->MakeTwoCommonViewMerges(elementList))
71 {
72 mergeMade = true;
73 mergesMade = true;
74 break;
75 }
76
77 finishedTwoViewMerges = true;
78
79 if (this->MakeOneCommonViewMerges(elementList))
80 {
81 mergeMade = true;
82 mergesMade = true;
83 break;
84 }
85 }
86 } while (mergeMade);
87
88 return mergesMade;
89}
90
91//------------------------------------------------------------------------------------------------------------------------------------------
92
93bool DeltaRayMergeTool::MakeTwoCommonViewMerges(const TensorType::ElementList &elementList) const
94{
95 for (auto iter1 = elementList.begin(); iter1 != elementList.end(); ++iter1)
96 {
97 const TensorType::Element &element1(*iter1);
98
99 for (auto iter2 = std::next(iter1); iter2 != elementList.end(); ++iter2)
100 {
101 const TensorType::Element &element2(*iter2);
102
103 for (const HitType hitType1 : {TPC_VIEW_U, TPC_VIEW_V})
104 {
105 if ((element1.GetCluster(hitType1) == element2.GetCluster(hitType1)))
106 {
107 for (const HitType hitType2 : {TPC_VIEW_V, TPC_VIEW_W})
108 {
109 if (hitType1 == hitType2)
110 continue;
111
112 if ((element1.GetCluster(hitType2) == element2.GetCluster(hitType2)))
113 {
114 const HitType mergeHitType(hitType1 == TPC_VIEW_U ? (hitType2 == TPC_VIEW_V ? TPC_VIEW_W : TPC_VIEW_V) : TPC_VIEW_U);
115 const Cluster *pClusterToEnlarge(element1.GetCluster(mergeHitType)), *pClusterToDelete(element2.GetCluster(mergeHitType));
116
117 if (this->AreAssociated(element1, element2, mergeHitType))
118 {
119 m_pParentAlgorithm->UpdateUponDeletion(pClusterToEnlarge);
120 m_pParentAlgorithm->UpdateUponDeletion(pClusterToDelete);
121
122 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
125
126 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
127 PandoraContentApi::MergeAndDeleteClusters(*m_pParentAlgorithm, pClusterToEnlarge, pClusterToDelete));
128
129 m_pParentAlgorithm->UpdateForNewClusters({pClusterToEnlarge}, {nullptr});
130
131 return true;
132 }
133 }
134 }
135 }
136 }
137 }
138 }
139
140 return false;
141}
142
143//------------------------------------------------------------------------------------------------------------------------------------------
144
145bool DeltaRayMergeTool::AreAssociated(const TensorType::Element &element1, const TensorType::Element &element2, const HitType &mergeHitType) const
146{
147 const PfoList &commonMuonPfoList1(element1.GetOverlapResult().GetCommonMuonPfoList());
148 const PfoList &commonMuonPfoList2(element2.GetOverlapResult().GetCommonMuonPfoList());
149
150 // Demand the elements to have a shared common muon
151 PfoList commonMuonPfoList;
152 this->CombineCommonMuonPfoLists(commonMuonPfoList1, commonMuonPfoList2, commonMuonPfoList);
153
154 if (commonMuonPfoList.empty())
155 return false;
156
157 const Cluster *const pCluster1(element1.GetCluster(mergeHitType)), *const pCluster2(element2.GetCluster(mergeHitType));
158
159 PfoList connectedMuonPfoList1, connectedMuonPfoList2;
160 this->GetConnectedMuons(pCluster1, commonMuonPfoList1, connectedMuonPfoList1);
161 this->GetConnectedMuons(pCluster2, commonMuonPfoList2, connectedMuonPfoList2);
162
163 if (connectedMuonPfoList1.empty() || connectedMuonPfoList2.empty())
164 return (this->IsBrokenCluster(pCluster1, pCluster2));
165
166 for (const ParticleFlowObject *const pConnectedMuon1 : connectedMuonPfoList1)
167 {
168 for (const ParticleFlowObject *const pConnectedMuon2 : connectedMuonPfoList2)
169 {
170 if ((pConnectedMuon1 == pConnectedMuon2) && (this->IsHiddenByTrack(pConnectedMuon1, pCluster1, pCluster2)))
171 return true;
172 }
173 }
174
175 return false;
176}
177
178//------------------------------------------------------------------------------------------------------------------------------------------
179
180void DeltaRayMergeTool::CombineCommonMuonPfoLists(const PfoList &commonMuonPfoList1, const PfoList &commonMuonPfoList2, PfoList &commonMuonPfoList) const
181{
182 for (const ParticleFlowObject *const pCommonMuonPfo1 : commonMuonPfoList1)
183 {
184 for (const ParticleFlowObject *const pCommonMuonPfo2 : commonMuonPfoList2)
185 {
186 if (pCommonMuonPfo1 == pCommonMuonPfo2)
187 commonMuonPfoList.push_back(pCommonMuonPfo1);
188 }
189 }
190}
191
192//------------------------------------------------------------------------------------------------------------------------------------------
193
194void DeltaRayMergeTool::GetConnectedMuons(const Cluster *const pDeltaRayCluster, const PfoList &commonMuonPfoList, PfoList &connectedMuonPfoList) const
195{
196 for (const ParticleFlowObject *const pCommonMuonPfo : commonMuonPfoList)
197 {
198 if (this->IsConnected(pDeltaRayCluster, pCommonMuonPfo))
199 connectedMuonPfoList.push_back(pCommonMuonPfo);
200 }
201}
202
203//------------------------------------------------------------------------------------------------------------------------------------------
204
205bool DeltaRayMergeTool::IsConnected(const Cluster *const pCluster, const Pfo *const pCommonMuonPfo) const
206{
208
209 ClusterList muonClusterList;
210 LArPfoHelper::GetClusters(pCommonMuonPfo, hitType, muonClusterList);
211
212 if (muonClusterList.size() != 1)
213 return false;
214
215 const float separation(LArClusterHelper::GetClosestDistance(pCluster, muonClusterList));
216
217 return separation < m_maxDRSeparationFromTrack;
218}
219
220//------------------------------------------------------------------------------------------------------------------------------------------
221
222bool DeltaRayMergeTool::IsBrokenCluster(const Cluster *const pClusterToEnlarge, const Cluster *const pClusterToDelete) const
223{
224 const float clusterSeparation(LArClusterHelper::GetClosestDistance(pClusterToEnlarge, pClusterToDelete));
225
226 return clusterSeparation < m_maxClusterSeparation;
227}
228
229//------------------------------------------------------------------------------------------------------------------------------------------
230
231bool DeltaRayMergeTool::IsHiddenByTrack(const ParticleFlowObject *const pMuonPfo, const Cluster *const pCluster1, const Cluster *const pCluster2) const
232{
233 CaloHitList vertices1, vertices2;
234 this->FindVertices(pMuonPfo, pCluster1, vertices1);
235 this->FindVertices(pMuonPfo, pCluster2, vertices2);
236
237 if (vertices1.empty() || vertices2.empty())
238 return false;
239
240 for (const CaloHit *const pCaloHit : vertices1)
241 {
242 const float separation(LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), vertices2));
243
244 if (separation < m_maxVertexSeparation)
245 return true;
246 }
247
248 return false;
249}
250
251//------------------------------------------------------------------------------------------------------------------------------------------
252
253void DeltaRayMergeTool::FindVertices(const Pfo *const pCommonMuonPfo, const Cluster *const pCluster, CaloHitList &vertexList) const
254{
256
257 ClusterList muonClusterList;
258 LArPfoHelper::GetClusters(pCommonMuonPfo, hitType, muonClusterList);
259
260 if (muonClusterList.size() != 1)
261 return;
262
263 CaloHitList caloHitList;
264 muonClusterList.front()->GetOrderedCaloHitList().FillCaloHitList(caloHitList);
265
266 for (const CaloHit *const pCaloHit : caloHitList)
267 {
268 if (LArClusterHelper::GetClosestDistance(pCaloHit->GetPositionVector(), pCluster) < m_maxDRSeparationFromTrack)
269 vertexList.push_back(pCaloHit);
270 }
271}
272
273//------------------------------------------------------------------------------------------------------------------------------------------
274
275bool DeltaRayMergeTool::MakeOneCommonViewMerges(const TensorType::ElementList &elementList) const
276{
277 for (auto iter1 = elementList.begin(); iter1 != elementList.end(); ++iter1)
278 {
279 const TensorType::Element &element1(*iter1);
280
281 for (auto iter2 = std::next(iter1); iter2 != elementList.end(); ++iter2)
282 {
283 const TensorType::Element &element2(*iter2);
284
285 for (const HitType hitType : {TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W})
286 {
287 if (element1.GetCluster(hitType) == element2.GetCluster(hitType))
288 {
289 const HitType mergeHitType1(hitType == TPC_VIEW_U ? TPC_VIEW_V : hitType == TPC_VIEW_V ? TPC_VIEW_W : TPC_VIEW_U);
290 const HitType mergeHitType2(mergeHitType1 == TPC_VIEW_U ? TPC_VIEW_V : mergeHitType1 == TPC_VIEW_V ? TPC_VIEW_W : TPC_VIEW_U);
291
292 const Cluster *pClusterToEnlarge1 = element1.GetCluster(mergeHitType1), *pClusterToDelete1 = element2.GetCluster(mergeHitType1);
293 const Cluster *pClusterToEnlarge2 = element1.GetCluster(mergeHitType2), *pClusterToDelete2 = element2.GetCluster(mergeHitType2);
294
295 if ((pClusterToEnlarge1 == pClusterToDelete1) || (pClusterToEnlarge2 == pClusterToDelete2))
296 continue;
297
298 if (!this->AreAssociated(element1, element2, mergeHitType1))
299 continue;
300
301 if (!this->AreAssociated(element1, element2, mergeHitType2))
302 continue;
303
304 CaloHitList caloHitList1, caloHitList2, caloHitList3;
305 pClusterToEnlarge1->GetOrderedCaloHitList().FillCaloHitList(caloHitList1);
306 pClusterToDelete1->GetOrderedCaloHitList().FillCaloHitList(caloHitList1);
307 pClusterToEnlarge2->GetOrderedCaloHitList().FillCaloHitList(caloHitList2);
308 pClusterToDelete2->GetOrderedCaloHitList().FillCaloHitList(caloHitList2);
309 element1.GetCluster(hitType)->GetOrderedCaloHitList().FillCaloHitList(caloHitList3);
310
311 float reducedChiSquared(std::numeric_limits<float>::max());
312 StatusCode status(m_pParentAlgorithm->PerformThreeViewMatching(caloHitList1, caloHitList2, caloHitList3, reducedChiSquared));
313
314 if (status == STATUS_CODE_NOT_FOUND)
315 continue;
316
317 if (reducedChiSquared < m_maxGoodMatchReducedChiSquared)
318 {
319 m_pParentAlgorithm->UpdateUponDeletion(pClusterToEnlarge1);
320 m_pParentAlgorithm->UpdateUponDeletion(pClusterToDelete1);
321
322 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
324
325 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
326 PandoraContentApi::MergeAndDeleteClusters(*m_pParentAlgorithm, pClusterToEnlarge1, pClusterToDelete1));
327
328 m_pParentAlgorithm->UpdateForNewClusters({pClusterToEnlarge1}, {nullptr});
329
330 m_pParentAlgorithm->UpdateUponDeletion(pClusterToEnlarge2);
331 m_pParentAlgorithm->UpdateUponDeletion(pClusterToDelete2);
332
333 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
335
336 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=,
337 PandoraContentApi::MergeAndDeleteClusters(*m_pParentAlgorithm, pClusterToEnlarge2, pClusterToDelete2));
338
339 m_pParentAlgorithm->UpdateForNewClusters({pClusterToEnlarge2}, {nullptr});
340
341 return true;
342 }
343 }
344 }
345 }
346 }
347
348 return false;
349}
350
351//------------------------------------------------------------------------------------------------------------------------------------------
352
354{
355 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
356 XmlHelper::ReadValue(xmlHandle, "MaxDRSeparationFromTrack", m_maxDRSeparationFromTrack));
357
359 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxClusterSeparation", m_maxClusterSeparation));
360
362 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxVertexSeparation", m_maxVertexSeparation));
363
364 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=,
365 XmlHelper::ReadValue(xmlHandle, "MaxGoodMatchReducedChiSquared", m_maxGoodMatchReducedChiSquared));
366
367 return STATUS_CODE_SUCCESS;
368}
369
370} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the delta ray merge tool class.
Header file for the cluster helper class.
Header file for the muon leading helper class.
Header file for the pfo helper class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
static pandora::StatusCode ReplaceCurrentList(const pandora::Algorithm &algorithm, const std::string &newListName)
Replace the current list with a pre-saved list; use this new list as a permanent replacement for the ...
static pandora::StatusCode MergeAndDeleteClusters(const pandora::Algorithm &algorithm, const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete)
Merge two clusters in the current list, enlarging one cluster and deleting the second.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
bool AreAssociated(const TensorType::Element &element1, const TensorType::Element &element2, const pandora::HitType &mergeHitType) const
Determine, from a topological point of view, whether two delta ray clusters should be merged together...
bool IsConnected(const pandora::Cluster *const pCluster, const pandora::Pfo *const pCommonMuonPfo) const
Determine whether a given cluster is connected to a cosmic ray pfo.
void GetConnectedMuons(const pandora::Cluster *const pDeltaRayCluster, const pandora::PfoList &commonMuonPfoList, pandora::PfoList &connectedMuonPfoList) const
Return the list of muon pfos that a specified delta ray cluster is directly connected to.
bool MakeTwoCommonViewMerges(const TensorType::ElementList &elementList) const
Search for two matches with two common clusters and attempt to merge the clusters in the third view t...
float m_maxVertexSeparation
The maximum separation of the connection points of two delta ray clusters that are hidden by a CR tra...
void FindVertices(const pandora::Pfo *const pCommonMuonPfo, const pandora::Cluster *const pCluster, pandora::CaloHitList &vertexList) const
Find all connection points of a delta ray cluster and a cosmic ray pfo.
bool IsHiddenByTrack(const pandora::ParticleFlowObject *const pMuonPfo, const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2) const
Determine whether two delta ray clusters are actually a single cluster that is hidden behind a cosmic...
bool MakeOneCommonViewMerges(const TensorType::ElementList &elementList) const
Search for two matches with a single common cluster and attempt to merge the clusters in the other tw...
bool ExamineConnectedElements(TensorType &overlapTensor) const
Identify ambiguous matches (e.g. 3:2:1) and attempt to merge clusters together.
float m_maxGoodMatchReducedChiSquared
The threshold reduced chi squared value for a potential two view merge to go ahead.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
bool IsBrokenCluster(const pandora::Cluster *const pClusterToEnlarge, const pandora::Cluster *const pClusterToDelete) const
Determine whether two delta ray clusters have been split.
DeltaRayMergeTool()
Default constructor.
void CombineCommonMuonPfoLists(const pandora::PfoList &commonMuonPfoList1, const pandora::PfoList &commonMuonPfoList2, pandora::PfoList &commonMuonPfoList) const
Create a list of the shared common muon pfos of two elements.
float m_maxClusterSeparation
The maximum separation of two broken clusters that should be merged.
float m_maxDRSeparationFromTrack
The maximum distance of a connected delta ray from a cosmic ray track.
bool Run(ThreeViewDeltaRayMatchingAlgorithm *const pAlgorithm, TensorType &overlapTensor)
Run the algorithm tool.
ThreeViewDeltaRayMatchingAlgorithm::MatchingType::TensorType TensorType
ThreeViewDeltaRayMatchingAlgorithm * m_pParentAlgorithm
Address of the parent matching algorithm.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
static float GetClosestDistance(const pandora::ClusterList &clusterList1, const pandora::ClusterList &clusterList2)
Get closest distance between clusters in a pair of cluster lists.
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.
void UpdateUponDeletion(const pandora::Cluster *const pDeletedCluster)
Update to reflect cluster deletion.
void UpdateForNewClusters(const pandora::ClusterVector &newClusterVector, const pandora::PfoVector &pfoVector)
Add a new cluster to algorithm ownership maps and, if it a delta ray cluster, to the underlying match...
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...
const std::string & GetClusterListName(const pandora::HitType hitType) const
Get the cluster list name corresponding to a specified hit type.
CaloHit class.
Definition CaloHit.h:26
Cluster class.
Definition Cluster.h:31
const OrderedCaloHitList & GetOrderedCaloHitList() const
Get the ordered calo hit list.
Definition Cluster.h:470
void FillCaloHitList(CaloHitList &caloHitList) const
Fill a provided calo hit list with all the calo hits in the ordered calo hit list.
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
const std::string & GetType() const
Get the type.
Definition Process.h:102
const std::string & GetInstanceName() const
Get the instance name.
Definition Process.h:109
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
HitType
Calorimeter hit type enum.
std::vector< const Cluster * > ClusterVector
MANAGED_CONTAINER< const Cluster * > ClusterList
std::unordered_set< const Cluster * > ClusterSet
MANAGED_CONTAINER< const CaloHit * > CaloHitList
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList