ATLAS Offline Software
Loading...
Searching...
No Matches
TrigTauMonitorTruthAlgorithm.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#if __GNUC__ >= 16
6// Suppress false-positive warning seen with gcc16.
7# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
8#endif
9
15
16TrigTauMonitorTruthAlgorithm::TrigTauMonitorTruthAlgorithm(const std::string& name, ISvcLocator* pSvcLocator)
17 : TrigTauMonitorBaseAlgorithm(name, pSvcLocator)
18{}
19
20
23
24 ATH_CHECK( m_truthParticleKey.initialize() );
25
26 return StatusCode::SUCCESS;
27}
28
29
30std::pair<std::vector<std::shared_ptr<xAOD::TruthParticle>>, std::vector<std::shared_ptr<xAOD::TruthParticle>>> TrigTauMonitorTruthAlgorithm::getTruthTaus(const EventContext& ctx, const float threshold) const
31{
32 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_1p;
33 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_3p;
34
35 // Truth Taus distributions
37 if(!truth_cont.isValid()) {
38 ATH_MSG_WARNING("Failed to retrieve truth Taus");
39 return {true_taus_1p, true_taus_3p};
40 }
41
42 static const SG::ConstAccessor<double> acc_ptvis("pt_vis");
43 static const SG::ConstAccessor<double> acc_etavis("eta_vis");
44 static const SG::ConstAccessor<int> acc_ntracks("nTracks");
45 static const SG::ConstAccessor<char> acc_isleptonic("IsLeptonicTau");
46
47 // Fill truth tau containers
48 for(const auto xTruthParticle : *truth_cont) {
49 if(xTruthParticle->isTau()) {
50 ATH_MSG_DEBUG("Tau with status " << xTruthParticle->status() << " and charge " << xTruthParticle->charge());
51
52 // Create a copy of the original TruthParticle, to augment it with tau-specific properties
53 std::shared_ptr xTruthTau = std::make_shared<xAOD::TruthParticle>();
54 xTruthTau->makePrivateStore(*xTruthParticle);
55
56 // Keep only truth taus
57 if(examineTruthTau(xTruthTau).isFailure()) continue;
58
59 // Keep only the hadronic decay mode
60 if(acc_isleptonic(*xTruthTau)) continue;
61
62 float pt = acc_ptvis(*xTruthTau);
63 float eta = acc_etavis(*xTruthTau);
64 ATH_MSG_DEBUG("True Tau visible pt: " << pt << ", eta: " << eta);
65
66 // Keep only truth taus in the barrel region, with a pT > 20 GeV (offline minimum threshold)
67 if(pt < threshold || std::abs(eta) > 2.47) continue;
68
69 int nTracks = acc_ntracks(*xTruthTau);
70 if(nTracks == 1) true_taus_1p.push_back(xTruthTau);
71 else if(nTracks == 3) true_taus_3p.push_back(xTruthTau);
72 }
73 }
74
75 return {true_taus_1p, true_taus_3p};
76}
77
78
79StatusCode TrigTauMonitorTruthAlgorithm::examineTruthTau(const std::shared_ptr<xAOD::TruthParticle>& xTruthTau) const
80{
81 if(!xTruthTau->hasDecayVtx()) return StatusCode::FAILURE;
82 static const SG::Accessor<double> acc_ptvis("pt_vis");
83 static const SG::Accessor<double> acc_etavis("eta_vis");
84 static const SG::Accessor<double> acc_phivis("phi_vis");
85 static const SG::Accessor<double> acc_mvis("mvis");
86 static const SG::Accessor<int> acc_childChargeSum("childChargeSum");
87 static const SG::Accessor<int> acc_ntracks("nTracks");
88 static const SG::Accessor<char> acc_isleptonic("IsLeptonicTau");
89
90 acc_isleptonic(*xTruthTau) = false;
91
92 TLorentzVector VisSumTLV;
93 acc_ptvis(*xTruthTau) = 0.;
94 acc_etavis(*xTruthTau) = 0.;
95 acc_phivis(*xTruthTau) = 0.;
96 acc_mvis(*xTruthTau) = 0.;
97 acc_childChargeSum(*xTruthTau) = 0;
98 acc_ntracks(*xTruthTau) = 0;
99
100 const xAOD::TruthVertex* decayvtx = xTruthTau->decayVtx();
101 if(decayvtx) {
102 const std::size_t nChildren = decayvtx->nOutgoingParticles();
103 for(std::size_t iChild = 0; iChild != nChildren; ++iChild) {
104 const xAOD::TruthParticle* child = decayvtx->outgoingParticle(iChild);
105 if(child) {
106 if(MC::isSMNeutrino(child)) continue;
107 if(!MC::isPhysical(child)) continue;
108 ATH_MSG_DEBUG("Child " << child->pdgId() << ", status " << child->status() << ", charge " << child->charge());
109 if(MC::isSMLepton(child)) acc_isleptonic(*xTruthTau) = true; // Just selects charged SM Leptons as we have already skipped SM neutrinos
110 VisSumTLV += child->p4();
111 acc_childChargeSum(*xTruthTau) += child->charge();
112 acc_ntracks(*xTruthTau) += std::abs(child->charge());
113 }
114 }
115 }
116 acc_ptvis(*xTruthTau) = VisSumTLV.Pt();
117 acc_etavis(*xTruthTau) = VisSumTLV.Eta();
118 acc_phivis(*xTruthTau) = VisSumTLV.Phi();
119 acc_mvis(*xTruthTau) = VisSumTLV.M();
120
121 if(acc_childChargeSum(*xTruthTau) != xTruthTau->charge() || acc_ntracks(*xTruthTau)%2 == 0) {
122 ATH_MSG_WARNING("Strange tau: charge " << acc_childChargeSum(*xTruthTau) << " and " << acc_ntracks(*xTruthTau) << " tracks");
123 const std::size_t nChildren = decayvtx->nOutgoingParticles();
124 for(std::size_t iChild = 0; iChild != nChildren; ++iChild) {
125 const xAOD::TruthParticle * child = decayvtx->outgoingParticle(iChild);
126 if(child) ATH_MSG_WARNING("Child "<< child->pdgId() << ", status "<< child->status() << ", charge "<< child->charge());
127 }
128 }
129
130 return StatusCode::SUCCESS;
131}
132
133
134StatusCode TrigTauMonitorTruthAlgorithm::processEvent(const EventContext& ctx) const
135{
136 // Truth taus
137 auto true_taus = getTruthTaus(ctx, 20.0);
138 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_1p = true_taus.first;
139 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_3p = true_taus.second;
140
141 for(const std::string& trigger : m_triggers) {
142
143 // skip ditau and T&P chains:
144 const TrigTauInfo& info = getTrigInfo(trigger);
145 if( info.isHLTTandP() || info.isHLTDiTau()) continue;
146
147 // Online taus
148 std::vector<const xAOD::TauJet*> hlt_taus = getOnlineTausAll(trigger, true, info.isBootstrappedTauTrigger());
149
150 if(!true_taus_1p.empty()) {
151 if(m_do_variable_plots) fillTruthVars(hlt_taus, true_taus_1p, trigger, "1P");
152 if(m_do_efficiency_plots) fillTruthEfficiency(hlt_taus, true_taus_1p, trigger, "1P");
153 }
154
155 if(!true_taus_3p.empty()) {
156 if(m_do_variable_plots) fillTruthVars(hlt_taus, true_taus_3p, trigger, "3P");
157 if(m_do_efficiency_plots) fillTruthEfficiency(hlt_taus, true_taus_3p, trigger, "3P");
158 }
159 }
160
161 return StatusCode::SUCCESS;
162}
163
164
165void TrigTauMonitorTruthAlgorithm::fillTruthEfficiency(const std::vector<const xAOD::TauJet*>& online_tau_vec, const std::vector<std::shared_ptr<xAOD::TruthParticle>>& true_taus, const std::string& trigger, const std::string& nProng) const
166{
167 ATH_MSG_DEBUG("Fill Truth Tau Matching to Offline and Online Taus efficiencies: " << trigger);
168
169 const TrigTauInfo& info = getTrigInfo(trigger);
170
171 auto monGroup = getGroup(trigger+"_Truth_Efficiency_"+nProng);
172
173 // Truth Tau + HLT Tau / Truth Tau
174 auto pt_vis = Monitored::Scalar<float>("pt_vis", 0.0);
175 auto eta_vis = Monitored::Scalar<float>("eta_vis", 0.0);
176 auto phi_vis = Monitored::Scalar<float>("phi_vis", 0.0);
177 auto HLT_truth_match = Monitored::Scalar<bool>("HLT_pass", false);
178 auto HLT_truth_match_highPt = Monitored::Scalar<bool>("HLT_pass_highPt", false);
179
180 bool hlt_fires = m_trigDecTool->isPassed(trigger, TrigDefs::Physics | TrigDefs::allowResurrectedDecision);
181
182 static const SG::ConstAccessor<double> acc_ptvis("pt_vis");
183 static const SG::ConstAccessor<double> acc_etavis("eta_vis");
184 static const SG::ConstAccessor<double> acc_phivis("phi_vis");
185
186 for(const std::shared_ptr<xAOD::TruthParticle>& true_tau : true_taus) {
187 pt_vis = acc_ptvis(*true_tau)/Gaudi::Units::GeV;
188 eta_vis = acc_etavis(*true_tau);
189 phi_vis = acc_phivis(*true_tau);
190
191 HLT_truth_match = matchTruthObjects(true_tau.get(), online_tau_vec, 0.2) && hlt_fires;
192
193 bool is_highPt = false;
194 if(info.isHLTSingleTau()) is_highPt = pt_vis > info.getHLTTauThreshold() + 20.0;
195
196 fill(monGroup, pt_vis, eta_vis, phi_vis, HLT_truth_match);
197
198 if(is_highPt) {
199 HLT_truth_match_highPt = static_cast<bool>(HLT_truth_match);
200 fill(monGroup, eta_vis, phi_vis, HLT_truth_match_highPt);
201 }
202 }
203 ATH_MSG_DEBUG("After fill Truth efficiencies");
204}
205
206
207void TrigTauMonitorTruthAlgorithm::fillTruthVars(const std::vector<const xAOD::TauJet*>& ef_taus, const std::vector<std::shared_ptr<xAOD::TruthParticle>>& true_taus, const std::string& trigger, const std::string& nProng) const
208{
209 ATH_MSG_DEBUG("Fill Truth variables: " << trigger);
210
211 auto monGroup = getGroup(trigger+"_TruthVars_"+nProng);
212
213 std::vector<float> ratio, ptvis, etavis, phivis, mvis;
214
215 auto PtRatio = Monitored::Collection("PtRatio", ratio);
216 auto pt_vis = Monitored::Collection("pt_vis", ptvis);
217 auto eta_vis = Monitored::Collection("eta_vis", etavis);
218 auto phi_vis = Monitored::Collection("phi_vis", phivis);
219 auto mass_vis = Monitored::Collection("mass_vis", mvis);
220
221 float matchedRatio = -999, matchedptvis = -999, matchedetavis = 999, matchedphivis = 999, matchedmvis = -999;
222
223 // Visible-Truth Tau matching to HLT Tau
224 static const SG::ConstAccessor<double> acc_ptvis("pt_vis");
225 static const SG::ConstAccessor<double> acc_etavis("eta_vis");
226 static const SG::ConstAccessor<double> acc_phivis("phi_vis");
227 static const SG::ConstAccessor<double> acc_mvis("mvis");
228
229 for(auto& HLTTau : ef_taus) {
230 for(const std::shared_ptr<xAOD::TruthParticle>& true_tau : true_taus) {
231 if(matchTruthObjects(true_tau.get(), {HLTTau}, 0.2)) {
232 double pt_vis = acc_ptvis(*true_tau);
233 matchedptvis = pt_vis/Gaudi::Units::GeV;
234 matchedetavis = acc_etavis(*true_tau);
235 matchedphivis = acc_phivis(*true_tau);
236 matchedmvis = acc_mvis(*true_tau);
237 matchedRatio = HLTTau->pt()/pt_vis - 1.;
238 }
239 }
240
241 if(matchedptvis > 0) {
242 ptvis.push_back(matchedptvis);
243 etavis.push_back(matchedetavis);
244 phivis.push_back(matchedphivis);
245 mvis.push_back(matchedmvis);
246 ratio.push_back(matchedRatio);
247 }
248 }
249
250 fill(monGroup, pt_vis, eta_vis, phi_vis, mass_vis, PtRatio);
251
252 ATH_MSG_DEBUG("After fill Truth variables");
253}
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Helper class to provide constant type-safe access to aux data.
Helper class to provide type-safe access to aux data.
ATLAS-specific HepMC functions.
const ToolHandle< GenericMonitoringTool > & getGroup(const std::string &name) const
Get a specific monitoring tool from the tool handle array.
PublicToolHandle< Trig::TrigDecisionTool > m_trigDecTool
Tool to tell whether a specific trigger is passed.
Declare a monitored scalar variable.
Helper class to provide type-safe access to aux data.
Helper class to provide constant type-safe access to aux data.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Gaudi::Property< bool > m_do_efficiency_plots
virtual StatusCode initialize() override
initialize
TrigTauMonitorBaseAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
bool matchTruthObjects(const T1 *true_tau, const std::vector< const T2 * > &tau_vec, float threshold) const
Gaudi::Property< std::vector< std::string > > m_triggers
const TrigTauInfo & getTrigInfo(const std::string &trigger) const
std::vector< const xAOD::TauJet * > getOnlineTausAll(const std::string &trigger, bool include_0P=true, bool filter_legs=false) const
Gaudi::Property< bool > m_do_variable_plots
virtual StatusCode processEvent(const EventContext &ctx) const override
void fillTruthEfficiency(const std::vector< const xAOD::TauJet * > &online_tau_vec_all, const std::vector< std::shared_ptr< xAOD::TruthParticle > > &true_taus, const std::string &trigger, const std::string &nProng) const
TrigTauMonitorTruthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleKey
virtual StatusCode initialize() override
initialize
std::pair< std::vector< std::shared_ptr< xAOD::TruthParticle > >, std::vector< std::shared_ptr< xAOD::TruthParticle > > > getTruthTaus(const EventContext &ctx, const float threshold=20.0) const
void fillTruthVars(const std::vector< const xAOD::TauJet * > &tau_vec, const std::vector< std::shared_ptr< xAOD::TruthParticle > > &true_taus, const std::string &trigger, const std::string &nProng) const
StatusCode examineTruthTau(const std::shared_ptr< xAOD::TruthParticle > &xTruthParticle) const
int status() const
Status code.
int pdgId() const
PDG ID code.
double charge() const
Physical charge.
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
size_t nOutgoingParticles() const
Get the number of outgoing particles.
void fill(const ToolHandle< GenericMonitoringTool > &groupHandle, std::vector< std::reference_wrapper< Monitored::IMonitoredVariable > > &&variables) const
Fills a vector of variables to a group by reference.
bool isSMLepton(const T &p)
APID: the fourth generation leptons are not standard model leptons.
bool isSMNeutrino(const T &p)
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
TruthVertex_v1 TruthVertex
Typedef to implementation.
Definition TruthVertex.h:15
TruthParticle_v1 TruthParticle
Typedef to implementation.