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