ATLAS Offline Software
Loading...
Searching...
No Matches
CaloClusterThinning.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6// CaloClusterThinning.cxx, (c) ATLAS Detector software
8// Author: Simone Mazza (simone.mazza@mi.infn.it)
9
11#include "ClustersInCone.h"
12
13#include "GaudiKernel/ThreadLocalContext.h"
23
24#include <algorithm>
25#include <string>
26#include <vector>
27
28// Constructor
30 const std::string& t,
31 const std::string& n,
32 const IInterface* p)
33 : base_class(t, n, p)
34 , m_ntot(0)
35 , m_ntotTopo(0)
36 , m_npass(0)
37 , m_npassTopo(0)
38 , m_run_calo(false)
39 , m_run_topo(false)
41 , m_coneSize(-1.0)
42{
43 declareProperty("SelectionString", m_selectionString);
44 declareProperty("ConeSize", m_coneSize);
45}
46
47// Destructor
49
50// Athena initialize and finalize
51StatusCode
53{
54 // Decide which collections need to be checked for ID TrackParticles
55 ATH_MSG_VERBOSE("initialize() ...");
56
57 if (!m_CaloClSGKey.empty()) {
59 m_run_calo = true;
60 ATH_MSG_INFO("Using " << m_CaloClSGKey.key()
61 << "as the source collection for calo clusters");
62 }
63 if (!m_TopoClSGKey.empty()) {
65 m_run_topo = true;
66 ATH_MSG_INFO("Using " << m_TopoClSGKey.key()
67 << "as the source collection for topo calo clusters");
68 }
69 if (m_CaloClSGKey.empty() && m_TopoClSGKey.empty()) {
71 "No CalCaloTopoCluster or CaloCluster collection provided for thinning.");
72 return StatusCode::FAILURE;
73 }
74
75 if (m_sgKey.empty()) {
76 ATH_MSG_FATAL("No particle collection provided for thinning.");
77 return StatusCode::FAILURE;
78 } else {
80 "Calo clusters associated with objects in "
81 << m_sgKey.key()
82 << " will be retained in this format with the rest being thinned away");
83 ATH_CHECK(m_sgKey.initialize());
84 }
85
86 // Set up the text-parsing machinery for selectiong the photon directly
87 // according to user cuts
88 if (!m_selectionString.empty()) {
89 ATH_CHECK(initializeParser(m_selectionString));
90 }
91
92 return StatusCode::SUCCESS;
93}
94
95StatusCode
97{
98 ATH_MSG_VERBOSE("finalize() ...");
99 ATH_MSG_INFO("Processed " << m_ntot << " clusters, of which " << m_npass
100 << " were retained ");
101 ATH_MSG_INFO("Processed " << m_ntotTopo << " topo clusters, of which "
102 << m_npassTopo << " were retained ");
103 ATH_CHECK(finalizeParser());
104 return StatusCode::SUCCESS;
105}
106
107// The thinning itself
108StatusCode
110{
111 const EventContext& ctx = Gaudi::Hive::currentContext();
112
113 bool is_muons = false;
114 bool is_egamma = false;
115 bool is_tau = false;
116 bool is_track = false;
117
118 // Retrieve egCluster collection
120 if (m_run_calo) {
121 importedCaloCluster =
123 }
124
125 // Retrieve CalCaloTopo collection if required
126 SG::ReadHandle<xAOD::CaloClusterContainer> importedTopoCaloCluster;
127 if (m_run_topo) {
128 importedTopoCaloCluster =
130 }
131 // Check if the event contains clusters
132 unsigned int nClusters = 0;
133 if (m_run_calo) {
134 nClusters = importedCaloCluster->size();
135 }
136 unsigned int nTopoClusters = 0;
137 if (m_run_topo) {
138 nTopoClusters = importedTopoCaloCluster->size();
139 }
140 if (nClusters == 0 && nTopoClusters == 0) {
141 return StatusCode::SUCCESS;
142 }
143
144 // Set up a mask with the same entries as the full cluster collection(s)
145 std::vector<bool> mask(nClusters, false), topomask(nTopoClusters, false);
146 m_ntot += nClusters;
147 m_ntotTopo += nTopoClusters;
148
149 // Retrieve particle container
150 SG::ReadHandle<xAOD::IParticleContainer> importedParticlesHandle{ m_sgKey,
151 ctx };
152 const xAOD::IParticleContainer* importedParticles =
153 importedParticlesHandle.ptr();
154
155 // No particles in the input
156 unsigned int nParticles(importedParticles->size());
157 if (nParticles == 0) {
158 if (m_run_calo) {
160 thin.keep(mask);
161 }
162 if (m_run_topo) {
164 thin.keep(topomask);
165 }
166 return StatusCode::SUCCESS;
167 }
168
169 is_egamma = false;
170 is_muons = false;
171 is_track = false;
172
173 // Are we dealing with a compatible collection?
175 dynamic_cast<const xAOD::ElectronContainer*>(importedParticles);
177 dynamic_cast<const xAOD::PhotonContainer*>(importedParticles);
178 if (testElectrons || testPhotons) {
179 is_egamma = true;
180 }
181 const xAOD::MuonContainer* testMuons =
182 dynamic_cast<const xAOD::MuonContainer*>(importedParticles);
183 if (testMuons) {
184 is_muons = true;
185 }
186 const xAOD::TauJetContainer* testTaus =
187 dynamic_cast<const xAOD::TauJetContainer*>(importedParticles);
188 if (testTaus) {
189 is_tau = true;
190 }
191 const xAOD::TrackParticleContainer* testTracks =
192 dynamic_cast<const xAOD::TrackParticleContainer*>(importedParticles);
193 if (testTracks) {
194 is_track = true;
195 }
196
197 if (!(is_egamma || is_muons || is_tau || is_track)) {
198 ATH_MSG_ERROR("This tool only works with Egamma, Muons, Taus and Tracks "
199 << m_sgKey.key() << " is not a compatible collection");
200 return StatusCode::FAILURE;
201 }
202
203 // Selection
204 // Execute the text parsers if requested
205 if (!m_selectionString.empty()) {
206 std::vector<int> entries = m_parser->evaluateAsVector();
207 unsigned int nEntries = entries.size();
208 // check the sizes are compatible
209 if (nParticles != nEntries) {
210 ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string "
211 "used e-gamma objects??");
212 return StatusCode::FAILURE;
213 }
214 std::vector<const xAOD::IParticle*> particlesToCheck = {};
215 // identify which e-gammas to keep for the thinning check
216 for (unsigned int i = 0; i < nParticles; ++i) {
217 if (static_cast<bool>(entries[i])) {
218 particlesToCheck.push_back((*importedParticles)[i]);
219 }
220 }
222 for (const auto* particle : particlesToCheck) {
223 if (m_run_calo) {
224 // Always keep own particle clusters
225 if (particleCluster(mask,
226 particle,
227 importedCaloCluster.cptr(),
228 is_muons,
229 is_egamma,
230 is_tau) != StatusCode::SUCCESS) {
231 return StatusCode::FAILURE;
232 }
233 if (setClustersMask(mask,
234 particle,
235 importedCaloCluster.cptr(),
236 is_muons,
237 is_egamma,
238 is_track) != StatusCode::SUCCESS) {
239 return StatusCode::FAILURE;
240 }
241 }
242 if (m_run_topo) {
243 if (particleCluster(topomask,
244 particle,
245 importedTopoCaloCluster.cptr(),
246 is_muons,
247 is_egamma,
248 is_tau) != StatusCode::SUCCESS) {
249 return StatusCode::FAILURE;
250 }
251 if (setClustersMask(topomask,
252 particle,
253 importedTopoCaloCluster.cptr(),
254 is_muons,
255 is_egamma,
256 is_track) != StatusCode::SUCCESS) {
257 return StatusCode::FAILURE;
258 }
259 }
260 }
261 } else { // No selection string provided
262 for (const auto* particle : *importedParticles) {
263 if (m_run_calo) {
264 if (particleCluster(mask,
265 particle,
266 importedCaloCluster.cptr(),
267 is_muons,
268 is_egamma,
269 is_tau) != StatusCode::SUCCESS) {
270 return StatusCode::FAILURE;
271 }
272 if (setClustersMask(mask,
273 particle,
274 importedCaloCluster.cptr(),
275 is_muons,
276 is_egamma,
277 is_track) != StatusCode::SUCCESS) {
278 return StatusCode::FAILURE;
279 }
280 }
281 if (m_run_topo) {
282 if (particleCluster(topomask,
283 particle,
284 importedTopoCaloCluster.cptr(),
285 is_muons,
286 is_egamma,
287 is_tau) != StatusCode::SUCCESS) {
288 return StatusCode::FAILURE;
289 }
290 if (setClustersMask(topomask,
291 particle,
292 importedTopoCaloCluster.cptr(),
293 is_muons,
294 is_egamma,
295 is_track) != StatusCode::SUCCESS) {
296 return StatusCode::FAILURE;
297 }
298 }
299 }
300 }
301 //
302 // Count up the mask contents
303 for (unsigned int i = 0; i < nClusters; ++i) {
304 if (mask[i])
305 ++m_npass;
306 }
307 for (unsigned int i = 0; i < nTopoClusters; ++i) {
308 if (topomask[i])
309 ++m_npassTopo;
310 }
311 //
312 // Execute the thinning service based on the mask. Finish.
313 if (m_run_calo) {
315 thin.keep(mask);
316 }
317 if (m_run_topo) {
319 thin.keep(topomask);
320 }
321 return StatusCode::SUCCESS;
322}
323
324StatusCode
326 std::vector<bool>& mask,
327 const xAOD::IParticle* particle,
329 bool is_muons,
330 bool is_egamma,
331 bool is_track) const
332{
333 if (!cps) {
334 ATH_MSG_ERROR("Cluster collection not found");
335 return StatusCode::FAILURE;
336 }
337
338 if (is_egamma) {
339 const xAOD::Egamma* egamma = dynamic_cast<const xAOD::Egamma*>(particle);
340 if (!egamma) {
341 ATH_MSG_ERROR("Egamma cast failed");
342 return StatusCode::FAILURE;
343 }
345 }
346 if (is_muons) {
347 const xAOD::Muon* muon = dynamic_cast<const xAOD::Muon*>(particle);
348 if (!muon) {
349 ATH_MSG_ERROR("Muon cast failed");
350 return StatusCode::FAILURE;
351 }
353 }
354 if (is_track) {
355 const xAOD::TrackParticle* track = dynamic_cast<const xAOD::TrackParticle*>(particle);
356 if (!track) {
357 ATH_MSG_ERROR("Track cast failed");
358 return StatusCode::FAILURE;
359 }
361 }
362 return StatusCode::SUCCESS;
363}
364
365StatusCode
367 std::vector<bool>& mask,
368 const xAOD::IParticle* particle,
370 bool is_muons,
371 bool is_egamma,
372 bool is_tau) const
373{
374 if (!cps) {
375 ATH_MSG_ERROR("Cluster collection not found");
376 return StatusCode::FAILURE;
377 }
378
379 if (is_egamma) {
380 const xAOD::Egamma* egamma = dynamic_cast<const xAOD::Egamma*>(particle);
381 if (!egamma) {
382 ATH_MSG_ERROR("Egamma cast failed");
383 return StatusCode::FAILURE;
384 }
385 auto it = std::find(cps->begin(), cps->end(), egamma->caloCluster());
386 if (it != cps->end()) {
387 int ItsCluster = std::distance(cps->begin(), it);
388 mask[ItsCluster] = true;
389 }
390 }
391
392 if (is_muons) {
393 const xAOD::Muon* muon = dynamic_cast<const xAOD::Muon*>(particle);
394 if (!muon) {
395 ATH_MSG_ERROR("Muon cast failed");
396 return StatusCode::FAILURE;
397 }
398 auto it = std::find(cps->begin(), cps->end(), muon->cluster());
399 if (it != cps->end()) {
400 int ItsCluster = std::distance(cps->begin(), it);
401 mask[ItsCluster] = true;
402 }
403 }
404
405 if (is_tau) {
406 const xAOD::TauJet* tau = dynamic_cast<const xAOD::TauJet*>(particle);
407 if (!tau) {
408 ATH_MSG_ERROR("TauJet cast failed");
409 return StatusCode::FAILURE;
410 }
412 TLorentzVector LC_P4 = tau->p4(xAOD::TauJetParameters::DetectorAxis);
413 for (const auto * pJetConstituent : vec) {
414 TLorentzVector cluster_P4;
415 cluster_P4.SetPtEtaPhiM(1, pJetConstituent->Eta(), pJetConstituent->Phi(), 1);
416 if (LC_P4.DeltaR(cluster_P4) > 0.2)
417 continue;
418 const xAOD::CaloCluster* cl =
419 dynamic_cast<const xAOD::CaloCluster*>(pJetConstituent->rawConstituent());
420 auto it_cps = std::find(cps->begin(), cps->end(), cl);
421 if (it_cps != cps->end()) {
422 int ItsCluster = std::distance(cps->begin(), it_cps);
423 mask[ItsCluster] = true;
424 }
425 }
426 }
427
428 return StatusCode::SUCCESS;
429}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
std::vector< size_t > vec
Handle class for reading from StoreGate.
Handle for requesting thinning for a data object.
StatusCode testPhotons(const char *APP_NAME, bool quiet)
StatusCode testElectrons(const char *APP_NAME, bool quiet)
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
StatusCode particleCluster(std::vector< bool > &mask, const xAOD::IParticle *particle, const xAOD::CaloClusterContainer *cps, bool is_muons, bool is_egamma, bool is_tau) const
SG::ThinningHandleKey< xAOD::CaloClusterContainer > m_TopoClSGKey
virtual StatusCode doThinning() const override
SG::ReadHandleKey< xAOD::IParticleContainer > m_sgKey
SG::ThinningHandleKey< xAOD::CaloClusterContainer > m_CaloClSGKey
StatusCode setClustersMask(std::vector< bool > &mask, const xAOD::IParticle *particle, const xAOD::CaloClusterContainer *cps, bool is_muons, bool is_egamma, bool is_track) const
CaloClusterThinning(const std::string &t, const std::string &n, const IInterface *p)
const_pointer_type ptr()
Dereference the pointer.
const_pointer_type cptr()
Dereference the pointer.
void keep(size_t ndx)
Mark that index ndx in the container should be kept (not thinned away).
Handle for requesting thinning for a data object.
elec/gamma data class.
Definition egamma.h:58
Class providing the definition of the 4-vector interface.
A vector of jet constituents at the scale used during jet finding.
JetConstituentVector getConstituents() const
Return a vector of consituents. The object behaves like vector<const IParticle*>. See JetConstituentV...
Definition Jet_v1.cxx:147
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition TauJet_v3.cxx:96
const Jet * jet() const
double entries
Definition listroot.cxx:49
void select(const xAOD::IParticle *particle, const float coneSize, const xAOD::CaloClusterContainer *clusters, std::vector< bool > &mask)
PhotonContainer_v1 PhotonContainer
Definition of the current "photon container version".
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
TauJet_v3 TauJet
Definition of the current "tau version".
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
Muon_v1 Muon
Reference the current persistent version:
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
TauJetContainer_v3 TauJetContainer
Definition of the current "taujet container version".
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.