Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
CosmicRayBaseMatchingAlgorithm.cc
Go to the documentation of this file.
1
10
12
15
16using namespace pandora;
17
18namespace lar_content
19{
20
22{
23 // Get the available clusters for each view
24 ClusterVector availableClustersU, availableClustersV, availableClustersW;
25 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetAvailableClusters(m_inputClusterListNameU, availableClustersU));
26 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetAvailableClusters(m_inputClusterListNameV, availableClustersV));
27 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetAvailableClusters(m_inputClusterListNameW, availableClustersW));
28
29 // Select clean clusters in each view
30 ClusterVector cleanClustersU, cleanClustersV, cleanClustersW;
31 this->SelectCleanClusters(availableClustersU, cleanClustersU);
32 this->SelectCleanClusters(availableClustersV, cleanClustersV);
33 this->SelectCleanClusters(availableClustersW, cleanClustersW);
34
35 // Build associations between pairs of views
36 ClusterAssociationMap matchedClusterUV, matchedClusterVW, matchedClusterWU;
37 this->MatchClusters(cleanClustersU, cleanClustersV, matchedClusterUV);
38 this->MatchClusters(cleanClustersV, cleanClustersW, matchedClusterVW);
39 this->MatchClusters(cleanClustersW, cleanClustersU, matchedClusterWU);
40
41 // Build particles from associations
42 ParticleList particleList;
43 this->MatchThreeViews(matchedClusterUV, matchedClusterVW, matchedClusterWU, particleList);
44 this->MatchTwoViews(matchedClusterUV, matchedClusterVW, matchedClusterWU, particleList);
45 this->BuildParticles(particleList);
46
47 return STATUS_CODE_SUCCESS;
48}
49
50//------------------------------------------------------------------------------------------------------------------------------------------
51
52StatusCode CosmicRayBaseMatchingAlgorithm::GetAvailableClusters(const std::string inputClusterListName, ClusterVector &clusterVector) const
53{
54 const ClusterList *pClusterList = NULL;
56 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_INITIALIZED, !=, PandoraContentApi::GetList(*this, inputClusterListName, pClusterList))
57
58 if (!pClusterList || pClusterList->empty())
59 {
61 std::cout << "CosmicRayBaseMatchingAlgorithm: unable to find cluster list " << inputClusterListName << std::endl;
62
63 return STATUS_CODE_SUCCESS;
64 }
65
66 for (const Cluster *const pCluster : *pClusterList)
67 {
68 if (!pCluster->IsAvailable())
69 continue;
70
71 clusterVector.push_back(pCluster);
72 }
73
74 std::sort(clusterVector.begin(), clusterVector.end(), LArClusterHelper::SortByNHits);
75
76 return STATUS_CODE_SUCCESS;
77}
78
79//------------------------------------------------------------------------------------------------------------------------------------------
80
82 const ClusterVector &clusterVector1, const ClusterVector &clusterVector2, ClusterAssociationMap &matchedClusters12) const
83{
84 // Check that there are input clusters from both views
85 if (clusterVector1.empty() || clusterVector2.empty())
86 return;
87
88 const HitType hitType1(LArClusterHelper::GetClusterHitType(*clusterVector1.begin()));
89 const HitType hitType2(LArClusterHelper::GetClusterHitType(*clusterVector2.begin()));
90
91 if (hitType1 == hitType2)
92 throw StatusCodeException(STATUS_CODE_FAILURE);
93
94 for (const Cluster *const pCluster1 : clusterVector1)
95 {
96 for (const Cluster *const pCluster2 : clusterVector2)
97 {
98 if (this->MatchClusters(pCluster1, pCluster2))
99 {
100 UIntSet daughterVolumeIntersection;
101 LArGeometryHelper::GetCommonDaughterVolumes(pCluster1, pCluster2, daughterVolumeIntersection);
102
103 if (!daughterVolumeIntersection.empty())
104 matchedClusters12[pCluster1].push_back(pCluster2);
105 }
106 }
107 }
108}
109
110//------------------------------------------------------------------------------------------------------------------------------------------
111
113 const ClusterAssociationMap &matchedClusters23, const ClusterAssociationMap &matchedClusters31, ParticleList &matchedParticles) const
114{
115 if (matchedClusters12.empty() || matchedClusters23.empty() || matchedClusters31.empty())
116 return;
117
118 ParticleList candidateParticles;
119
120 ClusterList clusterList1;
121 for (const auto &mapEntry : matchedClusters12)
122 clusterList1.push_back(mapEntry.first);
123 clusterList1.sort(LArClusterHelper::SortByNHits);
124
125 for (const Cluster *const pCluster1 : clusterList1)
126 {
127 const ClusterList &clusterList2(matchedClusters12.at(pCluster1));
128
129 for (const Cluster *const pCluster2 : clusterList2)
130 {
131 ClusterAssociationMap::const_iterator iter23 = matchedClusters23.find(pCluster2);
132
133 if (matchedClusters23.end() == iter23)
134 continue;
135
136 const ClusterList &clusterList3 = iter23->second;
137
138 for (const Cluster *const pCluster3 : clusterList3)
139 {
140 ClusterAssociationMap::const_iterator iter31 = matchedClusters31.find(pCluster3);
141
142 if (matchedClusters31.end() == iter31)
143 continue;
144
145 if (iter31->second.end() == std::find(iter31->second.begin(), iter31->second.end(), pCluster1))
146 continue;
147
148 const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
149 const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
150 const HitType hitType3(LArClusterHelper::GetClusterHitType(pCluster3));
151
152 if (!this->CheckMatchedClusters3D(pCluster1, pCluster2, pCluster3))
153 continue;
154
155 const Cluster *const pClusterU(
156 (TPC_VIEW_U == hitType1) ? pCluster1 : (TPC_VIEW_U == hitType2) ? pCluster2 : (TPC_VIEW_U == hitType3) ? pCluster3 : NULL);
157 const Cluster *const pClusterV(
158 (TPC_VIEW_V == hitType1) ? pCluster1 : (TPC_VIEW_V == hitType2) ? pCluster2 : (TPC_VIEW_V == hitType3) ? pCluster3 : NULL);
159 const Cluster *const pClusterW(
160 (TPC_VIEW_W == hitType1) ? pCluster1 : (TPC_VIEW_W == hitType2) ? pCluster2 : (TPC_VIEW_W == hitType3) ? pCluster3 : NULL);
161
162 candidateParticles.push_back(Particle(pClusterU, pClusterV, pClusterW));
163 }
164 }
165 }
166
167 return this->ResolveAmbiguities(candidateParticles, matchedParticles);
168}
169
170//------------------------------------------------------------------------------------------------------------------------------------------
171
173 const ClusterAssociationMap &matchedClusters23, const ClusterAssociationMap &matchedClusters31, ParticleList &matchedParticles) const
174{
175 ParticleList candidateParticles;
176 this->MatchTwoViews(matchedClusters12, candidateParticles);
177 this->MatchTwoViews(matchedClusters23, candidateParticles);
178 this->MatchTwoViews(matchedClusters31, candidateParticles);
179
180 return this->ResolveAmbiguities(candidateParticles, matchedParticles);
181}
182
183//------------------------------------------------------------------------------------------------------------------------------------------
184
185void CosmicRayBaseMatchingAlgorithm::MatchTwoViews(const ClusterAssociationMap &matchedClusters12, ParticleList &matchedParticles) const
186{
187 if (matchedClusters12.empty())
188 return;
189
190 ClusterList clusterList1;
191 for (const auto &mapEntry : matchedClusters12)
192 clusterList1.push_back(mapEntry.first);
193 clusterList1.sort(LArClusterHelper::SortByNHits);
194
195 for (const Cluster *const pCluster1 : clusterList1)
196 {
197 const ClusterList &clusterList2(matchedClusters12.at(pCluster1));
198
199 for (const Cluster *const pCluster2 : clusterList2)
200 {
201 const HitType hitType1(LArClusterHelper::GetClusterHitType(pCluster1));
202 const HitType hitType2(LArClusterHelper::GetClusterHitType(pCluster2));
203
204 const Cluster *const pClusterU((TPC_VIEW_U == hitType1) ? pCluster1 : (TPC_VIEW_U == hitType2) ? pCluster2 : NULL);
205 const Cluster *const pClusterV((TPC_VIEW_V == hitType1) ? pCluster1 : (TPC_VIEW_V == hitType2) ? pCluster2 : NULL);
206 const Cluster *const pClusterW((TPC_VIEW_W == hitType1) ? pCluster1 : (TPC_VIEW_W == hitType2) ? pCluster2 : NULL);
207
208 matchedParticles.push_back(Particle(pClusterU, pClusterV, pClusterW));
209 }
210 }
211}
212
213//------------------------------------------------------------------------------------------------------------------------------------------
214
215void CosmicRayBaseMatchingAlgorithm::ResolveAmbiguities(const ParticleList &candidateParticles, ParticleList &matchedParticles) const
216{
217 for (const Particle &particle1 : candidateParticles)
218 {
219 bool isGoodMatch(true);
220
221 for (const Particle &particle2 : candidateParticles)
222 {
223 const bool commonU(particle1.m_pClusterU == particle2.m_pClusterU);
224 const bool commonV(particle1.m_pClusterV == particle2.m_pClusterV);
225 const bool commonW(particle1.m_pClusterW == particle2.m_pClusterW);
226
227 const bool ambiguousU(commonU && NULL != particle1.m_pClusterU);
228 const bool ambiguousV(commonV && NULL != particle1.m_pClusterV);
229 const bool ambiguousW(commonW && NULL != particle1.m_pClusterW);
230
231 if (commonU && commonV && commonW)
232 continue;
233
234 if (ambiguousU || ambiguousV || ambiguousW)
235 {
236 isGoodMatch = false;
237 break;
238 }
239 }
240
241 if (isGoodMatch)
242 matchedParticles.push_back(particle1);
243 }
244}
245
246//------------------------------------------------------------------------------------------------------------------------------------------
247
249{
250 if (particleList.empty())
251 return;
252
253 const PfoList *pPfoList = NULL;
254 std::string pfoListName;
255 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pPfoList, pfoListName));
256
257 for (const Particle &particle : particleList)
258 {
259 const Cluster *const pClusterU = particle.m_pClusterU;
260 const Cluster *const pClusterV = particle.m_pClusterV;
261 const Cluster *const pClusterW = particle.m_pClusterW;
262
263 const bool isAvailableU((NULL != pClusterU) ? pClusterU->IsAvailable() : true);
264 const bool isAvailableV((NULL != pClusterV) ? pClusterV->IsAvailable() : true);
265 const bool isAvailableW((NULL != pClusterW) ? pClusterW->IsAvailable() : true);
266
267 if (!(isAvailableU && isAvailableV && isAvailableW))
268 throw StatusCodeException(STATUS_CODE_FAILURE);
269
270 PandoraContentApi::ParticleFlowObject::Parameters pfoParameters;
271 this->SetPfoParameters(particle, pfoParameters);
272
273 if (pfoParameters.m_clusterList.empty())
274 throw StatusCodeException(STATUS_CODE_FAILURE);
275
276 const ParticleFlowObject *pPfo(NULL);
277 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ParticleFlowObject::Create(*this, pfoParameters, pPfo));
278 }
279
280 if (!pPfoList->empty())
282}
283
284//------------------------------------------------------------------------------------------------------------------------------------------
285
286CosmicRayBaseMatchingAlgorithm::Particle::Particle(const Cluster *const pClusterU, const Cluster *const pClusterV, const Cluster *const pClusterW) :
287 m_pClusterU(pClusterU),
288 m_pClusterV(pClusterV),
289 m_pClusterW(pClusterW)
290{
291 if (NULL == m_pClusterU && NULL == m_pClusterV && NULL == m_pClusterW)
292 throw StatusCodeException(STATUS_CODE_FAILURE);
293
297
298 if (!(TPC_VIEW_U == hitTypeU && TPC_VIEW_V == hitTypeV && TPC_VIEW_W == hitTypeW))
299 throw StatusCodeException(STATUS_CODE_FAILURE);
300}
301
302//------------------------------------------------------------------------------------------------------------------------------------------
303
305{
306 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputPfoListName", m_outputPfoListName));
307 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameU", m_inputClusterListNameU));
308 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameV", m_inputClusterListNameV));
309 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputClusterListNameW", m_inputClusterListNameW));
310
311 return STATUS_CODE_SUCCESS;
312}
313
314} // namespace lar_content
Grouping of header files for many classes of use in particle flow algorithms.
Header file for the cosmic ray base matching algorithm class.
Header file for the cluster helper class.
Header file for the geometry 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
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:19
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 CreateTemporaryListAndSetCurrent(const pandora::Algorithm &algorithm, const T *&pT, std::string &temporaryListName)
Create a temporary list and set it to be the current list, enabling object creation.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static const pandora::PandoraSettings * GetSettings(const pandora::Algorithm &algorithm)
Get the pandora settings instance.
const pandora::Cluster * m_pClusterW
Address of cluster in W view.
const pandora::Cluster * m_pClusterU
Address of cluster in U view.
Particle(const pandora::Cluster *const pClusterU, const pandora::Cluster *const pClusterV, const pandora::Cluster *const pClusterW)
Constructor.
const pandora::Cluster * m_pClusterV
Address of cluster in V view.
std::unordered_map< const pandora::Cluster *, pandora::ClusterList > ClusterAssociationMap
virtual void SelectCleanClusters(const pandora::ClusterVector &inputVector, pandora::ClusterVector &outputVector) const =0
Select a set of clusters judged to be clean.
void ResolveAmbiguities(const ParticleList &inputList, ParticleList &outputList) const
Remove ambiguities between candidate particles.
pandora::StatusCode GetAvailableClusters(const std::string inputClusterListName, pandora::ClusterVector &clusterVector) const
Get a vector of available clusters.
virtual bool CheckMatchedClusters3D(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, const pandora::Cluster *const pCluster3) const =0
Check that three clusters have a consistent 3D position.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
std::string m_inputClusterListNameW
The name of the view W cluster list.
virtual void SetPfoParameters(const CosmicRayBaseMatchingAlgorithm::Particle &protoParticle, PandoraContentApi::ParticleFlowObject::Parameters &pfoParameters) const =0
Calculate Pfo properties from proto particle.
virtual bool MatchClusters(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2) const =0
Match a pair of clusters from two views.
void MatchTwoViews(const CosmicRayBaseMatchingAlgorithm::ClusterAssociationMap &matchedClusters12, const CosmicRayBaseMatchingAlgorithm::ClusterAssociationMap &matchedClusters23, const CosmicRayBaseMatchingAlgorithm::ClusterAssociationMap &matchedClusters31, ParticleList &particleList) const
Match clusters from two views and form into particles.
void MatchThreeViews(const CosmicRayBaseMatchingAlgorithm::ClusterAssociationMap &matchedClusters12, const CosmicRayBaseMatchingAlgorithm::ClusterAssociationMap &matchedClusters23, const CosmicRayBaseMatchingAlgorithm::ClusterAssociationMap &matchedClusters31, ParticleList &particleList) const
Match clusters from three views and form into particles.
std::string m_inputClusterListNameV
The name of the view V cluster list.
void BuildParticles(const ParticleList &particleList)
Build PFO objects from candidate particles.
std::string m_inputClusterListNameU
The name of the view U cluster list.
std::string m_outputPfoListName
The name of the output PFO list.
static pandora::HitType GetClusterHitType(const pandora::Cluster *const pCluster)
Get the hit type associated with a two dimensional cluster.
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,...
static void GetCommonDaughterVolumes(const pandora::Cluster *const pCluster1, const pandora::Cluster *const pCluster2, UIntSet &intersect)
Return the set of common daughter volumes between two 2D clusters.
Cluster class.
Definition Cluster.h:31
bool IsAvailable() const
Whether the cluster is available to be added to a particle flow object.
Definition Cluster.h:582
bool ShouldDisplayAlgorithmInfo() const
Whether to display algorithm information during processing.
ParticleFlowObject class.
StatusCodeException class.
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
StatusCode
The StatusCode enum.
MANAGED_CONTAINER< const ParticleFlowObject * > PfoList