ATLAS Offline Software
Macros | Functions
TrigGlobEffCorrExample3d.cxx File Reference
#include <TFile.h>
#include <TError.h>
#include "AthAnalysisBaseComps/AthAnalysisHelper.h"
#include "POOLRootAccess/TEvent.h"
#include "AsgMessaging/MessageCheck.h"
#include "AsgTools/AnaToolHandle.h"
#include "EgammaAnalysisInterfaces/IAsgElectronEfficiencyCorrectionTool.h"
#include "MuonAnalysisInterfaces/IMuonTriggerScaleFactors.h"
#include "TriggerAnalysisInterfaces/ITrigGlobalEfficiencyCorrectionTool.h"
#include "xAODEventInfo/EventInfo.h"
#include "xAODEgamma/ElectronContainer.h"
#include "xAODMuon/MuonContainer.h"
#include "PATCore/PATCoreEnums.h"
#include "AthContainers/AuxElement.h"
#include "AthContainers/ConstAccessor.h"
#include "AthContainers/Decorator.h"
#include <sstream>
#include <random>
#include <vector>
#include <array>

Go to the source code of this file.

Macros

#define MSGSOURCE   "Example 3d"
 

Functions

int main (int argc, char *argv[])
 

Macro Definition Documentation

◆ MSGSOURCE

#define MSGSOURCE   "Example 3d"

Definition at line 87 of file TrigGlobEffCorrExample3d.cxx.

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

For property 'ElectronEfficiencyTools':

For property 'ElectronScaleFactorTools':

For property 'ListOfLegsPerTool':

For property 'ListOfTagsPerTool':

For property 'ElectronLegsPerTag':

To tag electron(s) as 'MyMedium' and 'MyTight'

To emulate PID selection (90% loose-to-medium/medium-to-tight eff.)

RAII on-the-fly creation of electron CP tools:

<key in map file>, <PID WP>, <iso WP> Single-electron trigger: electrons tagged 'MyTight'

Electron-muon trigger: electrons tagged 'MyTight' or 'MyMedium'

Dielectron trigger: all electrons (tagged or not)

one instance per trigger leg x working point

two instances: 0 -> MC efficiencies, 1 -> SFs

Safer to retrieve the name from the final ToolHandle, it might be prefixed (by the parent tool name) when the handle is copied

For property 'MuonTools':

Listing 'Tight' first as it has higher priority (an electron with both non-zero 'Tight'+'Medium' decorations will then be tagged as 'Tight')

Uniform random run number generation spanning the target dataset. In real life, use the PileupReweightingTool instead!

2016 periods A-L

Get a random run number, and decorate the event info

