27 {
28 constexpr double muon_barrel_endcap_boundary = 1.05;
29
30 struct RunYear {
33 };
34
35 constexpr std::array runYears{
36 RunYear{284484, 2015},
37 RunYear{311481, 2016},
38 RunYear{340453, 2017},
39 RunYear{364292, 2018},
40 RunYear{440613, 2022},
41 RunYear{456749, 2023},
42 RunYear{486706, 2024},
43 RunYear{509849, 2025}
44 };
45
46 const std::map<unsigned short int, std::vector< std::tuple<unsigned int,unsigned int,std::string_view> > > MuonTriggerScaleFactors::m_year_periods = {
47 {2015, {
48 {266904,272531,"AC"},
49 {276073,276954,"D"},
50 {278727,279928,"E"},
51 {279932,280422,"F"},
52 {280423,281075,"G"},
53 {281130,281411,"H"},
54 {281662,282482,"I"},
55 {282625,284484,"J"}}
56 },
57 {2016, {
58 {296939,300287,"A"},
59 {300345,300908,"B"},
60 {301912,302393,"C"},
61 {302737,302872,"D1D3"},
62 {302919,303560,"D4D8"},
63 {303638,303892,"E"},
64 {303943,304494,"F"},
65 {305291,306714,"G"},
66 {307124,308084,"I"},
67 {309311,309759,"K"},
68 {310015,311481,"L"}}
69 },
70 {2017, {
71 {324320,325558,"A"},
72 {325713,328393,"B"},
73 {329385,330470,"C"},
74 {330857,332304,"D"},
75 {332720,334779,"E"},
76 {334842,335290,"F"},
77 {336497,336782,"H"},
78 {336832,337833,"I"},
79 {338183,340453,"K"}}
80 },
81 {2018, {
82 {348197,348836,"A"},
83 {348885,349533,"B"},
84 {349534,350220,"C"},
85 {350310,352107,"D"},
86 {352123,352137,"E"},
87 {352274,352514,"F"},
88 {354107,354494,"G"},
89 {354826,355224,"H"},
90 {355261,355273,"I"},
91 {355331,355468,"J"},
92 {355529,356259,"K"},
93 {357050,359171,"L"},
94 {359191,360414,"M"},
95 {361635,361696,"N"},
96 {361738,363400,"O"},
97 {363664,364292,"Q"}}
98 },
99 {2022, {
100 {430536,432180,"F"},
101 {435816,439927,"H"},
102 {440199,440613,"J"}}
103 },
104 {2023, {
105 {451094,455924,"F"},
106 {455975,456749,"G"}}
107 },
108 {2024, {
109 {473235,473400,"E"},
110 {473617,474271,"F"},
111 {474441,474602,"G"},
112 {474657,475522,"H"},
113 {476060,477048,"I"},
114 {479103,480032,"K"},
115 {480188,482221,"M"},
116 {482374,484799,"N"},
117 {484909,486706,"O"}}
118 },
119 {2025, {
120 {497924,498434,"D"},
121 {498515,499592,"E"},
122 {499618,500348,"F"},
123 {502557,505458,"K"},
124 {506231,507775,"M"},
125 {508160,509452,"O"},
126 {509803,509849,"Q"}}
127 }
128 };
129
130 MuonTriggerScaleFactors::MuonTriggerScaleFactors(const std::string& name) :
132
133 MuonTriggerScaleFactors::~MuonTriggerScaleFactors() { }
134
135 StatusCode MuonTriggerScaleFactors::LoadTriggerMap(
unsigned int year) {
137 if (m_customInputFilePerYear.value().contains(year)) {
138 fileName = m_customInputFilePerYear.value().at(year);
140 ANA_MSG_INFO(
"Skipping loading trigger SF for year " << year <<
" since the provided file name is empty");
141 return StatusCode::SUCCESS;
142 } else {
143 ATH_MSG_INFO(
"Loading trigger SF from user specified file " << fileName <<
" for year " << year);
144 }
145 }
146
148 if (year == 2015)
fileName =
"muontrigger_sf_2015_mc20a_v3.root";
149 else if (year == 2016)
fileName =
"muontrigger_sf_2016_mc20a_v3.root";
150 else if (year == 2017)
fileName =
"muontrigger_sf_2017_mc20d_v3.root";
151 else if (year == 2018)
fileName =
"muontrigger_sf_2018_mc20e_v3.root";
152 else if (year == 2022)
fileName =
"muontrigger_sf_2022_mc23a_v5.root";
153 else if (year == 2023)
fileName =
"muontrigger_sf_2023_mc23d_v5.root";
154 else if (year == 2024)
fileName =
"muontrigger_sf_2024_mc23e_v5.root";
155 else if (year == 2025)
fileName =
"muontrigger_sf_2025_mc23g_v2.root";
156 else {
158 return StatusCode::SUCCESS;
159 }
160 }
161
163
165
166 if (m_customInputFolder.empty()) {
169 ATH_MSG_ERROR(
"Unable to resolve the input file " << fileName <<
" via PathResolver.");
170 }
171 }
172 else {
173 ATH_MSG_INFO(
"Note: setting up with user specified input file location " << m_customInputFolder.value() <<
" - this is not encouraged!");
175 }
176
178
179 if (
file ==
nullptr || !
file->IsOpen()) {
180 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::initialize Couldn't open file " << filePath);
181 return StatusCode::FAILURE;
182 }
183 TDirectory* tempDir = getTemporaryDirectory();
184 tempDir->cd();
185
186 static const std::vector<std::string>
type {
"data",
"mc" };
187 static const std::vector<std::string> region { "barrel", "endcap" };
188 static const std::vector<std::string> systematic { "nominal", "stat_up", "stat_down", "syst_up", "syst_down" };
189 if (m_muonQuality.value().compare("LowPt") == 0) {
190 m_muonQuality = "Medium";
191 }
192 TDirectory* qualityDirectory =
file->GetDirectory(m_muonQuality.value().c_str());
193 if (qualityDirectory == nullptr) {
194 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::initialize cannot find directory with selected quality");
195 return StatusCode::FAILURE;
196 }
197 TKey* periodKey;
198 TIter nextPeriod(qualityDirectory->GetListOfKeys());
199 while ((periodKey = (TKey*) nextPeriod())) {
200 if (not periodKey->IsFolder()) continue;
201 TDirectory* periodDirectory = qualityDirectory->GetDirectory(periodKey->GetName());
202 std::string
periodName = std::string(periodKey->GetName());
204 YearPeriod
period = YearPeriod(year, periodName_InMap);
205 TKey* triggerKey;
206 TIter nextTrigger(periodDirectory->GetListOfKeys());
207 while ((triggerKey = (TKey*) nextTrigger())) {
208 if (not triggerKey->IsFolder()) continue;
209 TDirectory* triggerDirectory = periodDirectory->GetDirectory(triggerKey->GetName());
210 std::string triggerName = std::string(triggerKey->GetName());
211 if(!std::set<std::string>{"HLT_mu26_ivarmedium", "HLT_mu50", "HLT_mu26_ivarmedium_OR_HLT_mu50"}.count(triggerName) && m_binning == "coarse"){
212 ATH_MSG_DEBUG(
"Coarse binning not supported for di-muon trigger legs at the moment");
213 continue;
214 }
215 for (const auto& iregion : region) {
216 bool isBarrel = iregion.find(
"barrel") != std::string::npos;
217 for (
const auto& itype :
type) {
218 bool isData = itype.find("data") != std::string::npos;
219 std::string
histname = (
"_MuonTrigEff_" +
periodName +
"_" + triggerName +
"_" + m_muonQuality.value() +
"_" +
"_EtaPhi_" + m_binning +
"_" + iregion +
"_" + itype);
220 for (const auto& isys : systematic) {
221 if (itype.find("data") != std::string::npos && isys.find("syst") != std::string::npos) continue;
222 std::string
path =
"eff_etaphi_" + m_binning +
"_" + iregion +
"_" + itype +
"_" + isys;
223 TH2*
hist =
dynamic_cast<TH2*
>(triggerDirectory->Get(
path.c_str()));
224 if (not hist) {
225
226 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::initialize " << path <<
" not found under trigger " << triggerName <<
" and period " << periodName <<
" for year: " << year);
227 continue;
228 }
229 hist->SetDirectory(0);
230
231 EffiHistoIdent HistoId = EffiHistoIdent(period, encodeHistoName(periodName_InMap, triggerName, isData, isys, isBarrel));
232 if (m_efficiencyMap.find(HistoId) != m_efficiencyMap.end()) {
233 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::initialize(): histogram " << path <<
" is duplicated for year" << year <<
" in period " << periodName);
234 return StatusCode::FAILURE;
235 }
236 m_efficiencyMap.insert(std::pair<EffiHistoIdent, TH1_Ptr>(HistoId, std::shared_ptr < TH1 > (hist)));
237
238 }
239
240
241 if (m_replicaSet.find(triggerName) != m_replicaSet.end() && itype.find("data") != std::string::npos) {
242
243 TH1_Ptr Nominal_H = getEfficiencyHistogram(year, periodName, triggerName, isData, "nominal", isBarrel);
244 TH1_Ptr StatUp_H = getEfficiencyHistogram(year, periodName, triggerName, isData, "stat_up", isBarrel);
245
246 TH1_Ptr tmp_h2 = TH1_Ptr(
dynamic_cast<TH2F*
>(Nominal_H->Clone(Form(
"tmp_h2_%s", Nominal_H->GetName()))));
247 const int xbins = tmp_h2->GetNbinsX(),
ybins = tmp_h2->GetNbinsY();
248 for (
int x_i = 0; x_i <=
xbins; ++x_i) {
249 for (
int y_i = 0; y_i <=
ybins; ++y_i) {
250 double statErr = std::abs(tmp_h2->GetBinContent(x_i, y_i) - StatUp_H->GetBinContent(x_i, y_i));
251 tmp_h2->SetBinError(x_i, y_i, statErr);
252 }
253 }
254 m_efficiencyMapReplicaArray[EffiHistoIdent(period, encodeHistoName(periodName, triggerName, isData, "repl", isBarrel))] = generateReplicas(tmp_h2, m_nReplicas, m_ReplicaRandomSeed);
255 }
256 }
257 }
258 }
259 }
263 return StatusCode::SUCCESS;
264 }
265
266
267
268 StatusCode MuonTriggerScaleFactors::initialize() {
269
270 ATH_MSG_INFO(
"MuonQuality = '" << m_muonQuality.value() <<
"'");
273 ATH_MSG_INFO(
"CalibrationRelease = '" << m_calibrationVersion.value() <<
"'");
274 ATH_MSG_INFO(
"CustomInputFolder = '" << m_customInputFolder.value() <<
"'");
277
279
280 if (registerSystematics() != StatusCode::SUCCESS) {
281 return StatusCode::FAILURE;
282 }
283
286 return StatusCode::FAILURE;
287 }
288
289 for (auto trigToy : m_replicaTriggerList)
290 m_replicaSet.insert(trigToy);
291
292
293 if (m_campaign.empty()) {
294 constexpr auto years_to_run = std::to_array<int>({2015, 2016, 2017, 2018, 2022, 2023, 2024, 2025});
295 for (const int &year: years_to_run) {
297 }
298 } else if (m_campaign.value() == "mc20a") {
301 } else if (m_campaign.value() == "mc20d") {
303 } else if (m_campaign.value() == "mc20e") {
305 } else if (m_campaign.value() == "mc23a") {
307 } else if (m_campaign.value() == "mc23d") {
309 } else if (m_campaign.value() == "mc23e") {
311 } else if (m_campaign.value() == "mc23g") {
313 } else {
314 ATH_MSG_ERROR(
"Campaign " << m_campaign.value() <<
" is not supported. Please choose a valid campaign or leave empty to load all years.");
315 }
316 return StatusCode::SUCCESS;
317 }
318
319 CP::CorrectionCode MuonTriggerScaleFactors::getTriggerScaleFactor(
const xAOD::Muon& muon, Double_t& triggersf,
const std::string& trigger)
const {
320 if(!m_experimental){
321 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor This is an experimental function. If you really know what you are doing set UseExperimental property.");
323 }
324
325 if (trigger.empty()) {
326 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor Trigger must have value.");
328 }
329
331
332 if (trigger == "HLT_mu8noL1")
333 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.");
334 else if (trigger.find("HLT_2mu10") != std::string::npos || trigger.find("HLT_2mu14") != std::string::npos)
335 ATH_MSG_WARNING(
"Di-muon trigger scale factors for single reco muons are not supported!");
336 else
337 return GetTriggerSF(triggersf, configuration, muon, trigger);
339 }
340
342 if (trigger.empty()) {
343 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor Trigger must have value.");
345 }
346
348
349 if (trigger == "HLT_mu8noL1") {
350 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.");
351 } else if (trigger.find("HLT_2mu10") != std::string::npos || trigger.find("HLT_2mu14") != std::string::npos) {
354 } else {
357 }
359 }
360
361
362
363
364
365
366
367 int MuonTriggerScaleFactors::getReplica_index(const std::string& sysBaseName, const std::string& trigStr) const{
368 if (m_replicaSet.find(trigStr) == m_replicaSet.end()) return -1;
369 std::size_t
pos = sysBaseName.find(
"MCTOY");
370 if (pos == std::string::npos) return -1;
371 return atoi(sysBaseName.substr(pos + 5, pos + 8).c_str());
372 }
373
375 if (trigger.empty()) {
376 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerEfficiency Trigger must have value.");
378 }
388 }
389
390
395
396 std::string systype = "";
397 if (appliedSystematics().matchSystematic(syst_down) && !dataType) {
398 systype = "syst_down";
399 } else if (appliedSystematics().matchSystematic(syst_up) && !dataType) {
400 systype = "syst_up";
401 } else if (appliedSystematics().matchSystematic(stat_down)) {
402 systype = "stat_down";
403 } else if (appliedSystematics().matchSystematic(stat_up)) {
404 systype = "stat_up";
405 } else {
406 systype = "nominal";
407 }
408
409
410
411
412
413
414 if (!appliedSystematics().
empty() && configuration.
isData ==
true) {
416 if (configuration.
replicaIndex != -1) systype =
"replicas";
417 }
420 }
421
423
425
426
427
428
429
430
431 std::vector<TH1_Ptr> MuonTriggerScaleFactors::generateReplicas(TH1_Ptr
h,
int nrep,
int seed)
const {
432 TRandom3 Rndm(seed);
433 std::vector<TH1_Ptr> replica_v;
434 const int xbins =
h->GetNbinsX(),
ybins =
h->GetNbinsY();
435
436 for (
int t = 0;
t < nrep; ++
t) {
437 TH2* replica =
dynamic_cast<TH2*
>(
h->Clone(Form(
"rep%d_%s", t,
h->GetName())));
438
439 for (
int x_i = 0; x_i <=
xbins; ++x_i) {
440 for (
int y_i = 0; y_i <=
ybins; ++y_i) {
441 replica->SetBinContent(x_i, y_i, Rndm.Gaus(
h->GetBinContent(x_i, y_i),
h->GetBinError(x_i, y_i)));
442 }
443 }
444 replica_v.push_back(TH1_Ptr(replica));
445 }
446 return replica_v;
447 }
448
449 bool MuonTriggerScaleFactors::isTriggerSupported(const std::string& trigger) const{
450 TH1_Ptr H1 = getEfficiencyHistogram(trigger, true, "nominal");
451 return H1.get() != nullptr;
452 }
453
454 int MuonTriggerScaleFactors::getBinNumber(
const xAOD::Muon& muon,
const std::string& trigger)
const{
455 if(!m_experimental){
456 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor This is an experimental function. If you really know what you are doing set UseExperimental property.");
458 }
459
462 bool isBarrel = std::abs(mu_eta) < muon_barrel_endcap_boundary;
463 TH1_Ptr cit = getEfficiencyHistogram(trigger, true, "nominal", isBarrel);
464 if(!cit.get()){
465 if(!m_allowZeroSF)
466 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." );
467 return -1;
468 }
469 auto eff_h2 = cit;
470 double mu_phi_corr =
mu_phi;
471 if (mu_phi_corr < eff_h2->GetYaxis()->GetXmin()) mu_phi_corr += 2.0 *
M_PI;
472 if (mu_phi_corr > eff_h2->GetYaxis()->GetXmax()) mu_phi_corr -= 2.0 *
M_PI;
473 return eff_h2->FindFixBin(mu_eta, mu_phi_corr);
474 }
475
476 unsigned int MuonTriggerScaleFactors::encodeHistoName(const std::string_view period, const std::string& Trigger, bool isData, const std::string& Systematic, bool isBarrel) const {
477
479 return std::hash<std::string>()(
histName);
480 }
481
482 unsigned int MuonTriggerScaleFactors::encodeHistoName(
const std::string& Trigger,
const TrigMuonEff::Configuration& configuration,
const std::string& Systematic,
bool isBarrel)
const {
483
484 return encodeHistoName(getDataPeriod(), Trigger, configuration.
isData, Systematic, isBarrel);
485
486 }
487 TH1_Ptr MuonTriggerScaleFactors::getEfficiencyHistogram(unsigned int year, const std::string_view period, const std::string& trigger, bool isData, const std::string& Systematic, bool isBarrel) const {
488 EffiHistoIdent Ident = EffiHistoIdent(YearPeriod(year, period), encodeHistoName(period, trigger, isData, Systematic, isBarrel));
489 EfficiencyMap::const_iterator Itr = m_efficiencyMap.find(Ident);
490
491 if (Itr == m_efficiencyMap.end()) {
492 return TH1_Ptr();
493 }
494 return Itr->second;
495 }
496 TH1_Ptr MuonTriggerScaleFactors::getEfficiencyHistogram(const std::string& trigger, bool isData, const std::string& Systematic, bool isBarrel) const {
497 unsigned int run = getRunNumber();
498 return getEfficiencyHistogram(getYear(
run), getDataPeriod(
run), trigger, isData, Systematic, isBarrel);
499 }
500
504 bool isBarrel = std::abs(mu_eta) < muon_barrel_endcap_boundary;
505
506 TH1_Ptr eff_h2 = nullptr;
508
509 unsigned int run = getRunNumber();
510 EffiHistoIdent Ident = EffiHistoIdent(YearPeriod(getYear(
run), getDataPeriod(
run)), encodeHistoName(getDataPeriod(
run), trigger, configuration.
isData,
"repl", isBarrel));
511 std::map<EffiHistoIdent, std::vector<TH1_Ptr> >
::const_iterator cit = m_efficiencyMapReplicaArray.find(Ident);
512 if (cit == m_efficiencyMapReplicaArray.end()) {
513 if (m_allowZeroSF) {
514 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.");
517 }
518
519 else {
520 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.");
522 }
523 }
524
525 if (configuration.
replicaIndex >= (
int) cit->second.size()) {
526 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getMuonEfficiency ; index for replicated histograms is out of range.");
528 }
529
531 } else {
532 TH1_Ptr cit = getEfficiencyHistogram(trigger, configuration.
isData, systematic, isBarrel);
533 if (cit.get() == nullptr) {
534 if (m_allowZeroSF) {
535 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.");
538 } else {
539 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.");
541 }
542 }
543 eff_h2 = cit;
544 }
545
546 double mu_phi_corr =
mu_phi;
547 if (mu_phi_corr < eff_h2->GetYaxis()->GetXmin()) mu_phi_corr += 2.0 *
M_PI;
548 if (mu_phi_corr > eff_h2->GetYaxis()->GetXmax()) mu_phi_corr -= 2.0 *
M_PI;
549
550 const int bin = eff_h2->FindFixBin(mu_eta, mu_phi_corr);
552
554
555 ATH_MSG_DEBUG(
"getMuonEfficiency [eta,phi,phi_corr]=[" << mu_eta <<
"," << mu_phi <<
"," << mu_phi_corr <<
"], ibin=" <<
bin <<
" eff=" << eff);
556
558
559 }
560
562
563 if (mucont.
size() != 2) {
564 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::GetTriggerSF;Currently dimuon trigger chains only implemented for events with exactly 2 muons.");
565 }
567
568 Double_t eff_data = 0;
569 Double_t eff_mc = 0;
570
571 std::string data_err = "";
572 std::string mc_err = "";
573
575 data_err = "nominal";
576 mc_err = "syst_up";
578 data_err = "nominal";
579 mc_err = "syst_down";
580 }
else if (appliedSystematics().matchSystematic(
CP::SystematicVariation(
"MUON_EFF_TrigStatUncertainty", -1))) {
581 data_err = "stat_down";
582 mc_err = "nominal";
584 data_err = "stat_up";
585 mc_err = "nominal";
586 } else {
587 data_err = "nominal";
588 mc_err = "nominal";
589 }
590
591
592
593
594
595
596 if (!appliedSystematics().
empty()) {
598 if (configuration.
replicaIndex != -1) data_err =
"replicas";
599 }
600
601 configuration.
isData =
true;
604
605 configuration.
isData =
false;
607 result = getDimuonEfficiency(eff_mc, configuration, mucont, trigger, mc_err);
609
610 double event_SF = 1.;
611
612 if (std::abs(1. - eff_mc) > 0.0001) {
613 event_SF = eff_data / eff_mc;
614 }
615
616 TriggerSF = event_SF;
618 }
619
624
625 double rate_not_fired_data = 1.;
626 double rate_not_fired_mc = 1.;
627
628 for (const auto mu : mucont) {
629
630 double eff_data = 0., eff_mc = 0.;
631
633
634 eff_data = 0.;
635 eff_mc = 0.;
636
637 } else {
638
639 std::string muon_trigger_name = trigger;
640 std::string data_err = "";
641 std::string mc_err = "";
642
643
648
649 if (appliedSystematics().matchSystematic(syst_down)) {
650 data_err = "nominal";
651 mc_err = "syst_up";
652 } else if (appliedSystematics().matchSystematic(syst_up)) {
653 data_err = "nominal";
654 mc_err = "syst_down";
655 } else if (appliedSystematics().matchSystematic(stat_down)) {
656 data_err = "stat_down";
657 mc_err = "nominal";
658 } else if (appliedSystematics().matchSystematic(stat_up)) {
659 data_err = "stat_up";
660 mc_err = "nominal";
661 } else {
662 data_err = "nominal";
663 mc_err = "nominal";
664 }
665
666
667
668
669
670
671 if (!appliedSystematics().
empty()) {
673 if (configuration.
replicaIndex != -1) data_err =
"replicas";
674 }
675
676 configuration.
isData =
true;
677 CP::CorrectionCode result_data = getMuonEfficiency(eff_data, configuration, *mu, muon_trigger_name, data_err);
679 configuration.
isData =
false;
681 CP::CorrectionCode result_mc = getMuonEfficiency(eff_mc, configuration, *mu, muon_trigger_name, mc_err);
683 }
684 rate_not_fired_data *= (1. - eff_data);
685 rate_not_fired_mc *= (1. - eff_mc);
686 }
687
688 double event_SF = 1.;
689 if (1 - rate_not_fired_data == 0) event_SF = 0;
690 if ((mucont.size()) and (std::abs(1. - rate_not_fired_mc) > 0.0001)) {
691
692 event_SF = (1. - rate_not_fired_data) / (1. - rate_not_fired_mc);
693 }
694 TriggerSF = event_SF;
695
697 }
698
704
705 double eff_data = 0., eff_mc = 0.;
706
708 eff_data = 0.;
709 eff_mc = 0.;
710 TriggerSF = 1.;
712 }
713
714 std::string muon_trigger_name = trigger;
715 std::string data_err = "";
716 std::string mc_err = "";
717
718
723
724 if (appliedSystematics().matchSystematic(syst_down)) {
725 data_err = "nominal";
726 mc_err = "syst_up";
727 } else if (appliedSystematics().matchSystematic(syst_up)) {
728 data_err = "nominal";
729 mc_err = "syst_down";
730 } else if (appliedSystematics().matchSystematic(stat_down)) {
731 data_err = "stat_down";
732 mc_err = "nominal";
733 } else if (appliedSystematics().matchSystematic(stat_up)) {
734 data_err = "stat_up";
735 mc_err = "nominal";
736 } else {
737 data_err = "nominal";
738 mc_err = "nominal";
739 }
740
741 if (!appliedSystematics().
empty()) {
743 if (configuration.
replicaIndex != -1) data_err =
"replicas";
744 }
745
746 configuration.
isData =
true;
747 CP::CorrectionCode result_data = getMuonEfficiency(eff_data, configuration, mu, muon_trigger_name, data_err);
749 return result_data;
750 configuration.
isData =
false;
752 CP::CorrectionCode result_mc = getMuonEfficiency(eff_mc, configuration, mu, muon_trigger_name, mc_err);
754 return result_mc;
755 if (eff_data == 0)
756 TriggerSF = 0;
757 if (std::abs(eff_mc) > 0.0001)
758 TriggerSF = eff_data / eff_mc;
760 }
761
763
764 std::string trigger = getTriggerCorrespondingToDimuonTrigger(chain);
768
771
772 Double_t eff1 = 0;
774 CP::CorrectionCode result1 = getMuonEfficiency(eff1, configuration, (**mu1), trigger, systematic);
776 }
777 Double_t eff2 = 0;
779 CP::CorrectionCode result2 = getMuonEfficiency(eff2, configuration, (**mu2), trigger, systematic);
781 }
782
785 }
786
787 std::string MuonTriggerScaleFactors::getTriggerCorrespondingToDimuonTrigger(const std::string& trigger) const {
788 if (trigger.find("2mu10") != std::string::npos) return "HLT_mu10";
789 if (trigger.find("2mu14") != std::string::npos) return "HLT_mu14";
790 throw std::runtime_error("Unknown dimuon trigger");
791 }
792
794 std::size_t
index = trigger.find(
"HLT_mu");
795 if (
index != std::string::npos) {
796 std::string rawNumber = trigger.substr(
index + 6);
797 if (!rawNumber.empty() && isdigit(rawNumber[0])) {
798 std::stringstream(rawNumber) >>
threshold;
802 }
803 }
804 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getThreshold Could not extract threshold for trigger " << trigger);
806 }
807
808 unsigned int MuonTriggerScaleFactors::getYear(
unsigned int run)
const {
809 if(m_forceYear != -1) return m_forceYear;
810
811 auto runCheck = RunYear{
run,2050};
812 auto lower = std::ranges::lower_bound(runYears, runCheck, [](
const auto &s1,
const auto &s2) {
return s1.lastRun <
s2.lastRun; });
813 return (lower != runYears.end()) ? lower->year : runCheck.year;
814 }
815
816 const std::string_view MuonTriggerScaleFactors::getDataPeriod() const {
817 return getDataPeriod(getRunNumber());
818 }
819
820 const std::string_view MuonTriggerScaleFactors::getDataPeriod(
unsigned int run)
const {
821 return getDataPeriod(
run, getYear(
run));
822 }
823
824 const std::string_view MuonTriggerScaleFactors::getDataPeriod(unsigned int runNumber, unsigned year) const {
825 if(!m_forcePeriod.empty()) return std::string_view{m_forcePeriod};
826
827 auto yit = m_year_periods.find(year);
828 if (yit != m_year_periods.end()) {
829 auto runit = std::find_if(yit->second.begin(), yit->second.end(), [&runNumber](const auto &item){return runNumber >= std::get<0>(item) && runNumber <= std::get<1>(item);});
830 if (runit != yit->second.end()) return std::get<2>(*runit);
831 else {
832 ATH_MSG_FATAL(
"RunNumber " << runNumber <<
" does not belong to any data period in " << year);
833 throw std::invalid_argument{""};
834 }
835 }
836 else {
838 throw std::invalid_argument{""};
839 }
840 }
841
842 unsigned int MuonTriggerScaleFactors::getRunNumber() const {
845 if (
info.operator->()==
nullptr) {
846 ATH_MSG_FATAL(
"Could not retrieve the xAOD::EventInfo with name: " << m_eventInfo.key() <<
". Exiting the code.");
847 throw std::invalid_argument{""};
848 }
850 ATH_MSG_DEBUG(
"The current event is a data event. Return runNumber instead.");
851 return info->runNumber();
852 }
853 if (!acc_rnd.isAvailable(*info)) {
854 if(m_forceYear == -1 && m_forcePeriod == "")
855 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");
856 throw std::invalid_argument{""};
857 } else if (acc_rnd(*info) == 0) {
858 ATH_MSG_FATAL(
"Pile up tool has given runNumber 0. Exiting the code.");
859 throw std::invalid_argument{""};
860 }
861
862
863 return acc_rnd(*info);
864 }
865
866 TDirectory* MuonTriggerScaleFactors::getTemporaryDirectory(void) const {
867 gROOT->cd();
868 TDirectory* tempDir = 0;
870 while (not tempDir) {
873 if (gROOT->GetDirectory((
dirname.str()).c_str())) {
875 continue;
876 }
877 tempDir = gROOT->mkdir((
dirname.str()).c_str());
878 if (not tempDir) {
879 ATH_MSG_ERROR(
"getTemporaryDirectory::Temporary directory could not be created");
880 }
881 }
882 return tempDir;
883 }
884
885
886
887
889 if (!systematic.
empty()) {
891 return sys.find(systematic) !=
sys.end();
892 }
893 return true;
894 }
895
899
902
903
904 if (m_replicaTriggerList.size() == 0) {
907 } else {
908 for (
int i = 0;
i < m_nReplicas; ++
i) {
910 }
911 }
912
913 return mySysSet;
914 }
915
916
917 StatusCode MuonTriggerScaleFactors::registerSystematics() {
919 if (
registry.registerSystematics(*
this) != StatusCode::SUCCESS) {
920 ATH_MSG_ERROR(
"Failed to add systematic to list of recommended systematics.");
921 return StatusCode::FAILURE;
922 }
923 return StatusCode::SUCCESS;
924 }
925
928 return affectingSystematics();
929 }
930
932
933 auto itr = m_systFilter.find(systConfig);
934
935
936 if (itr == m_systFilter.end()) {
937
938
942 ATH_MSG_ERROR(
"Unsupported combination of systematics passed to the tool!");
943 return StatusCode::FAILURE;
944 }
945
946
947 itr = m_systFilter.
insert(std::make_pair(systConfig, filteredSys)).first;
948 }
949
951
952
953
958
960 return StatusCode::FAILURE;
961 }
962
963 m_appliedSystematics = &mySysConf;
964 return StatusCode::SUCCESS;
965 }
966
967}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
CP::CorrectionCode getThreshold(Int_t &threshold, const std::string &trigger)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
size_t size() const
Number of registered mappings.
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.
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.
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
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.
Helper class to provide constant type-safe access to aux data.
@ 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="")
int atoi(std::string_view str)
Helper functions to unpack numbers decoded in string into integers and doubles The strings are requir...
::StatusCode StatusCode
StatusCode definition for legacy code.
path
python interpreter configuration --------------------------------------—
TH2F(name, title, nxbins, bins_par2, bins_par3, bins_par4, bins_par5=None, bins_par6=None, path='', **kwargs)
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
int run(int argc, char *argv[])
std::string dirname(std::string name)
std::string basename(std::string name)