ATLAS Offline Software
Loading...
Searching...
No Matches
CaloClusterMatchingTool.cxx
Go to the documentation of this file.
1
2
3/*
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5*/
6
7// CaloClusterMatchingTool.cxx
8// Implementation file for class CaloClusterMatchingTool
9// Author: S.Binet<binet@cern.ch>
11
12// CaloClusterMatching includes
14
15// STL includes
16
17// FrameWork includes
19#include <algorithm>
20#include <utility>
21
22namespace ClusterMatching {
23
24 using namespace xAOD;
25
26 // Destructor
29
30 // Athena algtool's Hooks
33 {
34 ATH_MSG_INFO ("Initializing " << name() << "...");
35
36 if (m_clustersIn.empty()) {
37 ATH_MSG_ERROR("Empty name provided for TopoCluster collection nothing to "
38 "work with -- aborting");
39 return StatusCode::FAILURE;
40 }
41
42 ATH_CHECK(m_clustersIn.initialize());
43
44 return StatusCode::SUCCESS;
45 }
46
48 {
49 ATH_MSG_INFO ("Finalizing " << name() << "...");
50
51 return StatusCode::SUCCESS;
52 }
53
55 // Const methods:
57
58 StatusCode CaloClusterMatchingTool::fillClusterMap(const EventContext& ctx, TopoClusterMap& tcmap) const
59 {
60
62 ATH_CHECK( tcmap.SetTopoClusters(topoclusters.cptr()) );
63
64 return StatusCode::SUCCESS;
65 }
66
67 // return shared fraction of clustered cell energy
69 const xAOD::CaloCluster& testCluster) const
70 {
71 int nSharedCells(0);
72 float sharedE(0.);
73 float totalE(0.);
74 for (auto tcItr = testCluster.cell_begin(); tcItr != testCluster.cell_end();++tcItr) {
75 if (tcItr->e() > 1e-9 || !m_reqPosE) {
76 for (auto rcItr = refCluster.cell_begin(); rcItr != refCluster.cell_end(); ++rcItr) {
77 if (*tcItr && *rcItr && (*tcItr == *rcItr)) {
78 ++nSharedCells;
79 sharedE += tcItr->e();
80 }
81 }
82 totalE += tcItr->e();
83 }
84 }
85 if(nSharedCells>0) {
86 ATH_MSG_VERBOSE("Reference cluster and target cluster share " << nSharedCells << " cells, " << sharedE << " / " << totalE << " MeV");
87 ATH_MSG_VERBOSE("DeltaR = " << refCluster.p4().DeltaR(testCluster.p4()));
88 }
89 return totalE<1e-9 ? 0. : sharedE/totalE;
90 }
91
92 // return true if clusters share a given fraction of their cell energy
94 const xAOD::CaloCluster& testCluster) const
95 {
96 return getClusterSharedEfrac(refCluster,testCluster)>m_minSharedEfrac;
97 }
98
99 // fill a list of clusters from the testClusters container that match the reference cluster
100 // match criteria determined by calling clustersAreMatched
101 // return true if matchedClusters list is non-empty
103 const std::vector<const xAOD::CaloCluster*>& testClusters,
104 std::vector<const xAOD::CaloCluster*>& matchedClusters) const
105 {
106 // check that it's empty?
107 matchedClusters.clear();
108
109 for(const auto& testCluster : testClusters) {
110 if(clustersAreMatched(refCluster, *testCluster)) matchedClusters.push_back(testCluster);
111 }
112 return !matchedClusters.empty();
113 }
114
115 // fill a list of clusters from the configured cluster container that match the reference cluster
116 // match criteria determined by calling clustersAreMatched
117 // return true if matchedClusters list is non-empty
119 std::vector<const xAOD::CaloCluster*>& matchedClusters,
120 const TopoClusterMap& tcmap,
121 bool useLeadingCellEtaPhi) const
122 {
123 float refEta(0.), refPhi(0.);
124 if(useLeadingCellEtaPhi) { // needed for muons because muon clusters have no eta/phi
125 const CaloCell* leadcell(nullptr);
126 float leadcellE(0.);
127 for(auto refItr = refCluster.cell_begin(); refItr!=refCluster.cell_end(); ++refItr) {
128 if(refItr->e() > leadcellE) leadcell = *refItr;
129 }
130 if(leadcell) {
131 refEta = leadcell->eta();
132 refPhi = leadcell->phi();
133 }
134 } else {
135 refEta = refCluster.eta();
136 refPhi = refCluster.phi();
137 }
138
139 // for now use the standard matching sizes determined by egamma, but may need to change for muons??
140 // egamma shower is probably wider than muon cell track
141 const std::vector<const xAOD::CaloCluster*> testClusters =
142 tcmap.RetrieveTopoClusters(refEta, refPhi, refCluster.e()*cosh(refEta));
143
144 return getMatchedClusters(refCluster, testClusters, matchedClusters);
145 }
146
147 // fill a list of clusters from the testClusters container that match the reference cluster
148 // match criteria determined by calling clustersAreMatched
149 // return true if matchedClusters list is non-empty
151 const std::vector<const xAOD::CaloCluster*>& testClusters,
152 std::vector<std::pair<const xAOD::CaloCluster*, float> >& matchedClustersAndE) const
153 {
154 // check that it's empty?
155 matchedClustersAndE.clear();
156
157 for(const auto& testCluster : testClusters) {
158 float sharedEfrac = getClusterSharedEfrac(refCluster, *testCluster);
159 if(sharedEfrac>m_minSharedEfrac) {
160 matchedClustersAndE.emplace_back(testCluster,sharedEfrac);
161 }
162 }
163 return !matchedClustersAndE.empty();
164 }
165
166 // fill a list of clusters from the configured cluster container that match the reference cluster
167 // match criteria determined by calling clustersAreMatched
168 // return true if matchedClusters list is non-empty
170 std::vector<std::pair<const xAOD::CaloCluster*, float> >& matchedClustersAndE,
171 const TopoClusterMap& tcmap,
172 bool useLeadingCellEtaPhi) const
173 {
174 float refEta(0.), refPhi(0.);
175 if(useLeadingCellEtaPhi) { // needed for muons because muon clusters have no eta/phi
176 const CaloCell* leadcell(nullptr);
177 float leadcellE(0.);
178 for(auto refItr = refCluster.cell_begin(); refItr!=refCluster.cell_end(); ++refItr) {
179 if(refItr->e() > leadcellE) leadcell = *refItr;
180 }
181 if(leadcell) {
182 refEta = leadcell->eta();
183 refPhi = leadcell->phi();
184 }
185 } else {
186 refEta = refCluster.eta();
187 refPhi = refCluster.phi();
188 }
189
190 // for now use the standard matching sizes determined by egamma, but may need to change for muons??
191 // egamma shower is probably wider than muon cell track
192 const std::vector<const xAOD::CaloCluster*> testClusters =
193 tcmap.RetrieveTopoClusters(refEta, refPhi, refCluster.e()*cosh(refEta));
194
195 return getMatchedClusters(refCluster, testClusters, matchedClustersAndE);
196 }
197
198 // set ElementLinks to clusters from the configured cluster container that match the reference cluster
199 // works via getMatchedClusters
200 // return true if matchedClusters list is non-empty
202 const xAOD::CaloCluster& refCluster,
203 const std::vector<const xAOD::CaloCluster*>& testClusters,
204 bool (*gtrthan)(const std::pair<const xAOD::CaloCluster*,float>& pair1,
205 const std::pair<const xAOD::CaloCluster*,float>& pair2)) const
206 {
207 std::vector<std::pair<const CaloCluster*,float> > matchedClustersAndE;
208 std::vector<ElementLink<CaloClusterContainer> > tcLinks;
209 std::vector<float> tcSharedE;
210 if(!testClusters.empty()) {
211 const CaloClusterContainer* pClCont = static_cast<const CaloClusterContainer*>(testClusters.front()->container());
212 if(getMatchedClusters(refCluster, testClusters, matchedClustersAndE)) {
213 std::sort(matchedClustersAndE.begin(),matchedClustersAndE.end(),gtrthan);
214 for(const auto& tcAndE : matchedClustersAndE) {
215 tcLinks.emplace_back(*pClCont,tcAndE.first->index());
216 tcSharedE.push_back(tcAndE.second);
217 }
218 }
219 }
220 // apply the decoration to the reference cluster -- no exceptions
221 elementLinkDec(refCluster) = std::move(tcLinks);
222 ATH_MSG_VERBOSE("Decorate cluster " << refCluster.index() << " with " << elementLinkDec(refCluster).size() << " tc links");
223
224 return StatusCode::SUCCESS;
225 }
226
227 // set ElementLinks to clusters from the configured cluster container that match the reference cluster
228 // works via getMatchedClusters
229 // return true if matchedClusters list is non-empty
231 elementLinkDecorHandle_t& elementLinkDec,
232 const xAOD::CaloCluster& refCluster,
233 const TopoClusterMap& tcmap,
234 bool useLeadingCellEtaPhi,
235 bool (*gtrthan)(const std::pair<const xAOD::CaloCluster*,float>& pair1,
236 const std::pair<const xAOD::CaloCluster*,float>& pair2)) const
237 {
238 std::vector<std::pair<const CaloCluster*,float> > matchedClustersAndE;
239 std::vector<ElementLink<CaloClusterContainer> > tcLinks;
240 std::vector<float> tcSharedE;
241 // no need to worry about return value.
242 if(getMatchedClusters(refCluster, matchedClustersAndE, tcmap, useLeadingCellEtaPhi)) {
243 const CaloClusterContainer* pClCont = static_cast<const CaloClusterContainer*>(matchedClustersAndE.front().first->container());
244 std::sort(matchedClustersAndE.begin(),matchedClustersAndE.end(),gtrthan);
245 for(const auto& tcAndE : matchedClustersAndE) {
246 tcLinks.emplace_back(*pClCont,tcAndE.first->index());
247 tcSharedE.push_back(tcAndE.second);
248 }
249 }
250 // apply the decoration to the reference cluster -- no exceptions
251 elementLinkDec(refCluster) = std::move(tcLinks);
252 ATH_MSG_VERBOSE("Decorate cluster " << refCluster.index() << " with " << elementLinkDec(refCluster).size() << " tc links");
253
254 return StatusCode::SUCCESS;
255 }
256}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
Handle class for adding a decoration to an object.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
virtual double phi() const override final
get phi (through CaloDetDescrElement)
Definition CaloCell.h:375
virtual double eta() const override final
get eta (through CaloDetDescrElement)
Definition CaloCell.h:382
virtual ~CaloClusterMatchingTool()
Destructor:
StatusCode linkMatchedClusters(elementLinkDecorHandle_t &elementLinkDec, const xAOD::CaloCluster &refCluster, const std::vector< const xAOD::CaloCluster * > &testClusters, bool(*gtrthan)(const std::pair< const xAOD::CaloCluster *, float > &pair1, const std::pair< const xAOD::CaloCluster *, float > &pair2)) const override final
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
bool clustersAreMatched(const xAOD::CaloCluster &refCluster, const xAOD::CaloCluster &testCluster) const override final
bool getMatchedClusters(const xAOD::CaloCluster &refCluster, const std::vector< const xAOD::CaloCluster * > &testClusters, std::vector< const xAOD::CaloCluster * > &matchedClusters) const override final
float getClusterSharedEfrac(const xAOD::CaloCluster &refCluster, const xAOD::CaloCluster &testCluster) const override final
StatusCode fillClusterMap(const EventContext &ctx, TopoClusterMap &tcmap) const override final
SG::ReadHandleKey< xAOD::CaloClusterContainer > m_clustersIn
SG::WriteDecorHandle< xAOD::CaloClusterContainer, std::vector< ElementLink< xAOD::CaloClusterContainer > > > elementLinkDecorHandle_t
size_t index() const
Return the index of this element within its container.
const_pointer_type cptr()
Dereference the pointer.
StatusCode SetTopoClusters(const xAOD::CaloClusterContainer *)
std::vector< const xAOD::CaloCluster * > RetrieveTopoClusters(double eta, double phi, double Pt) const
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
const_cell_iterator cell_end() const
virtual double phi() const
The azimuthal angle ( ) of the particle.
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version)
virtual FourMom_t p4() const
The full 4-momentum of the particle.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.