electron must be above softest trigger threshold (e7 here

muon must be above softest trigger threshold (mu24 here)

Add 'MyMedium' & 'MyTight' decorations to random electrons also count tight electrons above e26_xxx threshold and medium electrons above e7_xxx threshold

Events must contain enough leptons to trigger

single-electron trigger

electron-muon

dielectron

Finally retrieve the global trigger scale factor

Definition at line 91 of file TrigGlobEffCorrExample3d.cxx.

92 {
93  ANA_CHECK_SET_TYPE(bool)
94  const char* filename = nullptr;
95  bool debug = false, cmdline_error = false, toys = false;
96  for(int i=1;i<argc;++i)
97  {
98  if(string(argv[i]) == "--debug") debug = true;
99  else if(string(argv[i]) == "--toys") toys = true;
100  else if(!filename && *argv[i]!='-') filename = argv[i];
101  else cmdline_error = true;
102  }
103  if(!filename || cmdline_error)
104  {
105  Error(MSGSOURCE, "No file name received!");
106  Error(MSGSOURCE, " Usage: %s [--debug] [--toys] [DxAOD file name]", argv[0]);
107  return 1;
108  }
109  #ifdef XAOD_STANDALONE
110  xAOD::Init(MSGSOURCE).ignore();
111  TFile* file = TFile::Open(filename, "READ");
112  if(!file)
113  {
114  Error(MSGSOURCE, "Unable to open file!");
115  return 2;
116  }
119  StatusCode::enableFailure();
120  #else
121  IAppMgrUI* app = POOL::Init();
123  TString file(filename);
124  #endif
125  event.readFrom(file).ignore();
126  Long64_t entries = event.getEntries();
127  Info(MSGSOURCE, "Number of events in the file: %lli", entries);
128 
129  /* ********************************************************************** */
130 
131  Info(MSGSOURCE, "Configuring the electron CP tools");
133  ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronEffTools;
135  ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronSFTools;
137  std::map<std::string,std::string> legsPerTool;
139  std::map<std::string,std::string> tagsPerTool;
141  std::map<std::string,std::string> legsPerTag;
143  static const SG::Decorator<char> dec_medium("MyMedium");
144  static const SG::Decorator<char> dec_tight("MyTight");
146  std::bernoulli_distribution bernoulliPdf(0.9);
147 
149  vector<asg::AnaToolHandle<IAsgElectronEfficiencyCorrectionTool>> factory;
150  enum{ cLEGS, cTAG, cKEY, cPID, cISO };
151  std::vector<std::array<std::string,5> > toolConfigs = {
154  {"e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0", "MyTight",
155  "2016_e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0", "Tight", "GradientLoose"},
157  {"e7_lhmedium_nod0", "MyMedium,MyTight", "2016_e7_lhmedium_nod0", "Medium", ""},
159  {"e17_lhvloose_nod0", "*,MyMedium,MyTight", "2016_e17_lhvloose_nod0", "LooseBLayer", ""},
160  };
161 
162  const char* mapPath = "ElectronEfficiencyCorrection/2015_2017/"
163  "rel21.2/Moriond_February2018_v2/map6.txt";
164  for(auto& cfg : toolConfigs)
165  for(int j=0;j<2;++j)
166  {
167  string name = "AsgElectronEfficiencyCorrectionTool/"
168  + ((j? "ElTrigEff_" : "ElTrigSF_")
169  + std::to_string(factory.size()/2));
170  auto t = factory.emplace(factory.end(), name);
171  t->setProperty("MapFilePath", mapPath).ignore();
172  t->setProperty("TriggerKey", string(j?"":"Eff_") + cfg[cKEY]).ignore();
173  t->setProperty("IdKey", cfg[cPID]).ignore();
174  t->setProperty("IsoKey", cfg[cISO]).ignore();
175 
176  t->setProperty("CorrelationModel", "TOTAL").ignore();
177  t->setProperty("ForceDataType", (int)PATCore::ParticleDataType::Full).ignore();
178  if(t->initialize() != StatusCode::SUCCESS)
179  {
180  Error(MSGSOURCE, "Unable to initialize the electron CP tool <%s>!",
181  t->name().c_str());
182  return 3;
183  }
184  auto& handles = (j? electronSFTools : electronEffTools);
185  handles.push_back(t->getHandle());
188  name = handles[handles.size()-1].name();
189  legsPerTool[name] = cfg[cLEGS];
190  tagsPerTool[name] = cfg[cTAG];
191  if(!j)
192  {
193  for(auto& tag : ::split_comma_delimited(cfg[cTAG]))
194  {
195  if(legsPerTag[tag]=="") legsPerTag[tag] = cfg[cLEGS];
196  else legsPerTag[tag] += "," + cfg[cLEGS];
197  }
198  }
199 
200  }
201 
202  /* ********************************************************************** */
203 
204  Info(MSGSOURCE, "Configuring the muon CP tools");
206  ToolHandleArray<CP::IMuonTriggerScaleFactors> muonTools;
207  asg::AnaToolHandle<CP::IMuonTriggerScaleFactors> muonTool("CP::MuonTriggerScaleFactors/MuonTrigEff");
208  muonTool.setProperty("MuonQuality", "Tight").ignore();
209  muonTool.setProperty("useRel207", false).ignore();
210  if(muonTool.initialize() != StatusCode::SUCCESS)
211  {
212  Error(MSGSOURCE, "Unable to initialize the muon CP tool!");
213  return 3;
214  }
215  muonTools.push_back(muonTool.getHandle());
216 
217  /* ********************************************************************** */
218 
219  Info(MSGSOURCE, "Configuring the global trigger SF tool");
220  asg::AnaToolHandle<ITrigGlobalEfficiencyCorrectionTool> myTool("TrigGlobalEfficiencyCorrectionTool/TrigGlobal");
221  myTool.setProperty("ElectronEfficiencyTools", electronEffTools).ignore();
222  myTool.setProperty("ElectronScaleFactorTools", electronSFTools).ignore();
223  myTool.setProperty("MuonTools", muonTools).ignore();
224  const char* triggers2016 =
225  "e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0"
226  "|| e7_lhmedium_nod0_mu24"
227  "|| 2e17_lhvloose_nod0";
228  myTool.setProperty("TriggerCombination2016", triggers2016).ignore();
231  myTool.setProperty("LeptonTagDecorations", "MyTight,MyMedium").ignore();
232  myTool.setProperty("ListOfLegsPerTool", legsPerTool).ignore();
233  myTool.setProperty("ListOfTagsPerTool", tagsPerTool).ignore();
234  myTool.setProperty("ListOfLegsPerTag", legsPerTag).ignore();
235 
236  if(debug) myTool.setProperty("OutputLevel", MSG::DEBUG).ignore();
237  if(toys) myTool.setProperty("NumberOfToys", 1000).ignore();
238  if(myTool.initialize() != StatusCode::SUCCESS)
239  {
240  Error(MSGSOURCE, "Unable to initialize the TrigGlob tool!");
241  return 3;
242  }
243 
246  const unsigned periodRuns[] = {
248  296939, 300345, 301912, 302737, 303638, 303943, 305291, 307124,
249  305359, 309311, 310015
250  };
251  std::uniform_int_distribution<unsigned> uniformPdf(0,
252  sizeof(periodRuns)/sizeof(*periodRuns) - 1);
253  std::default_random_engine randomEngine;
254 
255  static const SG::ConstAccessor<int> truthType("truthType");
256  static const SG::ConstAccessor<int> truthOrigin("truthOrigin");
257 
258  /* ********************************************************************** */
259 
260  Info(MSGSOURCE, "Starting the event loop");
261  unsigned errors = 0;
262  double nSuitableEvents = 0., sumW = 0.;
263  static const SG::Decorator<unsigned> RandomRunNumberDec("RandomRunNumber");
264  for(Long64_t entry = 0; entry < entries; ++entry)
265  {
266  event.getEntry(entry);
267 
269  const xAOD::EventInfo* eventInfo = nullptr;
270  event.retrieve(eventInfo,"EventInfo").ignore();
271  unsigned runNumber = periodRuns[uniformPdf(randomEngine)];
272  RandomRunNumberDec(*eventInfo) = runNumber;
273 
274  unsigned nTrig_e26 = 0, nTrig_e7 = 0, nTrig_e17 = 0;
275 
276  vector<const xAOD::Electron*> myTriggeringElectrons;
277  const xAOD::ElectronContainer* electrons = nullptr;
278  event.retrieve(electrons,"Electrons").ignore();
279  for(auto electron : *electrons)
280  {
281  if(!electron->caloCluster()) continue;
282  float eta = fabs(electron->caloCluster()->etaBE(2));
283  float pt = electron->pt();
284  if(pt<10e3f || eta>=2.47) continue;
285  if(!truthType.isAvailable(*electron)) continue;
286  if(!truthOrigin.isAvailable(*electron)) continue;
287  int t = truthType(*electron), o = truthOrigin(*electron);
288  if(t!=2 || !(o==10 || (o>=12 && o<=22) || o==43)) continue;
290  if(pt < 7e3f) continue;
291  if(pt >= 18e3f) ++nTrig_e17;
292 
293  myTriggeringElectrons.push_back(electron);
294  }
295 
296  vector<const xAOD::Muon*> myTriggeringMuons;
297  const xAOD::MuonContainer* muons = nullptr;
298  event.retrieve(muons,"Muons").ignore();
299  for(auto muon : *muons)
300  {
301  if(runNumber >= 324320) break; // delete line once all SFs available for 2017
302  float pt = muon->pt();
303  if(pt<10e3f || fabs(muon->eta())>=2.5) continue;
304  auto mt = muon->muonType();
305  if(mt!=xAOD::Muon::Combined && mt!=xAOD::Muon::MuonStandAlone) continue;
306  auto& mtp = *(muon->primaryTrackParticle());
307  if(!truthType.isAvailable(mtp)) continue;
308  if(!truthOrigin.isAvailable(mtp)) continue;
309  int t = truthType(mtp), o = truthOrigin(mtp);
310  if(t!=6 || !(o==10 || (o>=12 && o<=22) || o==43)) continue;
312  if(pt < 25.2e3f) continue;
313 
314  myTriggeringMuons.push_back(muon);
315  }
316 
320  for(auto electron : myTriggeringElectrons)
321  {
322  bool medium = bernoulliPdf(randomEngine);
323  dec_medium(*electron) = medium? 1 : 0;
324  if(medium && electron->pt()>8e3f) ++nTrig_e7;
325  bool tight = medium && bernoulliPdf(randomEngine);
326  dec_tight(*electron) = tight? 1 : 0;
327  if(tight && electron->pt()>27e3f) ++nTrig_e26;
328  }
329 
331  if(nTrig_e26 < 1
332  && (nTrig_e7==0 || myTriggeringMuons.size()==0)
333  && nTrig_e17 < 2)
334  {
335  continue;
336  }
337 
338 
340  double sf = 1.;
341  auto cc = myTool->getEfficiencyScaleFactor(myTriggeringElectrons,
342  myTriggeringMuons, sf);
344  {
345  nSuitableEvents += 1;
346  sumW += sf;
347  }
348  else
349  {
350  Warning(MSGSOURCE, "Scale factor evaluation failed");
351  ++errors;
352  }
353  if(errors>10)
354  {
355  Error(MSGSOURCE, "Too many errors reported!");
356  break;
357  }
358  }
359  Info(MSGSOURCE, "Average scale factor: %f (over %ld events)",
360  sumW / nSuitableEvents, long(nSuitableEvents));
361  #ifndef XAOD_STANDALONE
362  ANA_CHECK(app->finalize())
363  #endif
364  return errors? 4 : 0;
365 }
store
StoreGateSvc * store
Definition: fbtTestBasics.cxx:69
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
asg::AnaToolHandle< CP::IMuonTriggerScaleFactors >
MSGSOURCE
#define MSGSOURCE
Definition: TrigGlobEffCorrExample3d.cxx:86
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
test_pyathena.pt
pt
Definition: test_pyathena.py:11
ANA_CHECK
#define ANA_CHECK(EXP)
check whether the given expression was successful
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:324
SG::ConstAccessor< int >
LArCellConditions.argv
argv
Definition: LArCellConditions.py:112
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
xAOD::TEvent::kClassAccess
@ kClassAccess
Access auxiliary data using the aux containers.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:97
ZDCMsg::Info
@ Info
Definition: ZDCMsg.h:20
POOL::Init
IAppMgrUI * Init(const char *options="POOLRootAccess/basic.opts")
Bootstraps (creates and configures) the Gaudi Application with the provided options file.
Definition: PhysicsAnalysis/POOLRootAccess/src/TEvent.cxx:29
POOL::TEvent::kClassAccess
@ kClassAccess
Definition: PhysicsAnalysis/POOLRootAccess/POOLRootAccess/TEvent.h:45
PATCore::ParticleDataType::Full
@ Full
Definition: PATCoreEnums.h:22
DiTauMassTools::ignore
void ignore(T &&)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:54
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
SG::Decorator< char >
lumiFormat.i
int i
Definition: lumiFormat.py:92
file
TFile * file
Definition: tile_monitor.h:29
DQHistogramMergeRegExp.argc
argc
Definition: DQHistogramMergeRegExp.py:20
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
Trk::Combined
@ Combined
Definition: TrackSummaryTool.h:32
mergePhysValFiles.errors
list errors
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:43
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
POOL::TEvent
Definition: PhysicsAnalysis/POOLRootAccess/POOLRootAccess/TEvent.h:39
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
debug
const bool debug
Definition: MakeUncertaintyPlots.cxx:53
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
WriteCaloSwCorrections.cfg
cfg
Definition: WriteCaloSwCorrections.py:23
xAOD::EventInfo_v1
Class describing the basic event information.
Definition: EventInfo_v1.h:43
DeMoAtlasDataLoss.runNumber
string runNumber
Definition: DeMoAtlasDataLoss.py:64
CP::CorrectionCode::Ok
@ Ok
The correction was done successfully.
Definition: CorrectionCode.h:38
xAOD::TStore
A relatively simple transient store for objects created in analysis.
Definition: TStore.h:44
mapkey::sf
@ sf
Definition: TElectronEfficiencyCorrectionTool.cxx:38
ANA_CHECK_SET_TYPE
#define ANA_CHECK_SET_TYPE(TYPE)
set the type for ANA_CHECK to report failures
Definition: Control/AthToolSupport/AsgMessaging/AsgMessaging/MessageCheck.h:314
DEBUG
#define DEBUG
Definition: page_access.h:11
xAOD::EgammaParameters::electron
@ electron
Definition: EgammaEnums.h:18
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:24
entries
double entries
Definition: listroot.cxx:49
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
CaloCondBlobAlgs_fillNoiseFromASCII.tag
string tag
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:24
InDetDD::electrons
@ electrons
Definition: InDetDD_Defs.h:17
xAOD::TEvent
Tool for accessing xAOD files outside of Athena.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:81
python.handimod.cc
int cc
Definition: handimod.py:523
xAOD::Init
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition: Init.cxx:31