ATLAS Offline Software
Loading...
Searching...
No Matches
MuonTriggerScaleFactors.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4
5#include <sstream>
6#include <TRandom3.h>
7#include "TROOT.h"
8#include "TH1.h"
9#include "TH2.h"
10#include "TFile.h"
11#include "TKey.h"
12
17
24
25#include <iostream>
26#include <functional>
27#include <string>
28#include <cmath>
29
30namespace CP {
31 static const double muon_barrel_endcap_boundary = 1.05;
32
33 const std::map<unsigned int,int> MuonTriggerScaleFactors::m_runNumber_year = {
34 {284484,2015},
35 {311481,2016},
36 {340453,2017},
37 {364292,2018},
38 {440613,2022},
39 {456749,2023},
40 {486706,2024}
41 };
42
46 m_appliedSystematics(nullptr),
47 m_fileName(),
50 m_muonquality("Medium"),
51 m_calibration_version("250731_SummerUpdate"),
53 m_binning("fine"),
54 m_allowZeroSF(false),
55 m_experimental(false),
56 m_forceYear(-1),
57 m_forcePeriod(""),
60 m_nReplicas(100),
61 m_ReplicaRandomSeed(12345) {
62
63 declareProperty("MuonQuality", m_muonquality); // HighPt,Tight,Medium,Loose,LowPt
64 declareProperty("CalibrationRelease", m_calibration_version);
65 // these are for debugging / testing, *not* for general use!
66 declareProperty("filename", m_fileName);
67 declareProperty("CustomInputFolder", m_custom_dir);
68 declareProperty("Binning", m_binning); // fine or coarse
69 declareProperty("UseExperimental", m_experimental); // enable experimental features like single muon SF
70 //Properties needed for TOY setup for a given trigger: No replicas if m_replicaTriggerList is empty
71 declareProperty("ReplicaTriggerList", m_replicaTriggerList, "List of triggers on which we want to generate stat. uncertainty toy replicas.");
72 declareProperty("NReplicas", m_nReplicas, "Number of generated toy replicas, if replicas are required.");
73 declareProperty("ReplicaRandomSeed", m_ReplicaRandomSeed, "Random seed for toy replica generation.");
74 declareProperty("AllowZeroSF", m_allowZeroSF, "If a trigger is not available will return 0 instead of throwing an error. More difficult to spot configuration issues. Use at own risk");
75 declareProperty("forceYear", m_forceYear, "Only for developers. Never use this in any analysis!!!!!!");
76 declareProperty("forcePeriod", m_forcePeriod, "Only for developers. Never use this in any analysis!!!!!!");
77 }
78
80
81 StatusCode MuonTriggerScaleFactors::LoadTriggerMap(unsigned int year) {
82 std::string fileName = m_fileName;
83 if (fileName.empty()) {
84 if (year == 2015) fileName = "muontrigger_sf_2015_mc20a_v3.root";
85 else if (year == 2016) fileName = "muontrigger_sf_2016_mc20a_v3.root";
86 else if (year == 2017) fileName = "muontrigger_sf_2017_mc20d_v3.root";
87 else if (year == 2018) fileName = "muontrigger_sf_2018_mc20e_v3.root";
88 else if (year == 2022) fileName = "muontrigger_sf_2022_mc23a_v3.root";
89 else if (year == 2023) fileName = "muontrigger_sf_2023_mc23d_v3.root";
90 else if (year == 2024) fileName = "muontrigger_sf_2024_mc23e_v1.root";
91 else{
92 ATH_MSG_WARNING("There is no SF file for year " << year << " yet");
93 return StatusCode::SUCCESS;
94 }
95 }
96
97 TDirectory* origDir = gDirectory;
98
99 std::string filePath;
100
101 if (m_custom_dir.empty()) {
102 filePath = PathResolverFindCalibFile(Form("MuonEfficiencyCorrections/%s/%s", m_calibration_version.c_str(), fileName.c_str()));
103 if (filePath.empty()) {
104 ATH_MSG_ERROR("Unable to resolve the input file " << fileName << " via PathResolver.");
105 }
106 }
107 else {
108 ATH_MSG_INFO("Note: setting up with user specified input file location " << m_custom_dir << " - this is not encouraged!");
109 filePath = PathResolverFindCalibFile(Form("%s/%s", m_custom_dir.c_str(), fileName.c_str()));
110 }
111
112 TFile* file = TFile::Open(filePath.c_str());
113
114 if (file == nullptr || !file->IsOpen()) {
115 ATH_MSG_FATAL("MuonTriggerScaleFactors::initialize Couldn't open file " << filePath);
116 return StatusCode::FAILURE;
117 }
118 TDirectory* tempDir = getTemporaryDirectory();
119 tempDir->cd();
120
121 static const std::vector<std::string> type { "data", "mc" };
122 static const std::vector<std::string> region { "barrel", "endcap" };
123 static const std::vector<std::string> systematic { "nominal", "stat_up", "stat_down", "syst_up", "syst_down" };
124 if(m_muonquality.compare("LowPt") == 0)
125 m_muonquality = "Medium";
126 const std::string quality = m_muonquality;
127 TDirectory* qualityDirectory = file->GetDirectory(m_muonquality.c_str());
128 if (qualityDirectory == nullptr) {
129 ATH_MSG_FATAL("MuonTriggerScaleFactors::initialize cannot find directory with selected quality");
130 return StatusCode::FAILURE;
131 }
132 TKey* periodKey;
133 TIter nextPeriod(qualityDirectory->GetListOfKeys());
134 while ((periodKey = (TKey*) nextPeriod())) {
135 if (not periodKey->IsFolder()) continue;
136 TDirectory* periodDirectory = qualityDirectory->GetDirectory(periodKey->GetName());
137 std::string periodName = std::string(periodKey->GetName());
138 std::string periodName_InMap = periodName.substr(std::string("Period").size(), periodName.size());
139 YearPeriod period = YearPeriod(year, periodName_InMap);
140 TKey* triggerKey;
141 TIter nextTrigger(periodDirectory->GetListOfKeys());
142 while ((triggerKey = (TKey*) nextTrigger())) {
143 if (not triggerKey->IsFolder()) continue;
144 TDirectory* triggerDirectory = periodDirectory->GetDirectory(triggerKey->GetName());
145 std::string triggerName = std::string(triggerKey->GetName());
146 if(!std::set<std::string>{"HLT_mu26_ivarmedium", "HLT_mu50", "HLT_mu26_ivarmedium_OR_HLT_mu50"}.count(triggerName) && m_binning == "coarse"){
147 ATH_MSG_DEBUG("Coarse binning not supported for di-muon trigger legs at the moment");
148 continue;
149 }
150 for (const auto& iregion : region) {
151 bool isBarrel = iregion.find("barrel") != std::string::npos;
152 for (const auto& itype : type) {
153 bool isData = itype.find("data") != std::string::npos;
154 std::string histname = ("_MuonTrigEff_" + periodName + "_" + triggerName + "_" + quality + "_" + "_EtaPhi_" + m_binning + "_" + iregion + "_" + itype);
155 for (const auto& isys : systematic) {
156 if (itype.find("data") != std::string::npos && isys.find("syst") != std::string::npos) continue;
157 std::string path = "eff_etaphi_" + m_binning + "_" + iregion + "_" + itype + "_" + isys;
158 TH2* hist = dynamic_cast<TH2*>(triggerDirectory->Get(path.c_str()));
159 if (not hist) {
160
161 ATH_MSG_FATAL("MuonTriggerScaleFactors::initialize " << path << " not found under trigger " << triggerName << " and period " << periodName << " for year: " << year);
162 continue;
163 }
164 hist->SetDirectory(0);
165
166 EffiHistoIdent HistoId = EffiHistoIdent(period, encodeHistoName(periodName_InMap, triggerName, isData, isys, isBarrel));
167 if (m_efficiencyMap.find(HistoId) != m_efficiencyMap.end()) {
168 ATH_MSG_FATAL("MuonTriggerScaleFactors::initialize(): histogram " << path << " is duplicated for year" << year << " in period " << periodName);
169 return StatusCode::FAILURE;
170 }
171 m_efficiencyMap.insert(std::pair<EffiHistoIdent, TH1_Ptr>(HistoId, std::shared_ptr < TH1 > (hist)));
172
173 }
174 //If the trigger is chosen for toy evaluation, generate all the replicas from
175 // NOMINAL with STAT variations stored in the data hist, load them in corresponding vector
176 if (m_replicaSet.find(triggerName) != m_replicaSet.end() && itype.find("data") != std::string::npos) {
177
178 TH1_Ptr Nominal_H = getEfficiencyHistogram(year, periodName, triggerName, isData, "nominal", isBarrel);
179 TH1_Ptr StatUp_H = getEfficiencyHistogram(year, periodName, triggerName, isData, "stat_up", isBarrel);
180
181 TH1_Ptr tmp_h2 = TH1_Ptr(dynamic_cast<TH2F*>(Nominal_H->Clone(Form("tmp_h2_%s", Nominal_H->GetName()))));
182 const int xbins = tmp_h2->GetNbinsX(), ybins = tmp_h2->GetNbinsY();
183 for (int x_i = 0; x_i <= xbins; ++x_i) {
184 for (int y_i = 0; y_i <= ybins; ++y_i) {
185 double statErr = std::abs(tmp_h2->GetBinContent(x_i, y_i) - StatUp_H->GetBinContent(x_i, y_i));
186 tmp_h2->SetBinError(x_i, y_i, statErr);
187 }
188 }
189 m_efficiencyMapReplicaArray[EffiHistoIdent(period, encodeHistoName(periodName, triggerName, isData, "repl", isBarrel))] = generateReplicas(tmp_h2, m_nReplicas, m_ReplicaRandomSeed);
190 }
191 }
192 }
193 }
194 }
195 file->Close();
196 delete file;
197 origDir->cd();
198 return StatusCode::SUCCESS;
199 }
200 // ==================================================================================
201 // == MuonTriggerScaleFactors::initialize()
202 // ==================================================================================
204
205 ATH_MSG_INFO("MuonQuality = '" << m_muonquality << "'");
206 ATH_MSG_INFO("Binning = '" << m_binning << "'");
207 ATH_MSG_INFO("CalibrationRelease = '" << m_calibration_version << "'");
208 ATH_MSG_INFO("CustomInputFolder = '" << m_custom_dir << "'");
209 ATH_MSG_INFO("AllowZeroSF = " << m_allowZeroSF);
210 ATH_MSG_INFO("experimental = " << m_experimental);
211
212 ATH_CHECK(m_eventInfo.initialize());
213
214 if (registerSystematics() != StatusCode::SUCCESS) {
215 return StatusCode::FAILURE;
216 }
217
218 if (applySystematicVariation(CP::SystematicSet()) != StatusCode::SUCCESS) {
219 ATH_MSG_ERROR("Could not configure for nominal settings");
220 return StatusCode::FAILURE;
221 }
222 // Initialize indexes of replicas for trigges which are asked
223 for (auto trigToy : m_replicaTriggerList)
224 m_replicaSet.insert(trigToy);
225
226 ATH_MSG_INFO("MuonTriggerScaleFactors::initialize");
227 constexpr auto years_to_run = std::to_array<int>({2015, 2016, 2017, 2018, 2022, 2023, 2024});
228 for (const int &year: years_to_run) {
230 }
231 return StatusCode::SUCCESS;
232 }
233
234 CorrectionCode MuonTriggerScaleFactors::getTriggerScaleFactor(const xAOD::Muon& muon, Double_t& triggersf, const std::string& trigger) const {
235 if(!m_experimental){
236 ATH_MSG_ERROR("MuonTriggerScaleFactors::getTriggerScaleFactor This is an experimental function. If you really know what you are doing set UseExperimental property.");
238 }
239
240 if (trigger.empty()) {
241 ATH_MSG_ERROR("MuonTriggerScaleFactors::getTriggerScaleFactor Trigger must have value.");
243 }
244
245 TrigMuonEff::Configuration configuration;
246
247 if (trigger == "HLT_mu8noL1")
248 ATH_MSG_WARNING("What you are trying to do is not correct. For di-muon triggers you should get the efficiency with getTriggerEfficiency and compute the SF by yourself.");
249 else if (trigger.find("HLT_2mu10") != std::string::npos || trigger.find("HLT_2mu14") != std::string::npos)
250 ATH_MSG_WARNING("Di-muon trigger scale factors for single reco muons are not supported!");
251 else
252 return GetTriggerSF(triggersf, configuration, muon, trigger);
253 return CorrectionCode::Ok;
254 }
255
256 CorrectionCode MuonTriggerScaleFactors::getTriggerScaleFactor(const xAOD::MuonContainer& mucont, Double_t& triggersf, const std::string& trigger) const{
257 if (trigger.empty()) {
258 ATH_MSG_ERROR("MuonTriggerScaleFactors::getTriggerScaleFactor Trigger must have value.");
260 }
261
262 TrigMuonEff::Configuration configuration;
263
264 if (trigger == "HLT_mu8noL1") {
265 ATH_MSG_WARNING("What you are trying to do is not correct. For di-muon triggers you should get the efficiency with getTriggerEfficiency and compute the SF by yourself.");
266 }
267 else if (trigger.find("HLT_2mu10") != std::string::npos || trigger.find("HLT_2mu14") != std::string::npos) {
268 CorrectionCode cc = GetTriggerSF_dimu(triggersf, configuration, mucont, trigger);
269 return cc;
270 } else {
271 CorrectionCode cc = GetTriggerSF(triggersf, configuration, mucont, trigger);
272 return cc;
273 }
274 return CorrectionCode::Ok;
275 }
276
277 // ==================================================================================
278 // == MuonTriggerScaleFactors::getReplica_index
279 // ==================================================================================
280 // Gets replica index correponding to the toy.
281 // Also checks if the sys_name contains "MCTOY" and if the trigger has replicas generated.
282 // Returns -1 if conditions are note satisfied
283 int MuonTriggerScaleFactors::getReplica_index(const std::string& sysBaseName, const std::string& trigStr) const{
284 if (m_replicaSet.find(trigStr) == m_replicaSet.end()) return -1; //No toys for this trigger
285 std::size_t pos = sysBaseName.find("MCTOY");
286 if (pos == std::string::npos) return -1; //sys variation not affected by TOYS
287 return atoi(sysBaseName.substr(pos + 5, pos + 8).c_str()); //toys for this trigger are around get the 3-digit number
288 }
289
290 CorrectionCode MuonTriggerScaleFactors::getTriggerEfficiency(const xAOD::Muon& mu, Double_t& efficiency, const std::string& trigger, Bool_t dataType) const{
291 if (trigger.empty()) {
292 ATH_MSG_ERROR("MuonTriggerScaleFactors::getTriggerEfficiency Trigger must have value.");
294 }
295 TrigMuonEff::Configuration configuration;
296 configuration.isData = dataType;
297 configuration.replicaIndex = -1;
298 Int_t threshold;
300 if (result != CorrectionCode::Ok) return result;
301 if (mu.pt() < threshold) {
302 efficiency = 0;
303 return CorrectionCode::Ok;
304 }
305
306 // Pre-define uncertainty variations
307 static const CP::SystematicVariation stat_up("MUON_EFF_TrigStatUncertainty", 1);
308 static const CP::SystematicVariation stat_down("MUON_EFF_TrigStatUncertainty", -1);
309 static const CP::SystematicVariation syst_up("MUON_EFF_TrigSystUncertainty", 1);
310 static const CP::SystematicVariation syst_down("MUON_EFF_TrigSystUncertainty", -1);
311
312 std::string systype = "";
313 if (appliedSystematics().matchSystematic(syst_down) && !dataType) {
314 systype = "syst_down";
315 } else if (appliedSystematics().matchSystematic(syst_up) && !dataType) {
316 systype = "syst_up";
317 } else if (appliedSystematics().matchSystematic(stat_down)) {
318 systype = "stat_down";
319 } else if (appliedSystematics().matchSystematic(stat_up)) {
320 systype = "stat_up";
321 } else {
322 systype = "nominal";
323 }
324
325 // Toys, if found, will overwrite the data hists stat with the generated toy
326 //+++++++++++++
327 // The best way is the use of filterByName with the 000MCTOY at the end. See:
328 // if( !(appliedSystematics().filterByBaseName("MUON_EFF_Trig_MCTOY000")).empty()){//The following is a hack!!!
329 //++++++++++THE FOLLOWING IS A PARTIAL HACK!!!
330 if (!appliedSystematics().empty() && configuration.isData == true) {
331 configuration.replicaIndex = getReplica_index(appliedSystematics().begin()->basename(), trigger);
332 if (configuration.replicaIndex != -1) systype = "replicas";
333 }
334 CorrectionCode cc = getMuonEfficiency(efficiency, configuration, mu, trigger, systype);
335 return cc;
336 }
337
339 // Private functions //
341
342 // ==================================================================================
343 // == MuonTriggerScaleFactors::generateReplicas
344 // ==================================================================================
345 // Generate replicas of h for Toys with each bin of h varied with Gaussian distribution
346 // with mean from bin content and sigma from bin error
347 std::vector<TH1_Ptr> MuonTriggerScaleFactors::generateReplicas(TH1_Ptr h, int nrep, int seed) const {
348 TRandom3 Rndm(seed);
349 std::vector<TH1_Ptr> replica_v;
350 const int xbins = h->GetNbinsX(), ybins = h->GetNbinsY();
351
352 for (int t = 0; t < nrep; ++t) {
353 TH2* replica = dynamic_cast<TH2*>(h->Clone(Form("rep%d_%s", t, h->GetName())));
354
355 for (int x_i = 0; x_i <= xbins; ++x_i) {
356 for (int y_i = 0; y_i <= ybins; ++y_i) {
357 replica->SetBinContent(x_i, y_i, Rndm.Gaus(h->GetBinContent(x_i, y_i), h->GetBinError(x_i, y_i)));
358 }
359 }
360 replica_v.push_back(TH1_Ptr(replica));
361 }
362 return replica_v;
363 }
364
365 bool MuonTriggerScaleFactors::isTriggerSupported(const std::string& trigger) const{
366 TH1_Ptr H1 = getEfficiencyHistogram(trigger, true, "nominal");
367 return H1.get() != nullptr;
368 }
369
370 int MuonTriggerScaleFactors::getBinNumber(const xAOD::Muon& muon, const std::string& trigger) const{
371 if(!m_experimental){
372 ATH_MSG_ERROR("MuonTriggerScaleFactors::getTriggerScaleFactor This is an experimental function. If you really know what you are doing set UseExperimental property.");
374 }
375
376 const double mu_eta = muon.eta();
377 const double mu_phi = muon.phi();
378 bool isBarrel = std::abs(mu_eta) < muon_barrel_endcap_boundary;
379 TH1_Ptr cit = getEfficiencyHistogram(trigger, true, "nominal", isBarrel);
380 if(!cit.get()){
381 if(!m_allowZeroSF)
382 ATH_MSG_ERROR("Could not find efficiency map for muon with eta: " << mu_eta << " and phi: " << mu_phi << ". Something is inconsistent. Please check your settings for year, mc and trigger." );
383 return -1;
384 }
385 auto eff_h2 = cit;
386 double mu_phi_corr = mu_phi;
387 if (mu_phi_corr < eff_h2->GetYaxis()->GetXmin()) mu_phi_corr += 2.0 * M_PI;
388 if (mu_phi_corr > eff_h2->GetYaxis()->GetXmax()) mu_phi_corr -= 2.0 * M_PI;
389 return eff_h2->FindFixBin(mu_eta, mu_phi_corr);
390 }
391
392 unsigned int MuonTriggerScaleFactors::encodeHistoName(const std::string& period, const std::string& Trigger, bool isData, const std::string& Systematic, bool isBarrel) const {
393 //keep the string as short as possible
394 const std::string histName = period + "_" + Trigger + "_" + (isBarrel ? "b" : "e") + "_" + (isData ? "data" : "mc") + Systematic;
395 return std::hash<std::string>()(histName);
396 }
397
398 unsigned int MuonTriggerScaleFactors::encodeHistoName(const std::string& Trigger, const TrigMuonEff::Configuration& configuration, const std::string& Systematic, bool isBarrel) const {
399 //keep the string as short as possible
400 return encodeHistoName(getDataPeriod(), Trigger, configuration.isData, Systematic, isBarrel);
401
402 }
403 TH1_Ptr MuonTriggerScaleFactors::getEfficiencyHistogram(unsigned int year, const std::string& period, const std::string& trigger, bool isData, const std::string& Systematic, bool isBarrel) const {
404 EffiHistoIdent Ident = EffiHistoIdent(YearPeriod(year, period), encodeHistoName(period, trigger, isData, Systematic, isBarrel));
405 EfficiencyMap::const_iterator Itr = m_efficiencyMap.find(Ident);
406
407 if (Itr == m_efficiencyMap.end()) {
408 return TH1_Ptr();
409 }
410 return Itr->second;
411 }
412 TH1_Ptr MuonTriggerScaleFactors::getEfficiencyHistogram(const std::string& trigger, bool isData, const std::string& Systematic, bool isBarrel) const {
413 unsigned int run = getRunNumber();
414 return getEfficiencyHistogram(getYear(run), getDataPeriod(run), trigger, isData, Systematic, isBarrel);
415 }
416
417 CorrectionCode MuonTriggerScaleFactors::getMuonEfficiency(Double_t& eff, const TrigMuonEff::Configuration& configuration, const xAOD::Muon& muon, const std::string& trigger, const std::string& systematic) const{
418 const double mu_eta = muon.eta();
419 const double mu_phi = muon.phi();
420 bool isBarrel = std::abs(mu_eta) < muon_barrel_endcap_boundary;
421
422 TH1_Ptr eff_h2 = nullptr;
423 if (configuration.replicaIndex >= 0) { //Only look into the replicas if asking for them
424
425 unsigned int run = getRunNumber();
426 EffiHistoIdent Ident = EffiHistoIdent(YearPeriod(getYear(run), getDataPeriod(run)), encodeHistoName(getDataPeriod(run), trigger, configuration.isData, "repl", isBarrel));
427 std::map<EffiHistoIdent, std::vector<TH1_Ptr> >::const_iterator cit = m_efficiencyMapReplicaArray.find(Ident);
428 if (cit == m_efficiencyMapReplicaArray.end()) {
429 if (m_allowZeroSF) {
430 ATH_MSG_WARNING("Could not find what you are looking for in the efficiency map. The trigger you are looking for, year and mc are not consistent, or the trigger is unavailable in this data period. Returning efficiency = 0.");
431 eff = 0.;
432 return CorrectionCode::Ok;
433 }
434
435 else {
436 ATH_MSG_ERROR("Could not find what you are looking for in the efficiency map. The trigger you are looking for, year and mc are not consistent, or the trigger is unavailable in this data period. Please check how you set up the tool.");
438 }
439 }
440
441 if (configuration.replicaIndex >= (int) cit->second.size()) {
442 ATH_MSG_ERROR("MuonTriggerScaleFactors::getMuonEfficiency ; index for replicated histograms is out of range.");
444 }
445
446 eff_h2 = cit->second[configuration.replicaIndex];
447 } else { //Standard case, look into the usual eff map
448 TH1_Ptr cit = getEfficiencyHistogram(trigger, configuration.isData, systematic, isBarrel);
449 if (cit.get() == nullptr) {
450 if (m_allowZeroSF) {
451 ATH_MSG_WARNING("Could not find what you are looking for in the efficiency map. The trigger you are looking for, year and mc are not consistent, or the trigger is unavailable in this data period. Returning efficiency = 0.");
452 eff = 0.;
453 return CorrectionCode::Ok;
454 } else {
455 ATH_MSG_ERROR("Could not find what you are looking for in the efficiency map. The trigger you are looking for, year and mc are not consistent, or the trigger is unavailable in this data period. Please check how you set up the tool.");
457 }
458 }
459 eff_h2 = cit;
460 }
461
462 double mu_phi_corr = mu_phi;
463 if (mu_phi_corr < eff_h2->GetYaxis()->GetXmin()) mu_phi_corr += 2.0 * M_PI;
464 if (mu_phi_corr > eff_h2->GetYaxis()->GetXmax()) mu_phi_corr -= 2.0 * M_PI;
465
466 const int bin = eff_h2->FindFixBin(mu_eta, mu_phi_corr);
467 const double efficiency = eff_h2->GetBinContent(bin);
468
469 eff = efficiency;
470
471 ATH_MSG_DEBUG("getMuonEfficiency [eta,phi,phi_corr]=[" << mu_eta << "," << mu_phi << "," << mu_phi_corr << "], ibin=" << bin << " eff=" << eff);
472
473 return CorrectionCode::Ok;
474
475 }
476
477 CorrectionCode MuonTriggerScaleFactors::GetTriggerSF_dimu(Double_t& TriggerSF, TrigMuonEff::Configuration& configuration, const xAOD::MuonContainer& mucont, const std::string& trigger) const{
478
479 if (mucont.size() != 2) {
480 ATH_MSG_FATAL("MuonTriggerScaleFactors::GetTriggerSF;Currently dimuon trigger chains only implemented for events with exactly 2 muons.");
481 }
482 ATH_MSG_DEBUG("The trigger that you choose : " << trigger);
483
484 Double_t eff_data = 0;
485 Double_t eff_mc = 0;
486
487 std::string data_err = "";
488 std::string mc_err = "";
489
490 if (appliedSystematics().matchSystematic(CP::SystematicVariation("MUON_EFF_TrigSystUncertainty", -1))) {
491 data_err = "nominal";
492 mc_err = "syst_up";
493 } else if (appliedSystematics().matchSystematic(CP::SystematicVariation("MUON_EFF_TrigSystUncertainty", 1))) {
494 data_err = "nominal";
495 mc_err = "syst_down";
496 } else if (appliedSystematics().matchSystematic(CP::SystematicVariation("MUON_EFF_TrigStatUncertainty", -1))) {
497 data_err = "stat_down";
498 mc_err = "nominal";
499 } else if (appliedSystematics().matchSystematic(CP::SystematicVariation("MUON_EFF_TrigStatUncertainty", 1))) {
500 data_err = "stat_up";
501 mc_err = "nominal";
502 } else {
503 data_err = "nominal";
504 mc_err = "nominal";
505 }
506
507 //Toys, if found, will overwrite the data hists with the sys generated with one toy
508 //+++++++++++++
509 //The best way is the use of filterByName with the 000MCTOY at the end. See:
510 // if( !(appliedSystematics().filterByBaseName("MUON_EFF_Trig_MCTOY000")).empty()){//The following is a hack!!!
511 //++++++++++THE FOLLOWING IS A PARTIAL HACK!!!
512 if (!appliedSystematics().empty()) {
513 configuration.replicaIndex = getReplica_index(appliedSystematics().begin()->basename(), trigger);
514 if (configuration.replicaIndex != -1) data_err = "replicas";
515 }
516
517 configuration.isData = true;
518 CorrectionCode result = getDimuonEfficiency(eff_data, configuration, mucont, trigger, data_err);
519 if (result != CorrectionCode::Ok) return result;
520
521 configuration.isData = false;
522 configuration.replicaIndex = -1;
523 result = getDimuonEfficiency(eff_mc, configuration, mucont, trigger, mc_err);
524 if (result != CorrectionCode::Ok) return result;
525
526 double event_SF = 1.;
527
528 if (std::abs(1. - eff_mc) > 0.0001) {
529 event_SF = eff_data / eff_mc;
530 }
531
532 TriggerSF = event_SF;
533 return CorrectionCode::Ok;
534 }
535
536 CorrectionCode MuonTriggerScaleFactors::GetTriggerSF(Double_t& TriggerSF, TrigMuonEff::Configuration& configuration, const xAOD::MuonContainer& mucont, const std::string& trigger) const{
537 Int_t threshold;
539 if (result != CorrectionCode::Ok) return result;
540
541 double rate_not_fired_data = 1.;
542 double rate_not_fired_mc = 1.;
543
544 for (const auto mu : mucont) {
545
546 double eff_data = 0., eff_mc = 0.;
547
548 if (mu->pt() < threshold) {
549
550 eff_data = 0.;
551 eff_mc = 0.;
552
553 } else {
554
555 std::string muon_trigger_name = trigger;
556 std::string data_err = "";
557 std::string mc_err = "";
558
559 // Pre-define uncertainty variations
560 static const CP::SystematicVariation stat_up("MUON_EFF_TrigStatUncertainty", 1);
561 static const CP::SystematicVariation stat_down("MUON_EFF_TrigStatUncertainty", -1);
562 static const CP::SystematicVariation syst_up("MUON_EFF_TrigSystUncertainty", 1);
563 static const CP::SystematicVariation syst_down("MUON_EFF_TrigSystUncertainty", -1);
564
565 if (appliedSystematics().matchSystematic(syst_down)) {
566 data_err = "nominal";
567 mc_err = "syst_up";
568 } else if (appliedSystematics().matchSystematic(syst_up)) {
569 data_err = "nominal";
570 mc_err = "syst_down";
571 } else if (appliedSystematics().matchSystematic(stat_down)) {
572 data_err = "stat_down";
573 mc_err = "nominal";
574 } else if (appliedSystematics().matchSystematic(stat_up)) {
575 data_err = "stat_up";
576 mc_err = "nominal";
577 } else {
578 data_err = "nominal";
579 mc_err = "nominal";
580 }
581
582 //Toys, if found, will overwrite the data hists, on which toys for stat uncertainty have been generated
583 //+++++++++++++
584 //The best way is the use of filterByName with the 000MCTOY at the end. See:
585 // if( !(appliedSystematics().filterByBaseName("MUON_EFF_Trig_MCTOY000")).empty()){//The following is a hack!!!
586 //++++++++++The following is a hack!!!
587 if (!appliedSystematics().empty()) {
588 configuration.replicaIndex = getReplica_index(appliedSystematics().begin()->basename(), trigger);
589 if (configuration.replicaIndex != -1) data_err = "replicas";
590 }
591
592 configuration.isData = true;
593 CorrectionCode result_data = getMuonEfficiency(eff_data, configuration, *mu, muon_trigger_name, data_err);
594 if (result_data != CorrectionCode::Ok) return result_data;
595 configuration.isData = false;
596 configuration.replicaIndex = -1;
597 CorrectionCode result_mc = getMuonEfficiency(eff_mc, configuration, *mu, muon_trigger_name, mc_err);
598 if (result_mc != CorrectionCode::Ok) return result_mc;
599 }
600 rate_not_fired_data *= (1. - eff_data);
601 rate_not_fired_mc *= (1. - eff_mc);
602 }
603
604 double event_SF = 1.;
605 if (1 - rate_not_fired_data == 0) event_SF = 0;
606 if ((mucont.size()) and (std::abs(1. - rate_not_fired_mc) > 0.0001)) {
607
608 event_SF = (1. - rate_not_fired_data) / (1. - rate_not_fired_mc);
609 }
610 TriggerSF = event_SF;
611
612 return CorrectionCode::Ok;
613 }
614
615 CorrectionCode MuonTriggerScaleFactors::GetTriggerSF(Double_t& TriggerSF, TrigMuonEff::Configuration& configuration, const xAOD::Muon& mu, const std::string& trigger) const{
616 Int_t threshold;
619 return result;
620
621 double eff_data = 0., eff_mc = 0.;
622
623 if (mu.pt() < threshold) {
624 eff_data = 0.;
625 eff_mc = 0.;
626 TriggerSF = 1.;
627 return CorrectionCode::Ok;
628 }
629
630 std::string muon_trigger_name = trigger;
631 std::string data_err = "";
632 std::string mc_err = "";
633
634 // Pre-define uncertainty variations
635 static const CP::SystematicVariation stat_up("MUON_EFF_TrigStatUncertainty", 1);
636 static const CP::SystematicVariation stat_down("MUON_EFF_TrigStatUncertainty", -1);
637 static const CP::SystematicVariation syst_up("MUON_EFF_TrigSystUncertainty", 1);
638 static const CP::SystematicVariation syst_down("MUON_EFF_TrigSystUncertainty", -1);
639
640 if (appliedSystematics().matchSystematic(syst_down)) {
641 data_err = "nominal";
642 mc_err = "syst_up";
643 } else if (appliedSystematics().matchSystematic(syst_up)) {
644 data_err = "nominal";
645 mc_err = "syst_down";
646 } else if (appliedSystematics().matchSystematic(stat_down)) {
647 data_err = "stat_down";
648 mc_err = "nominal";
649 } else if (appliedSystematics().matchSystematic(stat_up)) {
650 data_err = "stat_up";
651 mc_err = "nominal";
652 } else {
653 data_err = "nominal";
654 mc_err = "nominal";
655 }
656
657 if (!appliedSystematics().empty()) {
658 configuration.replicaIndex = getReplica_index(appliedSystematics().begin()->basename(), trigger);
659 if (configuration.replicaIndex != -1) data_err = "replicas";
660 }
661
662 configuration.isData = true;
663 CorrectionCode result_data = getMuonEfficiency(eff_data, configuration, mu, muon_trigger_name, data_err);
664 if (result_data != CorrectionCode::Ok)
665 return result_data;
666 configuration.isData = false;
667 configuration.replicaIndex = -1;
668 CorrectionCode result_mc = getMuonEfficiency(eff_mc, configuration, mu, muon_trigger_name, mc_err);
669 if (result_mc != CorrectionCode::Ok)
670 return result_mc;
671 if (eff_data == 0)
672 TriggerSF = 0;
673 if (std::abs(eff_mc) > 0.0001)
674 TriggerSF = eff_data / eff_mc;
675 return CorrectionCode::Ok;
676 }
677
678 CorrectionCode MuonTriggerScaleFactors::getDimuonEfficiency(Double_t& eff, const TrigMuonEff::Configuration& configuration, const xAOD::MuonContainer& mucont, const std::string& chain, const std::string& systematic) const{
679
680 std::string trigger = getTriggerCorrespondingToDimuonTrigger(chain);
681 Int_t threshold;
683 if (result != CorrectionCode::Ok) return result;
684
687
688 Double_t eff1 = 0;
689 if ((**mu1).pt() > threshold) {
690 CorrectionCode result1 = getMuonEfficiency(eff1, configuration, (**mu1), trigger, systematic);
691 if (result1 != CorrectionCode::Ok) return result1;
692 }
693 Double_t eff2 = 0;
694 if ((**mu2).pt() > threshold) {
695 CorrectionCode result2 = getMuonEfficiency(eff2, configuration, (**mu2), trigger, systematic);
696 if (result2 != CorrectionCode::Ok) return result2;
697 }
698
699 eff = eff1 * eff2;
700 return CorrectionCode::Ok;
701 }
702
703 std::string MuonTriggerScaleFactors::getTriggerCorrespondingToDimuonTrigger(const std::string& trigger) const {
704 if (trigger.find("2mu10") != std::string::npos) return "HLT_mu10";
705 if (trigger.find("2mu14") != std::string::npos) return "HLT_mu14";
706 throw std::runtime_error("Unknown dimuon trigger");
707 }
708
709 CorrectionCode MuonTriggerScaleFactors::getThreshold(Int_t& threshold, const std::string& trigger) const{
710 std::size_t index = trigger.find("HLT_mu");
711 if (index != std::string::npos) {
712 std::string rawNumber = trigger.substr(index + 6);
713 if (!rawNumber.empty() && isdigit(rawNumber[0])) {
714 std::stringstream(rawNumber) >> threshold;
715 if (threshold < 10) threshold = 10000;
716 else threshold = (threshold + 1) * 1000;
717 return CorrectionCode::Ok;
718 }
719 }
720 ATH_MSG_ERROR("MuonTriggerScaleFactors::getThreshold Could not extract threshold for trigger " << trigger);
722 }
723
724 unsigned int MuonTriggerScaleFactors::getYear(unsigned int run) const {
725 if(m_forceYear != -1){
726 return m_forceYear;
727 }
728
729 int year=2050;
730 auto lower = m_runNumber_year.lower_bound(run);
731 if (lower != m_runNumber_year.end()){
732 year=lower->second;
733 }
734 return year;
735 }
736
738 return getDataPeriod(getRunNumber());
739 }
740
741 std::string MuonTriggerScaleFactors::getDataPeriod(unsigned int run) const {
742 return getDataPeriod(run, getYear(run));
743 }
744
745 std::string MuonTriggerScaleFactors::getDataPeriod(unsigned int runNumber, unsigned year) const {
746 if(!m_forcePeriod.empty())
747 return m_forcePeriod;
748 if (year == 2015) {
749 if (runNumber >= 266904 && runNumber <= 272531) return "AC";
750 else if (runNumber >= 276073 && runNumber <= 276954) return "D";
751 else if (runNumber >= 278727 && runNumber <= 279928) return "E";
752 else if (runNumber >= 279932 && runNumber <= 280422) return "F";
753 else if (runNumber >= 280423 && runNumber <= 281075) return "G";
754 else if (runNumber >= 281130 && runNumber <= 281411) return "H";
755 else if (runNumber >= 281662 && runNumber <= 282482) return "I"; // special ALFA run
756 else if (runNumber >= 282625 && runNumber <= 284484) return "J";
757 }
758 else if (year == 2016) {
759 if (runNumber >= 296939 && runNumber <= 300287) return "A";
760 else if (runNumber >= 300345 && runNumber <= 300908) return "B";
761 else if (runNumber >= 301912 && runNumber <= 302393) return "C";
762 else if (runNumber >= 302737 && runNumber <= 302872) return "D1D3";
763 else if (runNumber >= 302919 && runNumber <= 303560) return "D4D8";
764 else if (runNumber >= 303638 && runNumber <= 303892) return "E";
765 else if (runNumber >= 303943 && runNumber <= 304494) return "F";
766 else if (runNumber >= 305291 && runNumber <= 306714) return "G";
767 else if (runNumber >= 307124 && runNumber <= 308084) return "I";
768 else if (runNumber >= 309311 && runNumber <= 309759) return "K";
769 else if (runNumber >= 310015 && runNumber <= 311481) return "L";
770 }
771 else if (year == 2017) {
772 if (runNumber >= 324320 && runNumber <= 325558) return "A";
773 else if (runNumber >= 325713 && runNumber <= 328393) return "B";
774 else if (runNumber >= 329385 && runNumber <= 330470) return "C";
775 else if (runNumber >= 330857 && runNumber <= 332304) return "D";
776 else if (runNumber >= 332720 && runNumber <= 334779) return "E";
777 else if (runNumber >= 334842 && runNumber <= 335290) return "F";
778 else if (runNumber >= 336497 && runNumber <= 336782) return "H";
779 else if (runNumber >= 336832 && runNumber <= 337833) return "I";
780 else if (runNumber >= 338183 && runNumber <= 340453) return "K";
781 }
782 else if (year == 2018) {
783 if (runNumber >= 348197 && runNumber <= 348836) return "A";
784 else if (runNumber >= 348885 && runNumber <= 349533) return "B";
785 else if (runNumber >= 349534 && runNumber <= 350220) return "C";
786 else if (runNumber >= 350310 && runNumber <= 352107) return "D";
787 else if (runNumber >= 352123 && runNumber <= 352137) return "E";
788 else if (runNumber >= 352274 && runNumber <= 352514) return "F";
789 else if (runNumber >= 354107 && runNumber <= 354494) return "G";
790 else if (runNumber >= 354826 && runNumber <= 355224) return "H";
791 else if (runNumber >= 355261 && runNumber <= 355273) return "I";
792 else if (runNumber >= 355331 && runNumber <= 355468) return "J";
793 else if (runNumber >= 355529 && runNumber <= 356259) return "K";
794 else if (runNumber >= 357050 && runNumber <= 359171) return "L";
795 else if (runNumber >= 359191 && runNumber <= 360414) return "M";
796 else if (runNumber >= 361635 && runNumber <= 361696) return "N";
797 else if (runNumber >= 361738 && runNumber <= 363400) return "O";
798 else if (runNumber >= 363664 && runNumber <= 364292) return "Q";
799 }
800 else if (year == 2022) {
801 if(runNumber >= 430536 && runNumber <= 432180) return "F";
802 else if (runNumber >= 435816 && runNumber <= 439927) return "H";
803 else if (runNumber >= 440199 && runNumber <= 440613) return "J";
804 }
805 else if (year == 2023) {
806 if(runNumber >= 451094 && runNumber <= 455924) return "F";
807 else if (runNumber >= 455975 && runNumber <= 456749) return "G";
808 }
809 else if (year == 2024) {
810 if(runNumber >= 473235 && runNumber <= 473400) return "E";
811 else if (runNumber >= 473617 && runNumber <= 474271) return "F";
812 else if (runNumber >= 474441 && runNumber <= 474602) return "G";
813 else if (runNumber >= 474657 && runNumber <= 475522) return "H";
814 else if (runNumber >= 476060 && runNumber <= 477048) return "I";
815 else if (runNumber >= 479103 && runNumber <= 480032) return "K";
816 else if (runNumber >= 480188 && runNumber <= 482221) return "M";
817 else if (runNumber >= 482374 && runNumber <= 484799) return "N";
818 else if (runNumber >= 484909 && runNumber <= 486706) return "O";
819 }
820
821 ATH_MSG_FATAL("RunNumber: " << runNumber << " not known! Will stop the code to prevent using wrong SFs.");
822 throw std::invalid_argument{""};
823 }
824
826 static const SG::AuxElement::ConstAccessor<unsigned int> acc_rnd("RandomRunNumber");
828 if (info.operator->()==nullptr) {
829 ATH_MSG_FATAL("Could not retrieve the xAOD::EventInfo with name: " << m_eventInfo.key() << ". Exiting the code.");
830 throw std::invalid_argument{""};
831 }
832 if (!info->eventType(xAOD::EventInfo::IS_SIMULATION)) {
833 ATH_MSG_DEBUG("The current event is a data event. Return runNumber instead.");
834 return info->runNumber();
835 }
836 if (!acc_rnd.isAvailable(*info)) {
837 if(m_forceYear == -1 && m_forcePeriod == "")
838 ATH_MSG_FATAL("Failed to find the RandomRunNumber decoration. Please call the apply() method from the PileupReweightingTool beforehand in order to get period dependent SFs");
839 throw std::invalid_argument{""};
840 } else if (acc_rnd(*info) == 0) {
841 ATH_MSG_FATAL("Pile up tool has given runNumber 0. Exiting the code.");
842 throw std::invalid_argument{""};
843 }
844
845 // standard behaviour for MC, get the random RunNumber
846 return acc_rnd(*info);
847 }
848
850 gROOT->cd();
851 TDirectory* tempDir = 0;
852 int counter = 0;
853 while (not tempDir) {
854 std::stringstream dirname;
855 dirname << "MuonTriggerScaleFactorsTempDir_%i" << counter;
856 if (gROOT->GetDirectory((dirname.str()).c_str())) {
857 ++counter;
858 continue;
859 }
860 tempDir = gROOT->mkdir((dirname.str()).c_str());
861 if (not tempDir) {
862 ATH_MSG_ERROR("getTemporaryDirectory::Temporary directory could not be created");
863 }
864 }
865 return tempDir;
866 }
867
868 //=======================================================================
869 // Systematics Interface
870 //=======================================================================
872 if (!systematic.empty()) {
874 return sys.find(systematic) != sys.end();
875 }
876 return true;
877 }
878
881 CP::SystematicSet mySysSet;
882
883 mySysSet.insert(CP::SystematicVariation("MUON_EFF_TrigSystUncertainty", 1));
884 mySysSet.insert(CP::SystematicVariation("MUON_EFF_TrigSystUncertainty", -1));
885
886 //Consider full statUncertainty if TOY replicas are not used
887 if (m_replicaTriggerList.size() == 0) {
888 mySysSet.insert(CP::SystematicVariation("MUON_EFF_TrigStatUncertainty", 1));
889 mySysSet.insert(CP::SystematicVariation("MUON_EFF_TrigStatUncertainty", -1));
890 } else {
891 for (int i = 0; i < m_nReplicas; ++i) { //TOFIX Hack with just up variations! needs ASG reserved words for a clean handling//+++++++
892 mySysSet.insert(CP::SystematicVariation(Form("MUON_EFF_Trig_MCTOY%03d", i), 1));
893 }
894 }
895
896 return mySysSet;
897 }
898
899 // Register the systematics with the registry and add them to the recommended list
902 if (registry.registerSystematics(*this) != StatusCode::SUCCESS) {
903 ATH_MSG_ERROR("Failed to add systematic to list of recommended systematics.");
904 return StatusCode::FAILURE;
905 }
906 return StatusCode::SUCCESS;
907 }
908
913
915 // First, check if we already know this systematic configuration
916 auto itr = m_systFilter.find(systConfig);
917
918 // If it's a new input set, we need to filter it
919 if (itr == m_systFilter.end()) {
920
921 // New systematic. We need to parse it.
922 static const CP::SystematicSet affectingSys = affectingSystematics();
923 CP::SystematicSet filteredSys;
924 if (!CP::SystematicSet::filterForAffectingSystematics(systConfig, affectingSys, filteredSys)) {
925 ATH_MSG_ERROR("Unsupported combination of systematics passed to the tool!");
926 return StatusCode::FAILURE;
927 }
928
929 // Insert filtered set into the map
930 itr = m_systFilter.insert(std::make_pair(systConfig, filteredSys)).first;
931 }
932
933 CP::SystematicSet& mySysConf = itr->second;
934
935 // Check to see if the set of variations tries to add in the uncertainty up and down. Since the errors
936 // are symetric this would result in 0 and so should not be done.
937 static const CP::SystematicVariation stat_up("MUON_EFF_TrigStatUncertainty", 1);
938 static const CP::SystematicVariation stat_down("MUON_EFF_TrigStatUncertainty", -1);
939 static const CP::SystematicVariation syst_up("MUON_EFF_TrigSystUncertainty", 1);
940 static const CP::SystematicVariation syst_down("MUON_EFF_TrigSystUncertainty", -1);
941
942 if ((mySysConf.matchSystematic(stat_up) && mySysConf.matchSystematic(stat_down)) || (mySysConf.matchSystematic(syst_up) && mySysConf.matchSystematic(syst_down))) {
943 return StatusCode::FAILURE;
944 }
945
946 m_appliedSystematics = &mySysConf;
947 return StatusCode::SUCCESS;
948 }
949
950} /* namespace CP */
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
static const Attributes_t empty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Header file for AthHistogramAlgorithm.
Return value from object correction CP tools.
@ Error
Some error happened during the object correction.
@ OutOfValidityRange
Input object is out of validity range.
@ Ok
The correction was done successfully.
unsigned int getYear(unsigned int run) const
std::vector< std::string > m_replicaTriggerList
static const std::map< unsigned int, int > m_runNumber_year
virtual CorrectionCode GetTriggerSF_dimu(Double_t &TriggerSF, TrigMuonEff::Configuration &configuration, const xAOD::MuonContainer &mucont, const std::string &trigger) const
StatusCode LoadTriggerMap(unsigned int year)
std::set< std::string > m_replicaSet
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
std::map< EffiHistoIdent, std::vector< TH1_Ptr > > m_efficiencyMapReplicaArray
TDirectory * getTemporaryDirectory(void) const
virtual CorrectionCode getMuonEfficiency(Double_t &eff, const TrigMuonEff::Configuration &configuration, const xAOD::Muon &muon, const std::string &trigger, const std::string &systematic) const
virtual std::shared_ptr< TH1 > getEfficiencyHistogram(unsigned int year, const std::string &period, const std::string &trigger, bool isData, const std::string &Systematic, bool isBarrel=true) const
virtual int getReplica_index(const std::string &sysBaseName, const std::string &trigStr) const
std::pair< YearPeriod, unsigned int > EffiHistoIdent
virtual StatusCode applySystematicVariation(const CP::SystematicSet &systConfig)
effects: configure this tool for the given list of systematic variations.
MuonTriggerScaleFactors(const std::string &name)
std::vector< TH1_Ptr > generateReplicas(TH1_Ptr h, int nrep, int seed) const
virtual CorrectionCode getDimuonEfficiency(Double_t &eff, const TrigMuonEff::Configuration &configuration, const xAOD::MuonContainer &mucont, const std::string &chain, const std::string &systematic) const
unsigned int encodeHistoName(const std::string &period, const std::string &Trigger, bool isData, const std::string &Systematic, bool isBarrel=true) const
virtual CorrectionCode GetTriggerSF(Double_t &TriggerSF, TrigMuonEff::Configuration &configuration, const xAOD::MuonContainer &mucont, const std::string &trigger) const
virtual int getBinNumber(const xAOD::Muon &muon, const std::string &trigger) const
std::string getTriggerCorrespondingToDimuonTrigger(const std::string &trigger) const
CorrectionCode getThreshold(Int_t &threshold, const std::string &trigger) const
std::unordered_map< CP::SystematicSet, CP::SystematicSet > m_systFilter
const CP::SystematicSet & appliedSystematics() const
virtual bool isAffectedBySystematic(const CP::SystematicVariation &systematic) const
Declare the interface that this class provides.
virtual CorrectionCode getTriggerScaleFactor(const xAOD::MuonContainer &mucont, Double_t &triggersf, const std::string &trigger) const
virtual CP::SystematicSet affectingSystematics() const
returns: the list of all systematics this tool can be affected by
virtual CP::SystematicSet recommendedSystematics() const
returns: the list of all systematics this tool recommends to use
virtual bool isTriggerSupported(const std::string &trigger) const
Returns whether the trigger is supported by the tool or not. The decision depends on the present (ran...
virtual CorrectionCode getTriggerEfficiency(const xAOD::Muon &mu, Double_t &efficiency, const std::string &trigger, Bool_t dataType) const
std::pair< unsigned int, std::string > YearPeriod
This module implements the central registry for handling systematic uncertainties with CP tools.
static SystematicRegistry & getInstance()
Get the singleton instance of the registry for the curren thread.
StatusCode registerSystematics(const IReentrantSystematicsTool &tool)
effects: register all the systematics from the tool
Class to wrap a set of SystematicVariations.
bool matchSystematic(const SystematicVariation &systematic, MATCHTYPE type=FULL) const
void insert(const SystematicVariation &systematic)
description: insert a systematic into the set
static StatusCode filterForAffectingSystematics(const SystematicSet &systConfig, const SystematicSet &affectingSystematics, SystematicSet &filteredSystematics)
description: filter the systematics for the affected systematics returns: success guarantee: strong f...
bool empty() const
returns: whether this is an empty systematic, i.e.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
@ IS_SIMULATION
true: simulation, false: data
void efficiency(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
Select isolated Photons, Electrons and Muons.
std::shared_ptr< TH1 > TH1_Ptr
static const double muon_barrel_endcap_boundary
Definition index.py:1
Definition run.py:1
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
structure to hold variables to configure behaviour of the tool
int replicaIndex
index of replicated histograms to access
TFile * file
std::string dirname(std::string name)
Definition utils.cxx:200
std::string basename(std::string name)
Definition utils.cxx:207