ATLAS Offline Software
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"
14 #include "StoreGate/ReadHandle.h"
20 #include "xAODJet/JetContainer.h"
21 #include "xAODMuon/MuonContainer.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)
40  , m_selectionString("")
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
53 {
54  // Decide which collections need to be checked for ID TrackParticles
55  ATH_MSG_VERBOSE("initialize() ...");
56 
57  if (!m_CaloClSGKey.empty()) {
58  ATH_CHECK(m_CaloClSGKey.initialize(m_streamName));
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()) {
64  ATH_CHECK(m_TopoClSGKey.initialize(m_streamName));
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 
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
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
119  SG::ReadHandle<xAOD::CaloClusterContainer> importedCaloCluster;
120  if (m_run_calo) {
121  importedCaloCluster =
122  SG::ReadHandle<xAOD::CaloClusterContainer>(m_CaloClSGKey, ctx);
123  }
124 
125  // Retrieve CalCaloTopo collection if required
126  SG::ReadHandle<xAOD::CaloClusterContainer> importedTopoCaloCluster;
127  if (m_run_topo) {
128  importedTopoCaloCluster =
129  SG::ReadHandle<xAOD::CaloClusterContainer>(m_TopoClSGKey, ctx);
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) {
159  SG::ThinningHandle<xAOD::CaloClusterContainer> thin(m_CaloClSGKey, ctx);
160  thin.keep(mask);
161  }
162  if (m_run_topo) {
163  SG::ThinningHandle<xAOD::CaloClusterContainer> thin(m_TopoClSGKey, ctx);
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) {
314  SG::ThinningHandle<xAOD::CaloClusterContainer> thin(m_CaloClSGKey, ctx);
315  thin.keep(mask);
316  }
317  if (m_run_topo) {
318  SG::ThinningHandle<xAOD::CaloClusterContainer> thin(m_TopoClSGKey, ctx);
319  thin.keep(topomask);
320  }
321  return StatusCode::SUCCESS;
322 }
323 
326  std::vector<bool>& mask,
327  const xAOD::IParticle* particle,
328  const xAOD::CaloClusterContainer* cps,
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 
367  std::vector<bool>& mask,
368  const xAOD::IParticle* particle,
369  const xAOD::CaloClusterContainer* cps,
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 }
DerivationFramework::CaloClusterThinning::setClustersMask
StatusCode setClustersMask(std::vector< bool > &mask, const xAOD::IParticle *particle, const xAOD::CaloClusterContainer *cps, bool is_muons, bool is_egamma, bool is_track) const
Definition: CaloClusterThinning.cxx:325
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
Trk::ParticleSwitcher::particle
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
Definition: ParticleHypothesis.h:76
xAOD::TauJet_v3::jet
const Jet * jet() const
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
CaloClusterThinning.h
ThinningHandle.h
Handle for requesting thinning for a data object.
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
skel.it
it
Definition: skel.GENtoEVGEN.py:396
testElectrons
StatusCode testElectrons(const char *APP_NAME, bool quiet)
Definition: TrigGlobEffCorrExample4.cxx:75
xAOD::Egamma_v1
Definition: Egamma_v1.h:56
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
xAOD::Jet_v1::getConstituents
JetConstituentVector getConstituents() const
Return a vector of consituents. The object behaves like vector<const IParticle*>. See JetConstituentV...
Definition: Jet_v1.cxx:147
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:41
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
python.utils.AtlRunQueryLookup.mask
string mask
Definition: AtlRunQueryLookup.py:460
SG::ThinningHandle
Handle for requesting thinning for a data object.
Definition: ThinningHandle.h:84
egamma
Definition: egamma.h:58
DerivationFramework::CaloClusterThinning::doThinning
virtual StatusCode doThinning() const override
Definition: CaloClusterThinning.cxx:109
EgammaContainer.h
DerivationFramework::CaloClusterThinning::initialize
virtual StatusCode initialize() override
Definition: CaloClusterThinning.cxx:52
SG::ThinningHandleBase::keep
void keep(size_t ndx)
Mark that index ndx in the container should be kept (not thinned away).
Definition: ThinningHandleBase.cxx:68
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:59
DerivationFramework::CaloClusterThinning::particleCluster
StatusCode particleCluster(std::vector< bool > &mask, const xAOD::IParticle *particle, const xAOD::CaloClusterContainer *cps, bool is_muons, bool is_egamma, bool is_tau) const
Definition: CaloClusterThinning.cxx:366
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ElectronContainer.h
lumiFormat.i
int i
Definition: lumiFormat.py:85
CaloCluster.h
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::TauJet_v3
Class describing a tau jet.
Definition: TauJet_v3.h:41
DerivationFramework::CaloClusterThinning::~CaloClusterThinning
virtual ~CaloClusterThinning()
ClustersInCone.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
TauJetContainer.h
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
DerivationFramework::CaloClusterThinning::CaloClusterThinning
CaloClusterThinning(const std::string &t, const std::string &n, const IInterface *p)
Definition: CaloClusterThinning.cxx:29
DerivationFramework::CaloClusterThinning::finalize
virtual StatusCode finalize() override
Definition: CaloClusterThinning.cxx:96
MuonContainer.h
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
JetContainer.h
xAOD::TauJet_v3::p4
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition: TauJet_v3.cxx:97
DerivationFramework::CaloClusterThinning::m_selectionString
std::string m_selectionString
Definition: CaloClusterThinning.h:57
entries
double entries
Definition: listroot.cxx:49
xAOD::JetConstituentVector
A vector of jet constituents at the scale used during jet finding.
Definition: JetConstituentVector.h:117
testPhotons
StatusCode testPhotons(const char *APP_NAME, bool quiet)
Definition: TrigGlobEffCorrExample4.cxx:178
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
xAOD::TauJetParameters::DetectorAxis
@ DetectorAxis
Definition: TauDefs.h:337
ReadHandle.h
Handle class for reading from StoreGate.
dqBeamSpot.nEntries
int nEntries
Definition: dqBeamSpot.py:73
DerivationFramework::CaloClusterThinning::m_coneSize
float m_coneSize
Definition: CaloClusterThinning.h:58
DerivationFramework::ClustersInCone::select
void select(const xAOD::IParticle *particle, const float coneSize, const xAOD::CaloClusterContainer *clusters, std::vector< bool > &mask)
Definition: ClustersInCone.cxx:14
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
PhotonContainer.h
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.