ATLAS Offline Software
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 
11 TrigTauMonitorTruthAlgorithm::TrigTauMonitorTruthAlgorithm(const std::string& name, ISvcLocator* pSvcLocator)
12  : TrigTauMonitorBaseAlgorithm(name, pSvcLocator)
13 {}
14 
15 
18 
20 
21  return StatusCode::SUCCESS;
22 }
23 
24 
25 std::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 
74 StatusCode 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 
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 
160 void 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 
202 void 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 }
TrigTauMonitorTruthAlgorithm::TrigTauMonitorTruthAlgorithm
TrigTauMonitorTruthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Definition: TrigTauMonitorTruthAlgorithm.cxx:11
xAOD::TruthVertex_v1::nOutgoingParticles
size_t nOutgoingParticles() const
Get the number of outgoing particles.
python.TIDAMonTool.monGroup
def monGroup(analysis_chain)
Definition: TIDAMonTool.py:319
GeV
#define GeV
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:17
AthMonitorAlgorithm::m_trigDecTool
PublicToolHandle< Trig::TrigDecisionTool > m_trigDecTool
Tool to tell whether a specific trigger is passed.
Definition: AthMonitorAlgorithm.h:340
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:68
TrigTauMonitorBaseAlgorithm::initialize
virtual StatusCode initialize() override
initialize
Definition: TrigTauMonitorBaseAlgorithm.cxx:17
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
SG::ReadHandle< xAOD::TruthParticleContainer >
test_pyathena.pt
pt
Definition: test_pyathena.py:11
TrigDecisionTool.h
SG::ConstAccessor< double >
TrigTauMonitorBaseAlgorithm::m_do_variable_plots
Gaudi::Property< bool > m_do_variable_plots
Definition: TrigTauMonitorBaseAlgorithm.h:47
TrigTauMonitorTruthAlgorithm.h
isSMLepton
bool isSMLepton(const T &p)
APID: the fourth generation leptons are not standard model leptons.
Definition: AtlasPID.h:194
Monitored::Collection
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
Definition: MonitoredCollection.h:38
MC::isPhysical
bool isPhysical(const T &p)
Identify if the particle is physical, i.e. is stable or decayed.
Definition: HepMCHelpers.h:51
TrigTauMonitorTruthAlgorithm::examineTruthTau
StatusCode examineTruthTau(const std::shared_ptr< xAOD::TruthParticle > &xTruthParticle) const
Definition: TrigTauMonitorTruthAlgorithm.cxx:74
TrigTauMonitorBaseAlgorithm::getOnlineTausAll
std::vector< const xAOD::TauJet * > getOnlineTausAll(const std::string &trigger, bool include_0P=true) const
Definition: TrigTauMonitorBaseAlgorithm.cxx:57
xAOD::TruthParticle_v1::hasDecayVtx
bool hasDecayVtx() const
Check for a decay vertex on this particle.
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:37
TrigTauMonitorBaseAlgorithm::matchTruthObjects
bool matchTruthObjects(const T1 *true_tau, const std::vector< const T2 * > &tau_vec, float threshold) const
Definition: TrigTauMonitorBaseAlgorithm.h:101
TrigTauMonitorTruthAlgorithm::fillTruthEfficiency
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
Definition: TrigTauMonitorTruthAlgorithm.cxx:160
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
AthMonitorAlgorithm::fill
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.
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
xAOD::TruthParticle_v1::decayVtx
const TruthVertex_v1 * decayVtx() const
The decay vertex of this particle.
xAOD::TruthVertex_v1
Class describing a truth vertex in the MC record.
Definition: TruthVertex_v1.h:37
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
TrigTauMonitorTruthAlgorithm::initialize
virtual StatusCode initialize() override
initialize
Definition: TrigTauMonitorTruthAlgorithm.cxx:16
threshold
Definition: chainparser.cxx:74
TrigTauMonitorBaseAlgorithm
Definition: TrigTauMonitorBaseAlgorithm.h:24
TrigTauMonitorBaseAlgorithm::m_do_efficiency_plots
Gaudi::Property< bool > m_do_efficiency_plots
Definition: TrigTauMonitorBaseAlgorithm.h:46
TrigTauInfo
Definition: TrigTauInfo.h:14
xAOD::TruthParticle_v1::status
int status() const
Status code.
TrigTauMonitorTruthAlgorithm::getTruthTaus
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
Definition: TrigTauMonitorTruthAlgorithm.cxx:25
python.compareTCTs.ratio
ratio
Definition: compareTCTs.py:294
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
isSMNeutrino
bool isSMNeutrino(const T &p)
Definition: AtlasPID.h:215
TrigTauMonitorBaseAlgorithm::m_triggers
Gaudi::Property< std::vector< std::string > > m_triggers
Definition: TrigTauMonitorBaseAlgorithm.h:38
TrigTauMonitorBaseAlgorithm::getTrigInfo
const TrigTauInfo & getTrigInfo(const std::string &trigger) const
Definition: TrigTauMonitorBaseAlgorithm.h:51
xAOD::TruthParticle_v1::p4
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
Definition: TruthParticle_v1.cxx:191
ConstAccessor.h
Helper class to provide constant type-safe access to aux data.
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
xAOD::TruthParticle_v1::pdgId
int pdgId() const
PDG ID code.
TrigTauMonitorTruthAlgorithm::processEvent
virtual StatusCode processEvent(const EventContext &ctx) const override
Definition: TrigTauMonitorTruthAlgorithm.cxx:129
TrigTauMonitorTruthAlgorithm::fillTruthVars
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
Definition: TrigTauMonitorTruthAlgorithm.cxx:202
Decorator.h
Helper class to provide type-safe access to aux data.
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
xAOD::TruthVertex_v1::outgoingParticle
const TruthParticle_v1 * outgoingParticle(size_t index) const
Get one of the outgoing particles.
Definition: TruthVertex_v1.cxx:120
AthMonitorAlgorithm::getGroup
const ToolHandle< GenericMonitoringTool > & getGroup(const std::string &name) const
Get a specific monitoring tool from the tool handle array.
Definition: AthMonitorAlgorithm.cxx:164
xAOD::TruthParticle_v1::charge
double charge() const
Physical charge.
HepMCHelpers.h
TrigTauMonitorTruthAlgorithm::m_truthParticleKey
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleKey
Definition: TrigTauMonitorTruthAlgorithm.h:32