ATLAS Offline Software
PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 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 
13 using namespace DiTauMassTools;
14 
15 int DiTauMassTools::getFirstBinAboveMax(const std::shared_ptr<TH1F>& hist, double max, double targetVal)
16 {
17  int maxBin = hist->FindBin(max);
18  int targetBin = maxBin;
19  for(int i=maxBin; i<=hist->GetNbinsX(); i++){
20  if(hist->GetBinContent(i)<targetVal){
21  targetBin = i-1;
22  break;
23  }
24  }
25  return targetBin;
26 }
27 
28 int DiTauMassTools::getFirstBinBelowMax(const std::shared_ptr<TH1F>& hist, double max, double targetVal)
29 {
30  int maxBin = hist->FindBin(max);
31  int targetBin = maxBin;
32  for(int i=1; i<=maxBin; i++){
33  if(hist->GetBinContent(i)>=targetVal){
34  targetBin = i;
35  break;
36  }
37  }
38  return targetBin;
39 }
40 
41 double DiTauMassTools::MaxDelPhi(int tau_type, double Pvis, double dRmax_tau)
42 {
43  return dRmax_tau+0*Pvis*tau_type; // hack to avoid warning
44 }
45 
46 double DiTauMassTools::Angle(const TLorentzVector & vec1, const TLorentzVector & vec2) {
47  //SpeedUp (both are equivalent in fact)
48  return acos((vec1.Px()*vec2.Px()+vec1.Py()*vec2.Py()+vec1.Pz()*vec2.Pz())/(vec1.P()*vec2.P()));
49  //return vec1.Angle(vec2.Vect());
50 }
51 
52 //put back phi within -pi, +pi
53 double DiTauMassTools::fixPhiRange (const double & phi)
54 {
55  double phiOut=phi;
56 
57  if (phiOut>0){
58  while (phiOut>TMath::Pi()) {
59  phiOut-=TMath::TwoPi();
60  }
61  }
62 
63  else{
64  while (phiOut<-TMath::Pi()) {
65  phiOut+=TMath::TwoPi();
66  }
67  }
68  return phiOut;
69 }
70 
71 // fast approximate calculation of sin and cos
72 // approximation good to 1 per mill. c^2+s^2=1 strictly exact though
73 // it is like using slightly different values of phi1 and phi2
74 void DiTauMassTools::fastSinCos (const double & phiInput, double & sinPhi, double & cosPhi)
75 {
76  const double fastB=4/TMath::Pi();
77  const double fastC=-4/(TMath::Pi()*TMath::Pi());
78  const double fastP=9./40.;
79  const double fastQ=31./40.;
80  // use normal sin cos if switch off
81 #ifdef NOFASTSINCOS
82  sinPhi=sin(phiInput);
83  cosPhi=cos(phiInput);
84 #else
85 
86 
87  double phi = fixPhiRange(phiInput);
88 
89  // http://devmaster.net/forums/topic/4648-fast-and-accurate-sinecosine/
90  // accurate to 1 per mille
91 
92  // even faster
93  // const double y=fastB*phi+fastC*phi*std::abs(phi);
94  // sinPhi=fastP*(y*std::abs(y)-y)+y;
95  const double y=phi*(fastB+fastC*std::abs(phi));
96  sinPhi=y*(fastP*std::abs(y)+fastQ);
97 
98 
99  //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)
100  // 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
101  cosPhi=sqrt(1-std::pow(sinPhi,2));
102  if (std::abs(phi)>TMath::PiOver2()) cosPhi=-cosPhi;
103 #endif
104 }
105 
106 // return true if cache was uptodate
107 bool DiTauMassTools::updateDouble (const double in, double & out)
108 {
109  if (out==in) return true;
110  out=in;
111  return false;
112 }
113 
114 //CP::CorrectionCode MissingMassToolV2::getLFVMode( const xAOD::IParticle* p1, const xAOD::IParticle* p2, int mmcType1, int mmcType2) {
115 int DiTauMassTools::getLFVMode( const xAOD::IParticle* p1, const xAOD::IParticle* p2, int mmcType1, int mmcType2) {
116 
117  // Check if particles pointers are null
118  if(p1 == nullptr || p2 == nullptr) {
119  Info("DiTauMassTools", "MissingMassTool::getLFVMode() got a nullptr - returning -1");
120  return -1;
121  }
122 
123  // In case we're in LFV calibration, pass the LFV mode to the tool
124  if (mmcType1 == -1) mmcType1 = mmcType(p1);
125  if (mmcType1 < 0) return -1;//return CP::CorrectionCode::Error;
126 
127  if (mmcType2 == -1) mmcType2 = mmcType(p2);
128  if (mmcType2 < 0) return -1;//return CP::CorrectionCode::Error;
129 
130  // we don't use mmcType as it's 0 for both leptons
131  const xAOD::IParticle *p;
132  if(mmcType1 == 8 && mmcType2 == 8) {
133  // both leptonic; find whichever has the highest pT
134  if(p1->pt() > p2->pt() ) {
135  p = p1;
136  } else {
137  p = p2;
138  }
139 
140  } else {
141  // one of them is a lepton, find it
142  if(mmcType1 == 8) {
143  p = p1;
144  } else if(mmcType2 == 8) {
145  p = p2;
146  } else {
147  // if you're here, you've passed 2 taus to the LFV mode.
148  Warning("DiTauMassTools", "Trying to set LFV mode for 2 taus!");
149  return -1;//return CP::CorrectionCode::Error;
150  }
151  }
152 
153  if(!p) return -1;//return CP::CorrectionCode::Error;
154 
155  int LFVMode = -1;
156  if(p->type() == xAOD::Type::Muon) {
157  // mu+tau mode
158  Info("DiTauMassTools", "Setting MMC to mu+tau mode");
159  //m_MMC->SetLFVmode(1);
160  LFVMode = 1;
161  } else {
162  // e+tau mode
163  Info("DiTauMassTools", "Setting MMC to e+tau mode");
164  //m_MMC->SetLFVmode(0);
165  LFVMode = 0;
166  }
167 
168  return LFVMode;
169  //return CP::CorrectionCode::Ok;
170 }
171 
173 {
174  if(part == nullptr) {
175  // idea for fix: pass logger object to this function or whole algorithm that inherited from athena as pointer
176  Info("DiTauMassTools", "MissingMassTool::mmcType() got a nullptr - returning -1");
177  return -1;
178  }
179 
180  xAOD::Type::ObjectType partType=part->type();
181  int aType=-1;
182  if (partType==xAOD::Type::Electron || partType==xAOD::Type::Muon)
183  {
184  aType=8; // PanTau_DecayMode for leptonic taus
185  }
186  else if (partType==xAOD::Type::Tau)
187  {
188  const xAOD::TauJet * aTauJet=dynamic_cast<const xAOD::TauJet*>(part);
189  if (aTauJet==0)
190  {
191  Warning("DiTauMassTools", "MissingMassTool::mmcType() dynamic_cast of TauJet failed");
192  aType=-2;
193  }
194  else
195  {
196  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
197  }
198  }
199  else
200  {
201  Warning("DiTauMassTools", "MissingMassTool::mmcType() unrecognised particle type! Only Electron, Muon, TauJet allowed. If no mistake, please call MissingMassTool::calculate() directly.");
202  aType=-1;
203  }
204 
205  return aType;
206 }
207 //________________________________________________________________________
208 
209 double DiTauMassTools::mT(const TLorentzVector & vec,const TVector2 & met_vec) {
210  double mt=0.0;
211  double dphi=std::abs(TVector2::Phi_mpi_pi(vec.Phi()-met_vec.Phi()));
212  double cphi=1.0-cos(dphi);
213  if(cphi>0.0) mt=sqrt(2.0*vec.Pt()*met_vec.Mod()*cphi);
214  return mt;
215 }
216 
217 //________________________________________________________________________
218 void DiTauMassTools::readInParams(TDirectory* dir, MMCCalibrationSetV2::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) {
219  std::string paramcode;
220  if (aset == MMCCalibrationSetV2::MMC2019) paramcode = "MMC2019MC16";
221  else {
222  Info("DiTauMassTools", "The specified calibration version does not support root file parametrisations");
223  return;
224  }
225  TIter next(dir->GetListOfKeys());
226  TKey* key;
227  while ((key = (TKey*)next())) {
228  TClass *cl = gROOT->GetClass(key->GetClassName());
229  // if there is another subdirectory, go into that dir
230  if (cl->InheritsFrom("TDirectory")) {
231  dir->cd(key->GetName());
232  TDirectory *subdir = gDirectory;
233  readInParams(subdir, aset, lep_numass, lep_angle, lep_ratio, had_angle, had_ratio);
234  dir->cd();
235  }
236  else if (cl->InheritsFrom("TF1") || cl->InheritsFrom("TGraph")) {
237  // get parametrisations and sort them into their corresponding vectors
238  std::string total_path = dir->GetPath();
239  if (total_path.find(paramcode) == std::string::npos) continue;
240  TF1* func = (TF1*)dir->Get( (const char*) key->GetName() );
241  TF1* f = new TF1(*func);
242  if (total_path.find("lep") != std::string::npos)
243  {
244  if (total_path.find("Angle") != std::string::npos){
245  lep_angle.push_back(f);
246  }
247  else if (total_path.find("Ratio") != std::string::npos)
248  {
249  lep_ratio.push_back(f);
250  }
251  else if (total_path.find("Mass") != std::string::npos)
252  {
253  lep_numass.push_back(f);
254  }
255  else
256  {
257  Warning("DiTauMassTools", "Undefined leptonic PDF term in input file.");
258  }
259  }
260  else if (total_path.find("had") != std::string::npos)
261  {
262  if (total_path.find("Angle") != std::string::npos){
263  had_angle.push_back(f);
264  }
265  else if (total_path.find("Ratio") != std::string::npos)
266  {
267  had_ratio.push_back(f);
268  }
269  else
270  {
271  Warning("DiTauMassTools", "Undefined hadronic PDF term in input file.");
272  }
273  }
274  else
275  {
276  Warning("DiTauMassTools", "Undefined decay channel in input file.");
277  }
278  }
279  else {
280  Warning("DiTauMassTools", "Class in input file not recognized.");
281  }
282  }
283 }
LArG4FSStartPointFilter.part
part
Definition: LArG4FSStartPointFilter.py:21
xAOD::TauJetParameters::PanTau_DecayMode
@ PanTau_DecayMode
Definition: TauDefs.h:360
DiTauMassTools::Angle
double Angle(const TLorentzVector &vec1, const TLorentzVector &vec2)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:46
python.CaloRecoConfig.f
f
Definition: CaloRecoConfig.py:127
D3PDMakerTestInstan::vec2
std::vector< D3PDTest::MyVec2 > vec2
Definition: D3PDMakerTestDict.h:14
xAOD::Electron
Electron_v1 Electron
Definition of the current "egamma version".
Definition: Event/xAOD/xAODEgamma/xAODEgamma/Electron.h:17
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
max
#define max(a, b)
Definition: cfImp.cxx:41
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:64
DiTauMassTools::mT
double mT(const TLorentzVector &vec, const TVector2 &met_vec)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:209
DiTauMassTools::readInParams
void readInParams(TDirectory *dir, MMCCalibrationSetV2::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)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:218
ObjectType
ObjectType
Definition: BaseObject.h:11
plotmaker.hist
hist
Definition: plotmaker.py:148
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
HelperFunctions.h
xAOD::TauJet_v3::panTauDetail
bool panTauDetail(TauJetParameters::PanTauDetails panTauDetail, int &value) const
Get and set values of pantau details variables via enum.
Definition: TauJet_v3.cxx:367
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
Phi_mpi_pi
__HOSTDEV__ double Phi_mpi_pi(double)
Definition: GeoRegion.cxx:7
DiTauMassTools::fastSinCos
void fastSinCos(const double &phi, double &sinPhi, double &cosPhi)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:74
DiTauMassTools::updateDouble
bool updateDouble(const double in, double &out)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:107
DiTauMassTools
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:22
DiTauMassTools::MaxDelPhi
double MaxDelPhi(int tau_type, double Pvis, double dRmax_tau)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:41
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
ParseInputs.gDirectory
gDirectory
Definition: Final2012/ParseInputs.py:133
lumiFormat.i
int i
Definition: lumiFormat.py:92
xAOD::TauJet_v3
Class describing a tau jet.
Definition: TauJet_v3.h:41
DiTauMassTools::getLFVMode
int getLFVMode(const xAOD::IParticle *p1, const xAOD::IParticle *p2, int mmcType1, int mmcType2)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:115
DiTauMassTools::mmcType
int mmcType(const xAOD::IParticle *part)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:172
beamspotman.dir
string dir
Definition: beamspotman.py:623
xAOD::IParticle::pt
virtual double pt() const =0
The transverse momentum ( ) of the particle.
DiTauMassTools::fixPhiRange
double fixPhiRange(const double &phi)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:53
Muon
struct TBPatternUnitContext Muon
DiTauMassTools::MMCCalibrationSetV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:36
y
#define y
DiTauMassTools::MMCCalibrationSetV2::MMC2019
@ MMC2019
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:36
xAODType::Tau
@ Tau
The object is a tau (jet)
Definition: ObjectType.h:49
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
python.LumiCalcRecover.subdir
subdir
Definition: LumiCalcRecover.py:25
DiTauMassTools::getFirstBinBelowMax
int getFirstBinBelowMax(const std::shared_ptr< TH1F > &hist, double max, double targetVal)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:28
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:26
DiTauMassTools::getFirstBinAboveMax
int getFirstBinAboveMax(const std::shared_ptr< TH1F > &hist, double max, double targetVal)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/Root/HelperFunctions.cxx:15
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37