ATLAS Offline Software
Loading...
Searching...
No Matches
PhysicsAnalysis/TauID/DiTauMassTools/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// vim: ts=2 sw=2
6
7// if included, do not use fast calculation of sin/cos but built-in functions
8//#define NOFASTSINCOS
9
10// local include(s)
12#include "xAODBase/IParticle.h"
13#include "xAODBase/ObjectType.h"
14#include "xAODTau/TauJet.h"
15
16#include <TKey.h>
17#include <TCollection.h> // for TIter
18#include <TDirectory.h>
19#include <TF1.h>
20#include <TROOT.h> //for gROOT
21
22using namespace DiTauMassTools;
23
24double DiTauMassTools::MaxDelPhi(int tau_type, double Pvis, double dRmax_tau)
25{
26 return dRmax_tau+0*Pvis*tau_type; // hack to avoid warning
27}
28
29//put back phi within -pi, +pi
30double DiTauMassTools::fixPhiRange (const double & phi)
31{
32 double phiOut=phi;
33
34 if (phiOut>0){
35 while (phiOut>TMath::Pi()) {
36 phiOut-=TMath::TwoPi();
37 }
38 }
39
40 else{
41 while (phiOut<-TMath::Pi()) {
42 phiOut+=TMath::TwoPi();
43 }
44 }
45 return phiOut;
46}
47
48// fast approximate calculation of sin and cos
49// approximation good to 1 per mill. c^2+s^2=1 strictly exact though
50// it is like using slightly different values of phi1 and phi2
51void DiTauMassTools::fastSinCos (const double & phiInput, double & sinPhi, double & cosPhi)
52{
53 const double fastB=4/TMath::Pi();
54 const double fastC=-4/(TMath::Pi()*TMath::Pi());
55 const double fastP=9./40.;
56 const double fastQ=31./40.;
57 // use normal sin cos if switch off
58#ifdef NOFASTSINCOS
59 sinPhi=sin(phiInput);
60 cosPhi=cos(phiInput);
61#else
62
63
64 double phi = fixPhiRange(phiInput);
65
66 // http://devmaster.net/forums/topic/4648-fast-and-accurate-sinecosine/
67 // accurate to 1 per mille
68
69 // even faster
70 // const double y=fastB*phi+fastC*phi*std::abs(phi);
71 // sinPhi=fastP*(y*std::abs(y)-y)+y;
72 const double y=phi*(fastB+fastC*std::abs(phi));
73 sinPhi=y*(fastP*std::abs(y)+fastQ);
74
75
76 //note that one could use cos(phi)=sin(phi+pi/2), however then one would not have c^2+s^2=1 (would get it only within 1 per mille)
77 // the choice here is to keep c^2+s^2=1 so everything is as one would compute c and s from a slightly (1 per mille) different angle
78 cosPhi=sqrt(1-std::pow(sinPhi,2));
79 if (std::abs(phi)>TMath::PiOver2()) cosPhi=-cosPhi;
80#endif
81}
82
83// return true if cache was uptodate
84bool DiTauMassTools::updateDouble (const double in, double & out)
85{
86 if (out==in) return true;
87 out=in;
88 return false;
89}
90
91//CP::CorrectionCode MissingMassTool::getLFVMode( const xAOD::IParticle* p1, const xAOD::IParticle* p2, int mmcType1, int mmcType2) {
92int DiTauMassTools::getLFVMode( const xAOD::IParticle* p1, const xAOD::IParticle* p2, int mmcType1, int mmcType2) {
93
94 // Check if particles pointers are null
95 if(p1 == nullptr || p2 == nullptr) {
96 Info("DiTauMassTools", "MissingMassTool::getLFVMode() got a nullptr - returning -1");
97 return -1;
98 }
99
100 // In case we're in LFV calibration, pass the LFV mode to the tool
101 if (mmcType1 == -1) mmcType1 = mmcType(p1);
102 if (mmcType1 < 0) return -1;//return CP::CorrectionCode::Error;
103
104 if (mmcType2 == -1) mmcType2 = mmcType(p2);
105 if (mmcType2 < 0) return -1;//return CP::CorrectionCode::Error;
106
107 // we don't use mmcType as it's 0 for both leptons
108 const xAOD::IParticle *p;
109 if(mmcType1 == 8 && mmcType2 == 8) {
110 // both leptonic; find whichever has the highest pT
111 if(p1->pt() > p2->pt() ) {
112 p = p1;
113 } else {
114 p = p2;
115 }
116
117 } else {
118 // one of them is a lepton, find it
119 if(mmcType1 == 8) {
120 p = p1;
121 } else if(mmcType2 == 8) {
122 p = p2;
123 } else {
124 // if you're here, you've passed 2 taus to the LFV mode.
125 Warning("DiTauMassTools", "Trying to set LFV mode for 2 taus!");
126 return -1;//return CP::CorrectionCode::Error;
127 }
128 }
129
130
131 int LFVMode = -1;
132 if(p->type() == xAOD::Type::Muon) {
133 // mu+tau mode
134 LFVMode = 1;
135 } else {
136 // e+tau mode
137 LFVMode = 0;
138 }
139
140 return LFVMode;
141 //return CP::CorrectionCode::Ok;
142}
143
145{
146 if(part == nullptr) {
147 // idea for fix: pass logger object to this function or whole algorithm that inherited from athena as pointer
148 Info("DiTauMassTools", "MissingMassTool::mmcType() got a nullptr - returning -1");
149 return -1;
150 }
151
152 xAOD::Type::ObjectType partType=part->type();
153 int aType=-1;
154 if (partType==xAOD::Type::Electron || partType==xAOD::Type::Muon)
155 {
156 aType=8; // PanTau_DecayMode for leptonic taus
157 }
158 else if (partType==xAOD::Type::Tau)
159 {
160 const xAOD::TauJet * aTauJet=dynamic_cast<const xAOD::TauJet*>(part);
161 if (aTauJet==0)
162 {
163 Warning("DiTauMassTools", "MissingMassTool::mmcType() dynamic_cast of TauJet failed");
164 aType=-2;
165 }
166 else
167 {
168 aTauJet->panTauDetail(xAOD::TauJetParameters::PanTau_DecayMode, aType); // 0: 1p0n, 1: 1p1n, 2: 1pXn, 3: 3p0n, 4: 3pXn, 5: Other (2p, 4p, 5p), 6: not set (0p, >=6p), 7: error, 8: leptonic
169 }
170 }
171 else
172 {
173 Warning("DiTauMassTools", "MissingMassTool::mmcType() unrecognised particle type! Only Electron, Muon, TauJet allowed. If no mistake, please call MissingMassTool::calculate() directly.");
174 aType=-1;
175 }
176
177 return aType;
178}
179//________________________________________________________________________
180
181void DiTauMassTools::readInParams(TDirectory* dir, MMCCalibrationSet::e aset, std::vector<TF1*>& lep_numass, std::vector<TF1*>& lep_angle, std::vector<TF1*>& lep_ratio, std::vector<TF1*>& had_angle, std::vector<TF1*>& had_ratio) {
182 std::string paramcode;
183 if (aset == MMCCalibrationSet::MMC2019) paramcode = "MMC2019MC16";
184 else if (aset == MMCCalibrationSet::MMC2024) paramcode = "MMC2024MC23";
185 else {
186 Info("DiTauMassTools", "The specified calibration version does not support root file parametrisations");
187 return;
188 }
189 TIter next(dir->GetListOfKeys());
190 TKey* key;
191 while ((key = (TKey*)next())) {
192 TClass *cl = gROOT->GetClass(key->GetClassName());
193 // if there is another subdirectory, go into that dir
194 if (cl->InheritsFrom("TDirectory")) {
195 dir->cd(key->GetName());
196 TDirectory *subdir = gDirectory;
197 readInParams(subdir, aset, lep_numass, lep_angle, lep_ratio, had_angle, had_ratio);
198 dir->cd();
199 }
200 else if (cl->InheritsFrom("TF1") || cl->InheritsFrom("TGraph")) {
201 // get parametrisations and sort them into their corresponding vectors
202 std::string total_path = dir->GetPath();
203 if (total_path.find(paramcode) == std::string::npos) continue;
204 TF1* func = (TF1*)dir->Get( (const char*) key->GetName() );
205 TF1* f = new TF1(*func);
206 if (total_path.find("lep") != std::string::npos)
207 {
208 if (total_path.find("Angle") != std::string::npos){
209 lep_angle.push_back(f);
210 }
211 else if (total_path.find("Ratio") != std::string::npos)
212 {
213 lep_ratio.push_back(f);
214 }
215 else if (total_path.find("Mass") != std::string::npos)
216 {
217 lep_numass.push_back(f);
218 }
219 else
220 {
221 Warning("DiTauMassTools", "Undefined leptonic PDF term in input file.");
222 }
223 }
224 else if (total_path.find("had") != std::string::npos)
225 {
226 if (total_path.find("Angle") != std::string::npos){
227 had_angle.push_back(f);
228 }
229 else if (total_path.find("Ratio") != std::string::npos)
230 {
231 had_ratio.push_back(f);
232 }
233 else
234 {
235 Warning("DiTauMassTools", "Undefined hadronic PDF term in input file.");
236 }
237 }
238 else
239 {
240 Warning("DiTauMassTools", "Undefined decay channel in input file.");
241 }
242 }
243 else {
244 Warning("DiTauMassTools", "Class in input file not recognized.");
245 }
246 }
247}
Scalar phi() const
phi method
#define y
Class providing the definition of the 4-vector interface.
bool panTauDetail(TauJetParameters::PanTauDetails panTauDetail, int &value) const
Get and set values of pantau details variables via enum.
int getLFVMode(const xAOD::IParticle *p1, const xAOD::IParticle *p2, int mmcType1, int mmcType2)
double MaxDelPhi(int tau_type, double Pvis, double dRmax_tau)
void fastSinCos(const double &phi, double &sinPhi, double &cosPhi)
void readInParams(TDirectory *dir, MMCCalibrationSet::e aset, std::vector< TF1 * > &lep_numass, std::vector< TF1 * > &lep_angle, std::vector< TF1 * > &lep_ratio, std::vector< TF1 * > &had_angle, std::vector< TF1 * > &had_ratio)
ObjectType
Type of objects that have a representation in the xAOD EDM.
Definition ObjectType.h:32
@ Muon
The object is a muon.
Definition ObjectType.h:48
@ Electron
The object is an electron.
Definition ObjectType.h:46
@ Tau
The object is a tau (jet).
Definition ObjectType.h:49
TauJet_v3 TauJet
Definition of the current "tau version".
Definition TauJet.h:17