ATLAS Offline Software
Macros | Functions
TrigGlobEffCorrExample3e.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 3e"
 

Functions

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

Macro Definition Documentation

◆ MSGSOURCE

#define MSGSOURCE   "Example 3e"

Definition at line 85 of file TrigGlobEffCorrExample3e.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 electrons according to the PID criteria they fulfil

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: only electrons tagged 'PID2' (TightLH+iso)

Electron-muon trigger: electrons tagged 'PID2' or 'PID1' (MediumLH)

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':

Special character '?' indicates that the decorated value is to be suffixed to the name (=> 'PID1' for medium, 'PID2' for 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 'PID' decorations to random electrons also count 'Tight' electrons above e26_xxx threshold and 'Medium' electrons above e7_xxx threshold

Set decorated value to 2 for TightLH+iso or 1 for MediumLH

Events must contain enough leptons to trigger

single-electron trigger

electron-muon

dielectron

Finally retrieve the global trigger scale factor

Definition at line 89 of file TrigGlobEffCorrExample3e.cxx.

90 {
91  ANA_CHECK_SET_TYPE(bool)
92  const char* filename = nullptr;
93  bool debug = false, cmdline_error = false, toys = false;
94  for(int i=1;i<argc;++i)
95  {
96  if(string(argv[i]) == "--debug") debug = true;
97  else if(string(argv[i]) == "--toys") toys = true;
98  else if(!filename && *argv[i]!='-') filename = argv[i];
99  else cmdline_error = true;
100  }
101  if(!filename || cmdline_error)
102  {
103  Error(MSGSOURCE, "No file name received!");
104  Error(MSGSOURCE, " Usage: %s [--debug] [--toys] [DxAOD file name]", argv[0]);
105  return 1;
106  }
107  #ifdef XAOD_STANDALONE
108  xAOD::Init(MSGSOURCE).ignore();
109  TFile* file = TFile::Open(filename, "READ");
110  if(!file)
111  {
112  Error(MSGSOURCE, "Unable to open file!");
113  return 2;
114  }
117  StatusCode::enableFailure();
118  #else
119  IAppMgrUI* app = POOL::Init();
121  TString file(filename);
122  #endif
123  event.readFrom(file).ignore();
124  Long64_t entries = event.getEntries();
125  Info(MSGSOURCE, "Number of events in the file: %lli", entries);
126 
127  /* ********************************************************************** */
128 
129  Info(MSGSOURCE, "Configuring the electron CP tools");
131  ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronEffTools;
133  ToolHandleArray<IAsgElectronEfficiencyCorrectionTool> electronSFTools;
135  std::map<std::string,std::string> legsPerTool;
137  std::map<std::string,std::string> tagsPerTool;
139  std::map<std::string,std::string> legsPerTag;
141  static const SG::Decorator<char> dec_pid("PID");
143  std::bernoulli_distribution bernoulliPdf(0.9);
144 
146  vector<asg::AnaToolHandle<IAsgElectronEfficiencyCorrectionTool>> factory;
147  enum{ cLEGS, cTAG, cKEY, cPID, cISO };
148  std::vector<std::array<std::string,5> > toolConfigs = {
151  {"e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0", "PID2",
152  "2016_e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0", "Tight", "GradientLoose"},
154  {"e7_lhmedium_nod0", "PID1,PID2", "2016_e7_lhmedium_nod0", "Medium", ""},
156  {"e17_lhvloose_nod0", "*,PID1,PID2", "2016_e17_lhvloose_nod0", "LooseBLayer", ""},
157  };
158 
159  const char* mapPath = "ElectronEfficiencyCorrection/2015_2017/"
160  "rel21.2/Moriond_February2018_v2/map6.txt";
161  for(auto& cfg : toolConfigs)
162  for(int j=0;j<2;++j)
163  {
164  string name = "AsgElectronEfficiencyCorrectionTool/"
165  + ((j? "ElTrigEff_" : "ElTrigSF_")
166  + std::to_string(factory.size()/2));
167  auto t = factory.emplace(factory.end(), name);
168  t->setProperty("MapFilePath", mapPath).ignore();
169  t->setProperty("TriggerKey", string(j?"":"Eff_") + cfg[cKEY]).ignore();
170  t->setProperty("IdKey", cfg[cPID]).ignore();
171  t->setProperty("IsoKey", cfg[cISO]).ignore();
172 
173  t->setProperty("CorrelationModel", "TOTAL").ignore();
174  t->setProperty("ForceDataType", (int)PATCore::ParticleDataType::Full).ignore();
175  if(t->initialize() != StatusCode::SUCCESS)
176  {
177  Error(MSGSOURCE, "Unable to initialize the electron CP tool <%s>!",
178  t->name().c_str());
179  return 3;
180  }
181  auto& handles = (j? electronSFTools : electronEffTools);
182  handles.push_back(t->getHandle());
185  name = handles[handles.size()-1].name();
186  legsPerTool[name] = cfg[cLEGS];
187  tagsPerTool[name] = cfg[cTAG];
188  if(!j)
189  {
190  for(auto& tag : ::split_comma_delimited(cfg[cTAG]))
191  {
192  if(legsPerTag[tag]=="") legsPerTag[tag] = cfg[cLEGS];
193  else legsPerTag[tag] += "," + cfg[cLEGS];
194  }
195  }
196 
197  }
198 
199  /* ********************************************************************** */
200 
201  Info(MSGSOURCE, "Configuring the muon CP tools");
203  ToolHandleArray<CP::IMuonTriggerScaleFactors> muonTools;
204  asg::AnaToolHandle<CP::IMuonTriggerScaleFactors> muonTool("CP::MuonTriggerScaleFactors/MuonTrigEff");
205  muonTool.setProperty("MuonQuality", "Tight").ignore();
206  muonTool.setProperty("useRel207", false).ignore();
207  if(muonTool.initialize() != StatusCode::SUCCESS)
208  {
209  Error(MSGSOURCE, "Unable to initialize the muon CP tool!");
210  return 3;
211  }
212  muonTools.push_back(muonTool.getHandle());
213 
214  /* ********************************************************************** */
215 
216  Info(MSGSOURCE, "Configuring the global trigger SF tool");
217  asg::AnaToolHandle<ITrigGlobalEfficiencyCorrectionTool> myTool("TrigGlobalEfficiencyCorrectionTool/TrigGlobal");
218  myTool.setProperty("ElectronEfficiencyTools", electronEffTools).ignore();
219  myTool.setProperty("ElectronScaleFactorTools", electronSFTools).ignore();
220  myTool.setProperty("MuonTools", muonTools).ignore();
221  const char* triggers2016 =
222  "e26_lhtight_nod0_ivarloose_OR_e60_lhmedium_nod0_OR_e140_lhloose_nod0"
223  "|| e7_lhmedium_nod0_mu24"
224  "|| 2e17_lhvloose_nod0";
225  myTool.setProperty("TriggerCombination2016", triggers2016).ignore();
228  myTool.setProperty("LeptonTagDecorations", "PID?").ignore();
229  myTool.setProperty("ListOfLegsPerTool", legsPerTool).ignore();
230  myTool.setProperty("ListOfTagsPerTool", tagsPerTool).ignore();
231  myTool.setProperty("ListOfLegsPerTag", legsPerTag).ignore();
232 
233  if(debug) myTool.setProperty("OutputLevel", MSG::DEBUG).ignore();
234  if(toys) myTool.setProperty("NumberOfToys", 1000).ignore();
235  if(myTool.initialize() != StatusCode::SUCCESS)
236  {
237  Error(MSGSOURCE, "Unable to initialize the TrigGlob tool!");
238  return 3;
239  }
240 
243  const unsigned periodRuns[] = {
245  296939, 300345, 301912, 302737, 303638, 303943, 305291, 307124,
246  305359, 309311, 310015
247  };
248  std::uniform_int_distribution<unsigned> uniformPdf(0,
249  sizeof(periodRuns)/sizeof(*periodRuns) - 1);
250  std::default_random_engine randomEngine;
251 
252  static const SG::ConstAccessor<int> truthType("truthType");
253  static const SG::ConstAccessor<int> truthOrigin("truthOrigin");
254 
255  /* ********************************************************************** */
256 
257  Info(MSGSOURCE, "Starting the event loop");
258  unsigned errors = 0;
259  double nSuitableEvents = 0., sumW = 0.;
260  static const SG::Decorator<unsigned> RandomRunNumberDec("RandomRunNumber");
261  for(Long64_t entry = 0; entry < entries; ++entry)
262  {
263  event.getEntry(entry);
264 
266  const xAOD::EventInfo* eventInfo = nullptr;
267  event.retrieve(eventInfo,"EventInfo").ignore();
268  unsigned runNumber = periodRuns[uniformPdf(randomEngine)];
269  RandomRunNumberDec(*eventInfo) = runNumber;
270 
271  unsigned nTrig_e26 = 0, nTrig_e7 = 0, nTrig_e17 = 0;
272 
273  vector<const xAOD::Electron*> myTriggeringElectrons;
274  const xAOD::ElectronContainer* electrons = nullptr;
275  event.retrieve(electrons,"Electrons").ignore();
276  for(auto electron : *electrons)
277  {
278  if(!electron->caloCluster()) continue;
279  float eta = fabs(electron->caloCluster()->etaBE(2));
280  float pt = electron->pt();
281  if(pt<10e3f || eta>=2.47) continue;
282  if(!truthType.isAvailable(*electron)) continue;
283  if(!truthOrigin.isAvailable(*electron)) continue;
284  int t = truthType(*electron), o = truthOrigin(*electron);
285  if(t!=2 || !(o==10 || (o>=12 && o<=22) || o==43)) continue;
287  if(pt < 7e3f) continue;
288  if(pt >= 18e3f) ++nTrig_e17;
289 
290  myTriggeringElectrons.push_back(electron);
291  }
292 
293  vector<const xAOD::Muon*> myTriggeringMuons;
294  const xAOD::MuonContainer* muons = nullptr;
295  event.retrieve(muons,"Muons").ignore();
296  for(auto muon : *muons)
297  {
298  if(runNumber >= 324320) break; // delete line once all SFs available for 2017
299  float pt = muon->pt();
300  if(pt<10e3f || fabs(muon->eta())>=2.5) continue;
301  auto mt = muon->muonType();
302  if(mt!=xAOD::Muon::Combined && mt!=xAOD::Muon::MuonStandAlone) continue;
303  auto& mtp = *(muon->primaryTrackParticle());
304  if(!truthType.isAvailable(mtp)) continue;
305  if(!truthOrigin.isAvailable(mtp)) continue;
306  int t = truthType(mtp), o = truthOrigin(mtp);
307  if(t!=6 || !(o==10 || (o>=12 && o<=22) || o==43)) continue;
309  if(pt < 25.2e3f) continue;
310 
311  myTriggeringMuons.push_back(muon);
312  }
313 
317  for(auto electron : myTriggeringElectrons)
318  {
319  bool medium = bernoulliPdf(randomEngine);
320  bool tight = medium && bernoulliPdf(randomEngine);
322  dec_pid(*electron) = tight? 2 : medium? 1 : 0;
323  if(medium && electron->pt()>8e3f) ++nTrig_e7;
324  if(tight && electron->pt()>27e3f) ++nTrig_e26;
325  }
326 
328  if(nTrig_e26 < 1
329  && (nTrig_e7==0 || myTriggeringMuons.size()==0)
330  && nTrig_e17 < 2)
331  {
332  continue;
333  }
334 
335 
337  double sf = 1.;
338  auto cc = myTool->getEfficiencyScaleFactor(myTriggeringElectrons,
339  myTriggeringMuons, sf);
341  {
342  nSuitableEvents += 1;
343  sumW += sf;
344  }
345  else
346  {
347  Warning(MSGSOURCE, "Scale factor evaluation failed");
348  ++errors;
349  }
350  if(errors>10)
351  {
352  Error(MSGSOURCE, "Too many errors reported!");
353  break;
354  }
355  }
356  Info(MSGSOURCE, "Average scale factor: %f (over %ld events)",
357  sumW / nSuitableEvents, long(nSuitableEvents));
358  #ifndef XAOD_STANDALONE
359  ANA_CHECK(app->finalize())
360  #endif
361  return errors? 4 : 0;
362 }
store
StoreGateSvc * store
Definition: fbtTestBasics.cxx:71
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
asg::AnaToolHandle< CP::IMuonTriggerScaleFactors >
MSGSOURCE
#define MSGSOURCE
Definition: TrigGlobEffCorrExample3e.cxx:84
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
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 >
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:100
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:46
PATCore::ParticleDataType::Full
@ Full
Definition: PATCoreEnums.h:22
DiTauMassTools::ignore
void ignore(T &&)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:58
event
POOL::TEvent event(POOL::TEvent::kClassAccess)
SG::Decorator< char >
lumiFormat.i
int i
Definition: lumiFormat.py:85
LArCellNtuple.argv
argv
Definition: LArCellNtuple.py:152
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:40
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
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:84
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