ATLAS Offline Software
Loading...
Searching...
No Matches
PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.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
6
7// local include(s)
11#include "TF1.h"
12
13#ifdef ASGTOOL_ATHENA
14#include "CLHEP/Units/SystemOfUnits.h"
15using CLHEP::GeV;
16#else
17#define GeV 1000
18#endif
19
20#include <cmath>
21#include <fstream>
22#include <set>
23#include <sstream>
24
25using namespace TauAnalysisTools;
26using namespace ADD_CMODE(TauAnalysisTools);
27
28//______________________________________________________________________________
29void ADD_CMODE(TauAnalysisTools)::split(const std::string& sInput, const char cDelim, std::vector<std::string>& vOut)
30{
31 std::stringstream sSS(sInput);
32 std::string sItem;
33 while (std::getline(sSS, sItem, cDelim))
34 vOut.push_back(sItem);
35}
36
37//______________________________________________________________________________
38void ADD_CMODE(TauAnalysisTools)::split(TEnv& rEnv, const std::string& sKey, const char cDelim, std::vector<std::string>& vOut)
39{
40 std::stringstream sSS(rEnv.GetValue(sKey.c_str(),""));
41 std::string sItem;
42 while (std::getline(sSS, sItem, cDelim))
43 vOut.push_back(sItem);
44}
45
46//______________________________________________________________________________
47void ADD_CMODE(TauAnalysisTools)::split(TEnv& rEnv, const std::string& sKey, const char cDelim, std::vector<size_t>& vOut)
48{
49 std::stringstream sSS(rEnv.GetValue(sKey.c_str(),""));
50 std::string sItem;
51 while (std::getline(sSS, sItem, cDelim))
52 vOut.push_back(size_t(stoi(sItem)));
53}
54
55//______________________________________________________________________________
56void ADD_CMODE(TauAnalysisTools)::split(TEnv& rEnv, const std::string& sKey, const char cDelim, std::vector<int>& vOut)
57{
58 std::stringstream sSS(rEnv.GetValue(sKey.c_str(),""));
59 std::string sItem;
60 while (std::getline(sSS, sItem, cDelim))
61 vOut.push_back(stoi(sItem));
62}
63
64//______________________________________________________________________________
65void ADD_CMODE(TauAnalysisTools)::split(TEnv& rEnv, const std::string& sKey, const char cDelim, std::vector<unsigned>& vOut)
66{
67 std::stringstream sSS(rEnv.GetValue(sKey.c_str(),""));
68 std::string sItem;
69 while (std::getline(sSS, sItem, cDelim))
70 vOut.push_back(stoi(sItem));
71}
72
73//______________________________________________________________________________
74void ADD_CMODE(TauAnalysisTools)::split(TEnv& rEnv, const std::string& sKey, const char cDelim, std::vector<float>& vOut)
75{
76 std::stringstream sSS(rEnv.GetValue(sKey.c_str(),""));
77 std::string sItem;
78 while (std::getline(sSS, sItem, cDelim))
79 vOut.push_back(stof(sItem));
80}
81
82//______________________________________________________________________________
83void ADD_CMODE(TauAnalysisTools)::split(TEnv& rEnv, const std::string& sKey, const char cDelim, std::vector<double>& vOut)
84{
85 std::stringstream sSS(rEnv.GetValue(sKey.c_str(),""));
86 std::string sItem;
87 while (std::getline(sSS, sItem, cDelim))
88 vOut.push_back(stod(sItem));
89}
90
91//______________________________________________________________________________
92double ADD_CMODE(TauAnalysisTools)::finalTauPt(const xAOD::TauJet& xTau)
93{
94 // return MVA based tau pt in GeV
95 return xTau.ptFinalCalib()/GeV;
96}
97
98//______________________________________________________________________________
99double ADD_CMODE(TauAnalysisTools)::finalTauEta(const xAOD::TauJet& xTau)
100{
101 // return MVA based tau eta
102 return xTau.etaFinalCalib();
103}
104
105//______________________________________________________________________________
106double ADD_CMODE(TauAnalysisTools)::finalTauAbsEta(const xAOD::TauJet& xTau)
107{
108 // return MVA based absolute tau eta
109 return std::abs(xTau.etaFinalCalib());
110}
111
112//______________________________________________________________________________
113double ADD_CMODE(TauAnalysisTools)::truthVisTauPt(const xAOD::TauJet& xTau)
114{
115 // return truth visible tau Pt in GeV
117
118 // if there is a truth tau return visible pT, otherwise return 0 (getTruth will print an error)
119 static const SG::ConstAccessor<char> accIsHadronicTau ("IsHadronicTau");
120 static const SG::ConstAccessor<double> accPtVis("pt_vis");
121 if (xTruthTau!=nullptr && accIsHadronicTau (*xTruthTau))
122 return (accPtVis(*xTruthTau)/GeV);
123 else
124 return 0.;
125}
126//______________________________________________________________________________
127double ADD_CMODE(TauAnalysisTools)::truthTauAbsEta(const xAOD::TauJet& xTau)
128{
129 // return truth tau absolute eta
131
132 // if there is a truth tau return absolute eta, otherwise return -5 (getTruth will print an error)
133 static const SG::ConstAccessor<char> accIsHadronicTau ("IsHadronicTau");
134 if (xTruthTau!=nullptr && accIsHadronicTau (*xTruthTau))
135 return std::abs(xTruthTau->eta());
136 else
137 return -5.;
138}
139
140//______________________________________________________________________________
141double ADD_CMODE(TauAnalysisTools)::truthDecayMode(const xAOD::TauJet& xTau)
142{
143 // return truth tau decay mode.
144 int iDecayMode = getTruthDecayMode(xTau);
145 return static_cast<double>(iDecayMode);
146}
147
148//______________________________________________________________________________
150{
152
153 static const SG::ConstAccessor<char> accIsHadronicTau ("IsHadronicTau");
154 if (xTruthTau!=nullptr && accIsHadronicTau(*xTruthTau))
155 return getTruthDecayMode(*xTruthTau);
156 else
158}
159
160//______________________________________________________________________________
162{
163 static const SG::ConstAccessor<size_t> accNumCharged ("numCharged");
164 if (!(accNumCharged.isAvailable(xTruthTau)))
165 {
166 // passed truth particle is not a truth tau
168 }
169
170 int iCharged = getNTauDecayParticles(xTruthTau,MC::PIPLUS, true) + getNTauDecayParticles(xTruthTau,MC::KPLUS, true);
171 int iNeutral = getNTauDecayParticles(xTruthTau,MC::PI0, true);
172 if (iCharged == 1)
173 {
174 if (iNeutral == 0) return xAOD::TauJetParameters::DecayMode::Mode_1p0n;
175 if (iNeutral == 1) return xAOD::TauJetParameters::DecayMode::Mode_1p1n;
176 if (iNeutral >= 2) return xAOD::TauJetParameters::DecayMode::Mode_1pXn;
177 }
178 else if (iCharged == 3)
179 {
180 if (iNeutral == 0) return xAOD::TauJetParameters::DecayMode::Mode_3p0n;
181 if (iNeutral >= 1) return xAOD::TauJetParameters::DecayMode::Mode_3pXn;
182 }
183
184 if (iCharged == 2 or iCharged == 4 or iCharged == 5)
186 if (iCharged == 0 or iCharged >=6)
188
189 // if you got here, something should have gone wrong
191}
192
193//______________________________________________________________________________
194int ADD_CMODE(TauAnalysisTools)::getNTauDecayParticles(const xAOD::TruthParticle& xTruthTau, int iPdgId, bool bCompareAbsoluteValues)
195{
196 int iNum = 0;
197 static const SG::ConstAccessor<std::vector<int> > accDecayModeVector("DecayModeVector");
198 if (!accDecayModeVector.isAvailable(xTruthTau))
199 {
200 Warning("TauAnalysisTools::getNTauDecayParticles", "passed truth particle is not a truth tau, return 0");
201 return 0;
202 }
203
204 for(auto iPdgId2 : accDecayModeVector(xTruthTau))
205 if (!bCompareAbsoluteValues)
206 {
207 if (iPdgId2 == iPdgId) iNum++;
208 }
209 else
210 {
211 if (std::abs(iPdgId2) == std::abs(iPdgId)) iNum++;
212 }
213 return iNum;
214}
215
216//______________________________________________________________________________
217bool ADD_CMODE(TauAnalysisTools)::testFileForEOFContainsCharacters(const std::string& sFileName)
218{
219 // returns true if last line in file is empty or the line starts with the
220 // number sign #
221
222 std::ifstream fInputFile;
223 fInputFile.open(sFileName);
224 if(!fInputFile.is_open())
225 return true;
226
227 fInputFile.seekg(-1,fInputFile.end);
228
229 bool bKeepLooping = true;
230 while(bKeepLooping)
231 {
232 char ch;
233 fInputFile.get(ch);
234
235 if(static_cast<int>(fInputFile.tellg()) <= 1)
236 {
237 fInputFile.seekg(0);
238 bKeepLooping = false;
239 }
240 else if(ch == '\n')
241 bKeepLooping = false;
242 else
243 fInputFile.seekg(-2,fInputFile.cur);
244 }
245
246 std::string sLastLine;
247 getline(fInputFile,sLastLine);
248 fInputFile.close();
249
250 return (sLastLine.size() == 0 or sLastLine[0] == '#');
251}
252
253//______________________________________________________________________________
254void ADD_CMODE(TauAnalysisTools)::createPi0Vectors(const xAOD::TauJet* xTau, std::vector<TLorentzVector>& vPi0s)
255{
256 // reset the pi0s
257 vPi0s.clear();
258
259 // Since the PFO links as they come out of reconstruction, only correspond to
260 // calorimeter clusters, whereas we want the consts_pi0 vectors to correspond
261 // to real pi0s, we need to be careful to collect the PFOs correctly to pi0s
262 // for the cases where number of pi0s does not match to the decay mode:
263 size_t iNumPi0PFO = xTau->nPi0PFOs();
264
265 int iDecayMode = -1;
266
267 if (!(xTau->panTauDetail(xAOD::TauJetParameters::PanTauDetails::PanTau_DecayMode, iDecayMode)))
268 {
269 Error("TauAnalysisTools::createPi0Vectors", "Failed to retrieve panTauDetail decay mode.");
270 return;
271 }
272
273 if (iDecayMode == xAOD::TauJetParameters::DecayMode::Mode_1p1n && iNumPi0PFO > 1)
274 {
275 // float fMassPi0 = ParticleConstants::piZeroMassInMeV;
277
278 // combine both photons (with 0 mass from Pantau) to one pi0 vector:
279 const xAOD::PFO* xPfo1 = xTau->pi0PFO(0);
280 const xAOD::PFO* xPfo2 = xTau->pi0PFO(1);
281 vPi0s.push_back(xPfo1->p4() + xPfo2->p4());
282
283 // re-set the mass to one pi0:
284 double dNewMomentum = std::sqrt(vPi0s[0].E() * vPi0s[0].E() - fMassPi0Squared);
285 vPi0s[0].SetPxPyPzE(vPi0s[0].Vect().Unit().Px() * dNewMomentum,
286 vPi0s[0].Vect().Unit().Py() * dNewMomentum,
287 vPi0s[0].Vect().Unit().Pz() * dNewMomentum,
288 vPi0s[0].E());
289 }
290 else if (iDecayMode == xAOD::TauJetParameters::DecayMode::Mode_1pXn && iNumPi0PFO == 1)
291 {
292 // make a single pi0 from a PFO that contains two pi0s:
293 const xAOD::PFO* xPfo = xTau->pi0PFO(0);
294 // add the 2-pi0 vector preliminarily to the pi0vector:
295 vPi0s.push_back(xPfo->p4());
296
297 // re-set the mass back to one pi0:
298 double dNewMomentum = std::sqrt(vPi0s[0].E() / 2 * vPi0s[0].E() / 2 - vPi0s[0].M() / 2. * vPi0s[0].M() / 2.);
299 vPi0s[0].SetVectM(vPi0s[0].Vect() * (dNewMomentum / vPi0s[0].P()), vPi0s[0].M() / 2.);
300
301 // create another pi0 from the same vector:
302 vPi0s.push_back(vPi0s[0]);
303 }
304 else
305 {
306 // if it's not any of the special cases above then just collect the PFOs:
307 for (size_t iPFO = 0; iPFO < iNumPi0PFO; iPFO++)
308 {
309 vPi0s.push_back(xTau->pi0PFO(iPFO)->p4());
310 }
311 }
312}
313
314
315//______________________________________________________________________________
316void ADD_CMODE(TauAnalysisTools)::correctedPi0Vectors(const xAOD::TauJet* xTau, std::vector<TLorentzVector>& correctedPi0s, TLorentzVector& TauP4){
317 //reset the pi0s
318 correctedPi0s.clear();
319
320 int iDecayMode = -1;
321
322 if (!(xTau->panTauDetail(xAOD::TauJetParameters::PanTauDetails::PanTau_DecayMode, iDecayMode)))
323 {
324 Error("TauAnalysisTools::correctedPi0Vectors", "Failed to retrieve panTauDetail decay mode.");
325 return;
326 }
327
328 //Reading in the pi0 vector from createPi0Vectors
329 std::vector<TLorentzVector> vPi0s;
330 createPi0Vectors(xTau,vPi0s);
331
333 //Adding up Pi0 P4s from createPi0Vectors
334 TLorentzVector Sum_vPi0s;
335 for(unsigned int i = 0; i < vPi0s.size() ; i++){
336 Sum_vPi0s += vPi0s[i];
337 }
338
339 //Get sum of the chargedPFO (i.e. tau track) p4
340 TLorentzVector Sum_ChrgPFOP4;
341 for(const xAOD::TauTrack* track : xTau->tracks()) {
342 Sum_ChrgPFOP4 += track->track()->p4();
343 }
344
345 //Get tau FinalCalib P4 (explicitly requiring p4(xAOD::TauJetParameters::TauCalibType::FinalCalib) should be superfluous, as FinalCalib is the default p4)
346 TLorentzVector FinalCalibP4 = xTau->p4();
347
348 //Calculate the difference 3-vector between FinalCalib and Sum of chargedPFOP4
349 double px = FinalCalibP4.Px() - Sum_ChrgPFOP4.Px();
350 double py = FinalCalibP4.Py() - Sum_ChrgPFOP4.Py();
351 double pz = FinalCalibP4.Pz() - Sum_ChrgPFOP4.Pz();
352
353 double p_correctedPi0s = std::sqrt( std::pow(px,2.) + std::pow(py,2.) + std::pow(pz,2.) );
354 double p_vPi0s = Sum_vPi0s.P();
355
356 //Calucate scale factor for the pi0 3-vector momentum
357 double X = p_correctedPi0s/p_vPi0s;
358
359 //Scale the pi0s with X and recalculate the new pi0 energy
360 double px_scaled, py_scaled, pz_scaled, e;
362 for(unsigned int i = 0; i < vPi0s.size() ; i++){
363 px_scaled = vPi0s[i].Px() * X;
364 py_scaled = vPi0s[i].Py() * X;
365 pz_scaled = vPi0s[i].Pz() * X;
366 e = std::sqrt( std::pow(px_scaled,2.) + std::pow(py_scaled,2.) + std::pow(pz_scaled,2.) + std::pow(mPi0,2.) );
367
368 //Append the corrected pi0P4 to correctedPi0s
369 TLorentzVector P4_correctedPi0s;
370 P4_correctedPi0s.SetPxPyPzE(px_scaled,py_scaled,pz_scaled,e);
371 correctedPi0s.push_back(P4_correctedPi0s);
372 }
373 }else{
374 correctedPi0s = std::move(vPi0s);
375 }
376
377 //Correct angles between pi0s for 1pXn decays with 1 cluster
378 if(iDecayMode == xAOD::TauJetParameters::DecayMode::Mode_1pXn && xTau->nPi0PFOs() == 1){
379
380 //Get Function of Delta R between the two Pi0s
381 TF1 DeltaRdist("DeltaRdist", "pol3", 0, 67500);
382 DeltaRdist.SetParameter(0, 0.07924);
383 DeltaRdist.SetParameter(1, -2.078/1000000.);
384 DeltaRdist.SetParameter(2, 2.619/100000000000.);
385 DeltaRdist.SetParameter(3, -1.238/10000000000000000.);
386
387 //Get Sum of pi0 P4.Pt()
388 TLorentzVector SumPi0_P4;
389 for( unsigned int i = 0 ; i < correctedPi0s.size() ; i++){
390 SumPi0_P4 += correctedPi0s[i];
391 }
392
393 float SumPi0_pt = SumPi0_P4.Pt();
394
395 //Get delta R value (mean of true DeltaR distribution)
396 float deltaR;
397 if(SumPi0_pt >= 67500){
398 deltaR = 0.020; // = DeltaRdist.Eval(67500);
399 } else{
400 deltaR = DeltaRdist.Eval(SumPi0_pt);
401 }
402
403 TLorentzVector correctedPi0_0, correctedPi0_1;
404 correctedPi0_0.SetPtEtaPhiM( correctedPi0s[0].Pt()/cos(0.5*deltaR/std::sqrt(2.0)), correctedPi0s[0].Eta()+0.5*deltaR/std::sqrt(2.0), correctedPi0s[0].Phi()+0.5*deltaR/std::sqrt(2.0), correctedPi0s[0].M() );
405 correctedPi0_1.SetPtEtaPhiM( correctedPi0s[1].Pt()/cos(0.5*deltaR/std::sqrt(2.0)), correctedPi0s[1].Eta()-0.5*deltaR/std::sqrt(2.0), correctedPi0s[1].Phi()-0.5*deltaR/std::sqrt(2.0), correctedPi0s[1].M() );
406
407 std::vector<TLorentzVector> AngleCorrectedPi0s;
408 AngleCorrectedPi0s.push_back(correctedPi0_0);
409 AngleCorrectedPi0s.push_back(correctedPi0_1);
410
411 //Reparametrise: Delta R -> mass of pi0 Cluster
412 TLorentzVector PionCluster_angleCorrected = AngleCorrectedPi0s[0]+AngleCorrectedPi0s[1];
413
414 double dNewMomentum = std::sqrt(PionCluster_angleCorrected.E()/2. * PionCluster_angleCorrected.E()/2. - PionCluster_angleCorrected.M() / 2. * PionCluster_angleCorrected.M() / 2.);
415 correctedPi0s[0].SetVectM(PionCluster_angleCorrected.Vect() * (dNewMomentum / PionCluster_angleCorrected.P()), PionCluster_angleCorrected.M() / 2.);
416 correctedPi0s[1] = correctedPi0s[0];
417 }
418
419 //Calculate the new tau P4
420 for(const xAOD::TauTrack* track : xTau->tracks()) {
421 TauP4 += track->track()->p4();
422 }
423
424 for(unsigned int iPi0=0; iPi0 < correctedPi0s.size(); iPi0++) {
425 TauP4 += correctedPi0s[iPi0];
426 }
427
428}
429
430//______________________________________________________________________________
432{
434 static const SG::ConstAccessor< Link_t > accTruthParticleLink("truthParticleLink");
435 if (!accTruthParticleLink.isAvailable(xTau))
436 Error("TauAnalysisTools::getTruthParticleType", "No truth match information available. Please run TauTruthMatchingTool first.");
437
438 const xAOD::TruthParticle* xTruthParticle = xAOD::TauHelpers::getTruthParticle(&xTau);
439 if (xTruthParticle)
440 {
441 if (xTruthParticle->isTau())
442 {
443 static const SG::ConstAccessor<char> accIsHadronicTau("IsHadronicTau");
444 if (static_cast<bool>(accIsHadronicTau(*xTruthParticle)))
445 return TruthHadronicTau;
446 else
447 return TruthLeptonicTau;
448 }
449 if (xTruthParticle->isMuon())
450 return TruthMuon;
451 if (xTruthParticle->isElectron())
452 return TruthElectron;
453 }
454
455 // TODO: use const xAOD::Jet* xTruthJet = xAOD::TauHelpers::getLink<xAOD::Jet>(&xTau, "truthJetLink");
456 // currently it is unavailable as templated class is not in icc file
457 static const SG::ConstAccessor< ElementLink< xAOD::JetContainer > > accTruthJetLink("truthJetLink");
458 const ElementLink< xAOD::JetContainer > lTruthParticleLink = accTruthJetLink(xTau);
459 if (lTruthParticleLink.isValid())
460 return TruthJet;
461
462 return Unknown;
463}
464
466{
467 static const SG::ConstAccessor<char> accIsTruthHadronic("IsTruthHadronic");
468 if (!accIsTruthHadronic.isAvailable(xDiTau))
469 Error("TauAnalysisTools::getTruthParticleType", "No truth match information available. Please run DiTauTruthMatchingTool first");
470
471 TruthMatchedParticleType eTruthMatchedParticleType = Unknown;
472
473 if (accIsTruthHadronic(xDiTau))
474 eTruthMatchedParticleType = TruthHadronicDiTau;
475
476 return eTruthMatchedParticleType;
477}
478
479namespace
480{
481// Recursively search through ancestor chain to find b, c, light hadron
482// origin. Higher-priority classifications found further up the chain override
483// lower ones. Priority: b-hadron (1) > c-hadron (2) > light hadron (3) > none
484// (0). If e.g. a charm hadron came from a b hadron, assign class 1.
485int classifyAncestor(const xAOD::TruthParticle* particle, std::set<const xAOD::TruthParticle *>& visited)
486{
487 if (!particle || visited.count(particle))
488 return 0; // no classification
489 visited.insert(particle);
490
491 // Classify this particle
492 int thisClass = 0;
493
494 if (particle->isBottomHadron())
495 thisClass = 1;
496 else if (particle->isCharmHadron())
497 thisClass = 2;
498 else if (particle->isLightHadron())
499 thisClass = 3;
500
501 // Guard against going all the way back up to the beam
502 if (particle->nParents() == 0)
503 return thisClass;
504
505 // Recurse into parents; ancestors further up override current classification
506 int bestClass = thisClass;
507 const xAOD::TruthParticle *grandparent = particle->parent(0);
508 // Also if nParents > 1 this is a sign that we've gone past the hadron that
509 // produced the tau, so shouldn't recurse
510 if (particle->nParents() == 1)
511 {
512 int ancClass = classifyAncestor(grandparent, visited);
513 // A non-zero ancestor class with higher priority (lower number, but >0) overrides
514 if (ancClass > 0 && (bestClass == 0 || ancClass <= bestClass))
515 bestClass = ancClass;
516 }
517 return bestClass;
518}
519}
520
521int ADD_CMODE(TauAnalysisTools)::tauOrigin(const xAOD::TauJet& xTau)
522{
523 // Guard against missing truth match information
525 static const SG::ConstAccessor< Link_t > accTruthParticleLink("truthParticleLink");
526 if (!accTruthParticleLink.isAvailable(xTau))
527 Error("TauAnalysisTools::tauOrigin", "No truth match information available. Please run TauTruthMatchingTool first.");
528
529 // Loop over truth particles to get truth tau candidate
530 const xAOD::TruthParticle* xTruthCandidate = xAOD::TauHelpers::getTruthParticle(&xTau);
531 // Check if xTruthCandidate has just a single tau parent --> generator
532 // correction, so replace xTruthCandidate with its parent
533 if (xTruthCandidate)
534 {
535 // Keep following tau parents (generator corrections) until we reach a tau
536 // with a non-tau parent. The set stops a self-referential truth record from
537 // looping forever.
538 std::set<const xAOD::TruthParticle *> seen;
539 while (seen.insert(xTruthCandidate).second)
540 {
541 const xAOD::TruthParticle* parent = xTruthCandidate->parent(0);
542 // No recorded parent: the ancestry can't be followed, so no hadron origin can be found
543 if (!parent)
544 return 0;
545 if (parent->pdgId() == xTruthCandidate->pdgId())
546 xTruthCandidate = parent;
547 else
548 break;
549 }
550 }
551 else return -1;
552
553 // Classify the hadron origin of the truth tau from its ancestor chain
554 std::set<const xAOD::TruthParticle *> visited;
555 return classifyAncestor(xTruthCandidate, visited);
556}
557
558std::vector<const xAOD::TauJet*> ADD_CMODE(TauAnalysisTools)::combineTauJetsWithMuonRM(const xAOD::TauJetContainer* taus_std, const xAOD::TauJetContainer* taus_muonRM){
562 // std::string message = "found " + std::to_string(taus_muonRM->size()) + " muon-removal taus";
563 // Info("TauAnalysisTools::getTauJetsWithMuonRM", message.c_str());
564 std::vector<const xAOD::TauJet*> taus_murm_vec(taus_muonRM->begin(), taus_muonRM->end());
565 std::vector<const xAOD::TauJet*> taus_combined;
567 originalTauJetAcc ("originalTauJet");
568 for(const xAOD::TauJet* tau_std : *taus_std){
569 auto replacement_itr = std::find_if(taus_murm_vec.begin(), taus_murm_vec.end(),
570 [&](const xAOD::TauJet* tau_murm){
571 auto link_to_ori_tau = originalTauJetAcc (*tau_murm);
572 if (!link_to_ori_tau.isValid()) { return false; }
573 if (*link_to_ori_tau == tau_std){ return true; }
574 return false;
575 }
576 );
577 if (replacement_itr == taus_murm_vec.end()) { taus_combined.push_back(tau_std); }
578 else {
579 // message = "replacement found at TauJets_MuonRM index " + std::to_string((*replacement_itr)->index()) + " for TauJets index " + std::to_string(tau_std->index());
580 // Info("TauAnalysisTools::getTauJetsWithMuonRM", message.c_str());
581 taus_combined.push_back(*replacement_itr);
582 taus_murm_vec.erase(replacement_itr);
583 // message = std::to_string(taus_murm_vec.size()) + " muon-removal taus left";
584 // Info("TauAnalysisTools::getTauJetsWithMuonRM", message.c_str());
585 }
586 }
587 // Every muon-removal tau should have been used, otherwise there is a problem.
588 assert(taus_murm_vec.empty());
589 return taus_combined;
590}
Scalar deltaR(const MatrixBase< Derived > &vec) const
#define ADD_CMODE(name)
ATLAS-specific HepMC functions.
static Double_t P(Double_t *tt, Double_t *par)
ElementLink< xAOD::TruthParticleContainer > Link_t
A number of constexpr particle constants to avoid hardcoding them directly in various places.
@ Phi
Definition RPCdef.h:8
@ Eta
Definition RPCdef.h:8
if(pathvar)
#define X(x)
Definition SiHitPlots.h:102
Helper class to provide constant type-safe access to aux data.
STL class.
virtual FourMom_t p4() const
The full 4-momentum of the particle.
Definition PFO_v1.cxx:95
int pdgId() const
PDG ID code.
const TruthParticle_v1 * parent(size_t i) const
Retrieve the i-th mother (TruthParticle) of this TruthParticle.
bool isElectron() const
Whether the particle is an electron (or positron).
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
bool isTau() const
Whether the particle is a tau (or antitau).
bool isMuon() const
Whether the particle is a muon (or antimuon).
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition Error.h:16
static const int PI0
static const int KPLUS
static const int PIPLUS
constexpr double piZeroMassInMeV
the mass of the pi zero (in MeV)
constexpr ParticleHypothesis particle[PARTICLEHYPOTHESES]
the array of masses
STL namespace.
const xAOD::TruthParticle * getTruthParticle(const xAOD::IParticle *, bool debug=false)
return the truthParticle associated to the given IParticle (if any)
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
PFO_v1 PFO
Definition of the current "pfo version".
Definition PFO.h:17
TauTrack_v1 TauTrack
Definition of the current version.
Definition TauTrack.h:16
TauJet_v3 TauJet
Definition of the current "tau version".
Definition TauJet.h:17
TruthParticle_v1 TruthParticle
Typedef to implementation.
setBGCode setTAP setLVL2ErrorBits bool
DiTauJet_v1 DiTauJet
Definition of the current version.
Definition DiTauJet.h:17
TauJetContainer_v3 TauJetContainer
Definition of the current "taujet container version".