ATLAS Offline Software
Loading...
Searching...
No Matches
TrigTauMonitorTruthAlgorithm.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
10
11TrigTauMonitorTruthAlgorithm::TrigTauMonitorTruthAlgorithm(const std::string& name, ISvcLocator* pSvcLocator)
12 : TrigTauMonitorBaseAlgorithm(name, pSvcLocator)
13{}
14
15
18
19 ATH_CHECK( m_truthParticleKey.initialize() );
20
21 return StatusCode::SUCCESS;
22}
23
24
25std::pair<std::vector<std::shared_ptr<xAOD::TruthParticle>>, std::vector<std::shared_ptr<xAOD::TruthParticle>>> TrigTauMonitorTruthAlgorithm::getTruthTaus(const EventContext& ctx, const float threshold) const
26{
27 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_1p;
28 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_3p;
29
30 // Truth Taus distributions
32 if(!truth_cont.isValid()) {
33 ATH_MSG_WARNING("Failed to retrieve truth Taus");
34 return {true_taus_1p, true_taus_3p};
35 }
36
37 static const SG::ConstAccessor<double> acc_ptvis("pt_vis");
38 static const SG::ConstAccessor<double> acc_etavis("eta_vis");
39 static const SG::ConstAccessor<int> acc_ntracks("nTracks");
40 static const SG::ConstAccessor<char> acc_isleptonic("IsLeptonicTau");
41
42 // Fill truth tau containers
43 for(const auto xTruthParticle : *truth_cont) {
44 if(xTruthParticle->isTau()) {
45 ATH_MSG_DEBUG("Tau with status " << xTruthParticle->status() << " and charge " << xTruthParticle->charge());
46
47 // Create a copy of the original TruthParticle, to augment it with tau-specific properties
48 std::shared_ptr xTruthTau = std::make_shared<xAOD::TruthParticle>();
49 xTruthTau->makePrivateStore(*xTruthParticle);
50
51 // Keep only truth taus
52 if(examineTruthTau(xTruthTau).isFailure()) continue;
53
54 // Keep only the hadronic decay mode
55 if(acc_isleptonic(*xTruthTau)) continue;
56
57 float pt = acc_ptvis(*xTruthTau);
58 float eta = acc_etavis(*xTruthTau);
59 ATH_MSG_DEBUG("True Tau visible pt: " << pt << ", eta: " << eta);
60
61 // Keep only truth taus in the barrel region, with a pT > 20 GeV (offline minimum threshold)
62 if(pt < threshold || std::abs(eta) > 2.47) continue;
63
64 int nTracks = acc_ntracks(*xTruthTau);
65 if(nTracks == 1) true_taus_1p.push_back(xTruthTau);
66 else if(nTracks == 3) true_taus_3p.push_back(xTruthTau);
67 }
68 }
69
70 return {true_taus_1p, true_taus_3p};
71}
72
73
74StatusCode TrigTauMonitorTruthAlgorithm::examineTruthTau(const std::shared_ptr<xAOD::TruthParticle>& xTruthTau) const
75{
76 if(!xTruthTau->hasDecayVtx()) return StatusCode::FAILURE;
77 static const SG::Accessor<double> acc_ptvis("pt_vis");
78 static const SG::Accessor<double> acc_etavis("eta_vis");
79 static const SG::Accessor<double> acc_phivis("phi_vis");
80 static const SG::Accessor<double> acc_mvis("mvis");
81 static const SG::Accessor<int> acc_childChargeSum("childChargeSum");
82 static const SG::Accessor<int> acc_ntracks("nTracks");
83 static const SG::Accessor<char> acc_isleptonic("IsLeptonicTau");
84
85 acc_isleptonic(*xTruthTau) = false;
86
87 TLorentzVector VisSumTLV;
88 acc_ptvis(*xTruthTau) = 0.;
89 acc_etavis(*xTruthTau) = 0.;
90 acc_phivis(*xTruthTau) = 0.;
91 acc_mvis(*xTruthTau) = 0.;
92 acc_childChargeSum(*xTruthTau) = 0;
93 acc_ntracks(*xTruthTau) = 0;
94
95 const xAOD::TruthVertex* decayvtx = xTruthTau->decayVtx();
96 if(decayvtx) {
97 const std::size_t nChildren = decayvtx->nOutgoingParticles();
98 for(std::size_t iChild = 0; iChild != nChildren; ++iChild) {
99 const xAOD::TruthParticle* child = decayvtx->outgoingParticle(iChild);
100 if(child) {
101 if(MC::isSMNeutrino(child)) continue;
102 if(!MC::isPhysical(child)) continue;
103 ATH_MSG_DEBUG("Child " << child->pdgId() << ", status " << child->status() << ", charge " << child->charge());
104 if(MC::isSMLepton(child)) acc_isleptonic(*xTruthTau) = true; // Just selects charged SM Leptons as we have already skipped SM neutrinos
105 VisSumTLV += child->p4();
106 acc_childChargeSum(*xTruthTau) += child->charge();
107 acc_ntracks(*xTruthTau) += std::abs(child->charge());
108 }
109 }
110 }
111 acc_ptvis(*xTruthTau) = VisSumTLV.Pt();
112 acc_etavis(*xTruthTau) = VisSumTLV.Eta();
113 acc_phivis(*xTruthTau) = VisSumTLV.Phi();
114 acc_mvis(*xTruthTau) = VisSumTLV.M();
115
116 if(acc_childChargeSum(*xTruthTau) != xTruthTau->charge() || acc_ntracks(*xTruthTau)%2 == 0) {
117 ATH_MSG_WARNING("Strange tau: charge " << acc_childChargeSum(*xTruthTau) << " and " << acc_ntracks(*xTruthTau) << " tracks");
118 const std::size_t nChildren = decayvtx->nOutgoingParticles();
119 for(std::size_t iChild = 0; iChild != nChildren; ++iChild) {
120 const xAOD::TruthParticle * child = decayvtx->outgoingParticle(iChild);
121 if(child) ATH_MSG_WARNING("Child "<< child->pdgId() << ", status "<< child->status() << ", charge "<< child->charge());
122 }
123 }
124
125 return StatusCode::SUCCESS;
126}
127
128
129StatusCode TrigTauMonitorTruthAlgorithm::processEvent(const EventContext& ctx) const
130{
131 // Truth taus
132 auto true_taus = getTruthTaus(ctx, 20.0);
133 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_1p = true_taus.first;
134 std::vector<std::shared_ptr<xAOD::TruthParticle>> true_taus_3p = true_taus.second;
135
136 for(const std::string& trigger : m_triggers) {
137
138 // skip ditau and T&P chains:
139 const TrigTauInfo& info = getTrigInfo(trigger);
140 if( info.isHLTTandP() || info.isHLTDiTau()) continue;
141
142 // Online taus
143 std::vector<const xAOD::TauJet*> hlt_taus = getOnlineTausAll(trigger, true);
144
145 if(!true_taus_1p.empty()) {
146 if(m_do_variable_plots) fillTruthVars(hlt_taus, true_taus_1p, trigger, "1P");
147 if(m_do_efficiency_plots) fillTruthEfficiency(hlt_taus, true_taus_1p, trigger, "1P");
148 }
149
150 if(!true_taus_3p.empty()) {
151 if(m_do_variable_plots) fillTruthVars(hlt_taus, true_taus_3p, trigger, "3P");
152 if(m_do_efficiency_plots) fillTruthEfficiency(hlt_taus, true_taus_3p, trigger, "3P");
153 }
154 }
155
156 return StatusCode::SUCCESS;
157}
158
159
160void 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
161{
162 ATH_MSG_DEBUG("Fill Truth Tau Matching to Offline and Online Taus efficiencies: " << trigger);
163
164 const TrigTauInfo& info = getTrigInfo(trigger);
165
166 auto monGroup = getGroup(trigger+"_Truth_Efficiency_"+nProng);
167
168 // Truth Tau + HLT Tau / Truth Tau
169 auto pt_vis = Monitored::Scalar<float>("pt_vis", 0.0);
170 auto eta_vis = Monitored::Scalar<float>("eta_vis", 0.0);
171 auto phi_vis = Monitored::Scalar<float>("phi_vis", 0.0);
172 auto HLT_truth_match = Monitored::Scalar<bool>("HLT_pass", false);
173 auto HLT_truth_match_highPt = Monitored::Scalar<bool>("HLT_pass_highPt", false);
174
175 bool hlt_fires = m_trigDecTool->isPassed(trigger, TrigDefs::Physics | TrigDefs::allowResurrectedDecision);
176
177 static const SG::AuxElement::ConstAccessor<double> acc_ptvis("pt_vis");
178 static const SG::AuxElement::ConstAccessor<double> acc_etavis("eta_vis");
179 static const SG::AuxElement::ConstAccessor<double> acc_phivis("phi_vis");
180
181 for(const std::shared_ptr<xAOD::TruthParticle>& true_tau : true_taus) {
182 pt_vis = acc_ptvis(*true_tau)/Gaudi::Units::GeV;
183 eta_vis = acc_etavis(*true_tau);
184 phi_vis = acc_phivis(*true_tau);
185
186 HLT_truth_match = matchTruthObjects(true_tau.get(), online_tau_vec, 0.2) && hlt_fires;
187
188 bool is_highPt = false;
189 if(info.isHLTSingleTau()) is_highPt = pt_vis > info.getHLTTauThreshold() + 20.0;
190
191 fill(monGroup, pt_vis, eta_vis, phi_vis, HLT_truth_match);
192
193 if(is_highPt) {
194 HLT_truth_match_highPt = static_cast<bool>(HLT_truth_match);
195 fill(monGroup, eta_vis, phi_vis, HLT_truth_match_highPt);
196 }
197 }
198 ATH_MSG_DEBUG("After fill Truth efficiencies");
199}
200
201
202void 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
203{
204 ATH_MSG_DEBUG("Fill Truth variables: " << trigger);
205
206 auto monGroup = getGroup(trigger+"_TruthVars_"+nProng);
207
208 std::vector<float> ratio, ptvis, etavis, phivis, mvis;
209
210 auto PtRatio = Monitored::Collection("PtRatio", ratio);
211 auto pt_vis = Monitored::Collection("pt_vis", ptvis);
212 auto eta_vis = Monitored::Collection("eta_vis", etavis);
213 auto phi_vis = Monitored::Collection("phi_vis", phivis);
214 auto mass_vis = Monitored::Collection("mass_vis", mvis);
215
216 float matchedRatio = -999, matchedptvis = -999, matchedetavis = 999, matchedphivis = 999, matchedmvis = -999;
217
218 static const SG::AuxElement::ConstAccessor<double> acc_ptvis("pt_vis");
219 static const SG::AuxElement::ConstAccessor<double> acc_etavis("eta_vis");
220 static const SG::AuxElement::ConstAccessor<double> acc_phivis("phi_vis");
221 static const SG::AuxElement::ConstAccessor<double> acc_mvis("mvis");
222
223 // Visible-Truth Tau matching to HLT Tau
224 static const SG::ConstAccessor<double> pt_visAcc("pt_vis");
225 static const SG::ConstAccessor<double> eta_visAcc("eta_vis");
226 static const SG::ConstAccessor<double> phi_visAcc("phi_vis");
227 static const SG::ConstAccessor<double> mvisAcc("mvis");
228 for(auto& HLTTau : ef_taus) {
229 for(const std::shared_ptr<xAOD::TruthParticle>& true_tau : true_taus) {
230 if(matchTruthObjects(true_tau.get(), {HLTTau}, 0.2)) {
231 double pt_vis = acc_ptvis(*true_tau);
232 matchedptvis = pt_vis/Gaudi::Units::GeV;
233 matchedetavis = acc_etavis(*true_tau);
234 matchedphivis = acc_phivis(*true_tau);
235 matchedmvis = acc_mvis(*true_tau);
236 matchedRatio = HLTTau->pt()/pt_vis - 1.;
237 }
238 }
239
240 if(matchedptvis > 0) {
241 ptvis.push_back(matchedptvis);
242 etavis.push_back(matchedetavis);
243 phivis.push_back(matchedphivis);
244 mvis.push_back(matchedmvis);
245 ratio.push_back(matchedRatio);
246 }
247 }
248
249 fill(monGroup, pt_vis, eta_vis, phi_vis, mass_vis, PtRatio);
250
251 ATH_MSG_DEBUG("After fill Truth variables");
252}
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.
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
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
Gaudi::Property< bool > m_do_variable_plots
std::vector< const xAOD::TauJet * > getOnlineTausAll(const std::string &trigger, bool include_0P=true) const
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.