ATLAS Offline Software
Loading...
Searching...
No Matches
TauClusterFinder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef XAOD_ATHLYSIS
6
7#include "TauClusterFinder.h"
9
11
12
13TauClusterFinder::TauClusterFinder(const std::string& name) :
14 TauRecToolBase(name) {
15}
16
17
19 const EventContext& /*ctx*/) const {
20 tau.clearClusterLinks();
21
22 if (tau.jet() == nullptr) {
23 ATH_MSG_ERROR("Tau jet link is invalid.");
24 return StatusCode::FAILURE;
25 }
26
27 const xAOD::Jet* jetSeed = tau.jet();
28
29 // Find all the clusters in the JetConstituent
30 std::vector<const xAOD::CaloCluster*> clusterList = getClusterList(*jetSeed);
31
32 for (const xAOD::CaloCluster* cluster : clusterList) {
33 if (cluster == nullptr) {
34 ATH_MSG_WARNING("Find cluster with nullptr, please check the configuration !");
35 continue;
36 }
37 if (inEleRM()){
38 static const SG::ConstAccessor<ElementLink<xAOD::CaloClusterContainer>> acc_originalObject("ERMOriginalCaloCluster");
39 auto original_cluster_link = acc_originalObject(*cluster);
40 if (!original_cluster_link.isValid()){
41 ATH_MSG_ERROR("Original ERM cluster link is not valid");
42 }
43 cluster = *original_cluster_link;
44 }
45
46 // Clusters with negative energy will be thinned, and the elementlinks to these
47 // clusters will not be valid.
48 if (cluster->rawE() <= 0.) continue;
49
51 linkToCluster.toContainedElement(
52 *(static_cast<const xAOD::IParticleContainer*> (cluster->container())),
53 static_cast<const xAOD::IParticle*>(cluster));
54 tau.addClusterLink(linkToCluster);
55 }
56
57 return StatusCode::SUCCESS;
58}
59
60
61
62std::vector<const xAOD::CaloCluster*> TauClusterFinder::getClusterList(const xAOD::Jet& jet) const {
63 std::vector<const xAOD::CaloCluster*> clusterList;
64
65 xAOD::JetConstituentVector constituents = jet.getConstituents();
66 for (const xAOD::JetConstituent* constituent : constituents) {
67 ATH_MSG_DEBUG("JetConstituent: ");
68 ATH_MSG_DEBUG("eta: " << constituent->eta() << " phi: " << constituent->phi() << " e: " << constituent->e());
69
70 if( constituent->type() == xAOD::Type::CaloCluster ) {
71 const xAOD::CaloCluster* cluster = static_cast<const xAOD::CaloCluster*>(constituent->rawConstituent());
72 ATH_MSG_DEBUG("CaloCluster: ");
73 ATH_MSG_DEBUG("eta: " << cluster->eta() << " phi: " << cluster->phi() << " e: " << cluster->e());
74
75 // If jet perfroms the vertex correction, then cluster in Topo jets is in a shallow copy of CaloCalTopoCluster.
76 // Since jets and the shallow copy may not be stored to AOD in R22, these clusters will be invalid with AOD as input.
77 // To fix this issue, we now retrieve the clusters in the original CaloCalTopoCluster.
78 const xAOD::IParticle* originalParticle = xAOD::getOriginalObject(*cluster);
79 if (m_useOrigCluster and originalParticle != nullptr) {
80 clusterList.push_back( static_cast<const xAOD::CaloCluster*>(originalParticle) );
81 }
82 else {
83 clusterList.push_back(cluster);
84 }
85 }
86 else if ( constituent->type() == xAOD::Type::FlowElement ) {
87 const xAOD::FlowElement* fe = static_cast<const xAOD::FlowElement*>( constituent->rawConstituent() );
88
89 if (fe->isCharged()) continue;
90 if (fe->nOtherObjects()!=1){
91 ATH_MSG_WARNING("Neutral PFO has " << std::to_string(fe->nOtherObjects()) << " clusters, expected exactly 1!\n");
92 continue;
93 }
94
95 clusterList.push_back( dynamic_cast<const xAOD::CaloCluster*>(fe->otherObject(0)) );
96 }
97 else {
98 ATH_MSG_WARNING("Seed jet constituent type not supported ! Skip");
99 continue;
100 }
101 }
102
103 for (const xAOD::JetConstituent* constituent : constituents) {
104 // There is only one type in the constituents
105 if (constituent->type() != xAOD::Type::FlowElement) break;
106
107 const xAOD::FlowElement* fe = static_cast<const xAOD::FlowElement*>( constituent->rawConstituent() );
108 if (! fe->isCharged()) continue;
109
110 for (u_int index=0; index<fe->nOtherObjects(); index++){
111 const xAOD::CaloCluster* cluster = dynamic_cast<const xAOD::CaloCluster*>(fe->otherObject(index));
112 // Check it is not duplicate of one in neutral list
113 if ( std::find(clusterList.begin(), clusterList.end(), cluster) == clusterList.end() ) {
114 clusterList.push_back(cluster);
115 }
116 }
117 }
118
119 return clusterList;
120}
121
122#endif
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
Helper class to provide constant type-safe access to aux data.
Gaudi::Property< bool > m_useOrigCluster
virtual StatusCode executeTool(xAOD::TauJet &tau, const EventContext &ctx) const override
Execute - called for each tau candidate.
TauClusterFinder(const std::string &name)
Constructor.
std::vector< const xAOD::CaloCluster * > getClusterList(const xAOD::Jet &jet) const
TauRecToolBase(const std::string &name)
bool inEleRM() const
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
std::size_t nOtherObjects() const
const xAOD::IParticle * otherObject(std::size_t i) const
Class providing the definition of the 4-vector interface.
A vector of jet constituents at the scale used during jet finding.
4-vector of jet constituent at the scale used during jet finding.
Definition index.py:1
@ FlowElement
The object is a track-calo-cluster.
Definition ObjectType.h:52
@ CaloCluster
The object is a calorimeter cluster.
Definition ObjectType.h:39
Jet_v1 Jet
Definition of the current "jet version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
FlowElement_v1 FlowElement
Definition of the current "pfo version".
Definition FlowElement.h:16
const IParticle * getOriginalObject(const IParticle &copy)
This function can be used to conveniently get a pointer back to the original object from which a copy...
TauJet_v3 TauJet
Definition of the current "tau version".
Definition TauJet.h:17
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.