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
22
23#include <algorithm>
24#include <string>
25#include <vector>
26
27// Constructor
29 const std::string& t,
30 const std::string& n,
31 const IInterface* p)
32 : base_class(t, n, p)
33 , m_ntot(0)
34 , m_ntotTopo(0)
35 , m_npass(0)
36 , m_npassTopo(0)
37 , m_run_calo(false)
38 , m_run_topo(false)
40 , m_coneSize(-1.0)
41{
42 declareProperty("SelectionString", m_selectionString);
43 declareProperty("ConeSize", m_coneSize);
44}
45
46// Destructor
48
49// Athena initialize and finalize
50StatusCode
52{
53 // Decide which collections need to be checked for ID TrackParticles
54 ATH_MSG_VERBOSE("initialize() ...");
55
56 if (!m_CaloClSGKey.empty()) {
58 m_run_calo = true;
59 ATH_MSG_INFO("Using " << m_CaloClSGKey.key()
60 << "as the source collection for calo clusters");
61 }
62 if (!m_TopoClSGKey.empty()) {
64 m_run_topo = true;
65 ATH_MSG_INFO("Using " << m_TopoClSGKey.key()
66 << "as the source collection for topo calo clusters");
67 }
68 if (m_CaloClSGKey.empty() && m_TopoClSGKey.empty()) {
70 "No CalCaloTopoCluster or CaloCluster collection provided for thinning.");
71 return StatusCode::FAILURE;
72 }
73
74 if (m_sgKey.empty()) {
75 ATH_MSG_FATAL("No particle collection provided for thinning.");
76 return StatusCode::FAILURE;
77 } else {
79 "Calo clusters associated with objects in "
80 << m_sgKey.key()
81 << " will be retained in this format with the rest being thinned away");
82 ATH_CHECK(m_sgKey.initialize());
83 }
84
85 // Set up the text-parsing machinery for selectiong the photon directly
86 // according to user cuts
87 if (!m_selectionString.empty()) {
88 ATH_CHECK(initializeParser(m_selectionString));
89 }
90
91 return StatusCode::SUCCESS;
92}
93
94StatusCode
96{
97 ATH_MSG_VERBOSE("finalize() ...");
98 ATH_MSG_INFO("Processed " << m_ntot << " clusters, of which " << m_npass
99 << " were retained ");
100 ATH_MSG_INFO("Processed " << m_ntotTopo << " topo clusters, of which "
101 << m_npassTopo << " were retained ");
102 ATH_CHECK(finalizeParser());
103 return StatusCode::SUCCESS;
104}
105
106// The thinning itself
107StatusCode
109{
110
111 bool is_muons = false;
112 bool is_egamma = false;
113 bool is_tau = false;
114 bool is_track = false;
115
116 // Retrieve egCluster collection
118 if (m_run_calo) {
119 importedCaloCluster =
121 }
122
123 // Retrieve CalCaloTopo collection if required
124 SG::ReadHandle<xAOD::CaloClusterContainer> importedTopoCaloCluster;
125 if (m_run_topo) {
126 importedTopoCaloCluster =
128 }
129 // Check if the event contains clusters
130 unsigned int nClusters = 0;
131 if (m_run_calo) {
132 nClusters = importedCaloCluster->size();
133 }
134 unsigned int nTopoClusters = 0;
135 if (m_run_topo) {
136 nTopoClusters = importedTopoCaloCluster->size();
137 }
138 if (nClusters == 0 && nTopoClusters == 0) {
139 return StatusCode::SUCCESS;
140 }
141
142 // Set up a mask with the same entries as the full cluster collection(s)
143 std::vector<bool> mask(nClusters, false), topomask(nTopoClusters, false);
144 m_ntot += nClusters;
145 m_ntotTopo += nTopoClusters;
146
147 // Retrieve particle container
148 SG::ReadHandle<xAOD::IParticleContainer> importedParticlesHandle{ m_sgKey,
149 ctx };
150 const xAOD::IParticleContainer* importedParticles =
151 importedParticlesHandle.ptr();
152
153 // No particles in the input
154 unsigned int nParticles(importedParticles->size());
155 if (nParticles == 0) {
156 if (m_run_calo) {
158 thin.keep(mask);
159 }
160 if (m_run_topo) {
162 thin.keep(topomask);
163 }
164 return StatusCode::SUCCESS;
165 }
166
167 is_egamma = false;
168 is_muons = false;
169 is_track = false;
170
171 // Are we dealing with a compatible collection?
173 dynamic_cast<const xAOD::ElectronContainer*>(importedParticles);
175 dynamic_cast<const xAOD::PhotonContainer*>(importedParticles);
176 if (testElectrons || testPhotons) {
177 is_egamma = true;
178 }
179 const xAOD::MuonContainer* testMuons =
180 dynamic_cast<const xAOD::MuonContainer*>(importedParticles);
181 if (testMuons) {
182 is_muons = true;
183 }
184 const xAOD::TauJetContainer* testTaus =
185 dynamic_cast<const xAOD::TauJetContainer*>(importedParticles);
186 if (testTaus) {
187 is_tau = true;
188 }
189 const xAOD::TrackParticleContainer* testTracks =
190 dynamic_cast<const xAOD::TrackParticleContainer*>(importedParticles);
191 if (testTracks) {
192 is_track = true;
193 }
194
195 if (!(is_egamma || is_muons || is_tau || is_track)) {
196 ATH_MSG_ERROR("This tool only works with Egamma, Muons, Taus and Tracks "
197 << m_sgKey.key() << " is not a compatible collection");
198 return StatusCode::FAILURE;
199 }
200
201 // Selection
202 // Execute the text parsers if requested
203 if (!m_selectionString.empty()) {
204 std::vector<int> entries = m_parser->evaluateAsVector();
205 unsigned int nEntries = entries.size();
206 // check the sizes are compatible
207 if (nParticles != nEntries) {
208 ATH_MSG_ERROR("Sizes incompatible! Are you sure your selection string "
209 "used e-gamma objects??");
210 return StatusCode::FAILURE;
211 }
212 std::vector<const xAOD::IParticle*> particlesToCheck = {};
213 // identify which e-gammas to keep for the thinning check
214 for (unsigned int i = 0; i < nParticles; ++i) {
215 if (static_cast<bool>(entries[i])) {
216 particlesToCheck.push_back((*importedParticles)[i]);
217 }
218 }
220 for (const auto* particle : particlesToCheck) {
221 if (m_run_calo) {
222 // Always keep own particle clusters
223 if (particleCluster(mask,
224 particle,
225 importedCaloCluster.cptr(),
226 is_muons,
227 is_egamma,
228 is_tau) != StatusCode::SUCCESS) {
229 return StatusCode::FAILURE;
230 }
231 if (setClustersMask(mask,
232 particle,
233 importedCaloCluster.cptr(),
234 is_muons,
235 is_egamma,
236 is_track) != StatusCode::SUCCESS) {
237 return StatusCode::FAILURE;
238 }
239 }
240 if (m_run_topo) {
241 if (particleCluster(topomask,
242 particle,
243 importedTopoCaloCluster.cptr(),
244 is_muons,
245 is_egamma,
246 is_tau) != StatusCode::SUCCESS) {
247 return StatusCode::FAILURE;
248 }
249 if (setClustersMask(topomask,
250 particle,
251 importedTopoCaloCluster.cptr(),
252 is_muons,
253 is_egamma,
254 is_track) != StatusCode::SUCCESS) {
255 return StatusCode::FAILURE;
256 }
257 }
258 }
259 } else { // No selection string provided
260 for (const auto* particle : *importedParticles) {
261 if (m_run_calo) {
262 if (particleCluster(mask,
263 particle,
264 importedCaloCluster.cptr(),
265 is_muons,
266 is_egamma,
267 is_tau) != StatusCode::SUCCESS) {
268 return StatusCode::FAILURE;
269 }
270 if (setClustersMask(mask,
271 particle,
272 importedCaloCluster.cptr(),
273 is_muons,
274 is_egamma,
275 is_track) != StatusCode::SUCCESS) {
276 return StatusCode::FAILURE;
277 }
278 }
279 if (m_run_topo) {
280 if (particleCluster(topomask,
281 particle,
282 importedTopoCaloCluster.cptr(),
283 is_muons,
284 is_egamma,
285 is_tau) != StatusCode::SUCCESS) {
286 return StatusCode::FAILURE;
287 }
288 if (setClustersMask(topomask,
289 particle,
290 importedTopoCaloCluster.cptr(),
291 is_muons,
292 is_egamma,
293 is_track) != StatusCode::SUCCESS) {
294 return StatusCode::FAILURE;
295 }
296 }
297 }
298 }
299 //
300 // Count up the mask contents
301 for (unsigned int i = 0; i < nClusters; ++i) {
302 if (mask[i])
303 ++m_npass;
304 }
305 for (unsigned int i = 0; i < nTopoClusters; ++i) {
306 if (topomask[i])
307 ++m_npassTopo;
308 }
309 //
310 // Execute the thinning service based on the mask. Finish.
311 if (m_run_calo) {
313 thin.keep(mask);
314 }
315 if (m_run_topo) {
317 thin.keep(topomask);
318 }
319 return StatusCode::SUCCESS;
320}
321
322StatusCode
324 std::vector<bool>& mask,
325 const xAOD::IParticle* particle,
327 bool is_muons,
328 bool is_egamma,
329 bool is_track) const
330{
331 if (!cps) {
332 ATH_MSG_ERROR("Cluster collection not found");
333 return StatusCode::FAILURE;
334 }
335
336 if (is_egamma) {
337 const xAOD::Egamma* egamma = dynamic_cast<const xAOD::Egamma*>(particle);
338 if (!egamma) {
339 ATH_MSG_ERROR("Egamma cast failed");
340 return StatusCode::FAILURE;
341 }
343 }
344 if (is_muons) {
345 const xAOD::Muon* muon = dynamic_cast<const xAOD::Muon*>(particle);
346 if (!muon) {
347 ATH_MSG_ERROR("Muon cast failed");
348 return StatusCode::FAILURE;
349 }
351 }
352 if (is_track) {
353 const xAOD::TrackParticle* track = dynamic_cast<const xAOD::TrackParticle*>(particle);
354 if (!track) {
355 ATH_MSG_ERROR("Track cast failed");
356 return StatusCode::FAILURE;
357 }
359 }
360 return StatusCode::SUCCESS;
361}
362
363StatusCode
365 std::vector<bool>& mask,
366 const xAOD::IParticle* particle,
368 bool is_muons,
369 bool is_egamma,
370 bool is_tau) const
371{
372 if (!cps) {
373 ATH_MSG_ERROR("Cluster collection not found");
374 return StatusCode::FAILURE;
375 }
376
377 if (is_egamma) {
378 const xAOD::Egamma* egamma = dynamic_cast<const xAOD::Egamma*>(particle);
379 if (!egamma) {
380 ATH_MSG_ERROR("Egamma cast failed");
381 return StatusCode::FAILURE;
382 }
383 auto it = std::find(cps->begin(), cps->end(), egamma->caloCluster());
384 if (it != cps->end()) {
385 int ItsCluster = std::distance(cps->begin(), it);
386 mask[ItsCluster] = true;
387 }
388 }
389
390 if (is_muons) {
391 const xAOD::Muon* muon = dynamic_cast<const xAOD::Muon*>(particle);
392 if (!muon) {
393 ATH_MSG_ERROR("Muon cast failed");
394 return StatusCode::FAILURE;
395 }
396 auto it = std::find(cps->begin(), cps->end(), muon->cluster());
397 if (it != cps->end()) {
398 int ItsCluster = std::distance(cps->begin(), it);
399 mask[ItsCluster] = true;
400 }
401 }
402
403 if (is_tau) {
404 const xAOD::TauJet* tau = dynamic_cast<const xAOD::TauJet*>(particle);
405 if (!tau) {
406 ATH_MSG_ERROR("TauJet cast failed");
407 return StatusCode::FAILURE;
408 }
410 TLorentzVector LC_P4 = tau->p4(xAOD::TauJetParameters::DetectorAxis);
411 for (const auto * pJetConstituent : vec) {
412 TLorentzVector cluster_P4;
413 cluster_P4.SetPtEtaPhiM(1, pJetConstituent->Eta(), pJetConstituent->Phi(), 1);
414 if (LC_P4.DeltaR(cluster_P4) > 0.2)
415 continue;
416 const xAOD::CaloCluster* cl =
417 dynamic_cast<const xAOD::CaloCluster*>(pJetConstituent->rawConstituent());
418 auto it_cps = std::find(cps->begin(), cps->end(), cl);
419 if (it_cps != cps->end()) {
420 int ItsCluster = std::distance(cps->begin(), it_cps);
421 mask[ItsCluster] = true;
422 }
423 }
424 }
425
426 return StatusCode::SUCCESS;
427}
#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
virtual StatusCode doThinning(const EventContext &ctx) const override
SG::ThinningHandleKey< xAOD::CaloClusterContainer > m_TopoClSGKey
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:149
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.