27namespace ADD_CMODE(CP) {
28 constexpr double muon_barrel_endcap_boundary = 1.05;
31 unsigned int lastRun{};
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},
46 const std::map<unsigned short int, std::vector< std::tuple<unsigned int,unsigned int,std::string_view> > > MuonTriggerScaleFactors::m_year_periods = {
61 {302737,302872,
"D1D3"},
62 {302919,303560,
"D4D8"},
130 MuonTriggerScaleFactors::MuonTriggerScaleFactors(
const std::string& name) :
133 MuonTriggerScaleFactors::~MuonTriggerScaleFactors() { }
135 StatusCode MuonTriggerScaleFactors::LoadTriggerMap(
unsigned int year) {
136 std::string fileName;
137 if (m_customInputFilePerYear.value().contains(year)) {
138 fileName = m_customInputFilePerYear.value().at(year);
139 if (fileName.empty()) {
140 ANA_MSG_INFO(
"Skipping loading trigger SF for year " << year <<
" since the provided file name is empty");
141 return StatusCode::SUCCESS;
143 ATH_MSG_INFO(
"Loading trigger SF from user specified file " << fileName <<
" for year " << year);
147 if (fileName.empty()) {
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";
158 return StatusCode::SUCCESS;
162 TDirectory* origDir = gDirectory;
164 std::string filePath;
166 if (m_customInputFolder.empty()) {
167 filePath =
PathResolverFindCalibFile(Form(
"MuonEfficiencyCorrections/%s/%s", m_calibrationVersion.value().c_str(), fileName.c_str()));
168 if (filePath.empty()) {
169 ATH_MSG_ERROR(
"Unable to resolve the input file " << fileName <<
" via PathResolver.");
173 ATH_MSG_INFO(
"Note: setting up with user specified input file location " << m_customInputFolder.value() <<
" - this is not encouraged!");
177 TFile*
file = TFile::Open(filePath.c_str());
179 if (
file ==
nullptr || !
file->IsOpen()) {
180 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::initialize Couldn't open file " << filePath);
181 return StatusCode::FAILURE;
183 TDirectory* tempDir = getTemporaryDirectory();
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";
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;
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());
203 std::string periodName_InMap = periodName.substr(std::string(
"Period").
size(), periodName.size());
204 YearPeriod period = YearPeriod(year, periodName_InMap);
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");
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()));
226 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::initialize " << path <<
" not found under trigger " << triggerName <<
" and period " << periodName <<
" for year: " << year);
229 hist->SetDirectory(0);
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;
236 m_efficiencyMap.insert(std::pair<EffiHistoIdent, TH1_Ptr>(HistoId, std::shared_ptr < TH1 > (hist)));
241 if (m_replicaSet.find(triggerName) != m_replicaSet.end() && itype.find(
"data") != std::string::npos) {
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);
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);
254 m_efficiencyMapReplicaArray[EffiHistoIdent(period, encodeHistoName(periodName, triggerName, isData,
"repl", isBarrel))] = generateReplicas(tmp_h2, m_nReplicas, m_ReplicaRandomSeed);
263 return StatusCode::SUCCESS;
268 StatusCode MuonTriggerScaleFactors::initialize() {
270 ATH_MSG_INFO(
"MuonQuality = '" << m_muonQuality.value() <<
"'");
273 ATH_MSG_INFO(
"CalibrationRelease = '" << m_calibrationVersion.value() <<
"'");
274 ATH_MSG_INFO(
"CustomInputFolder = '" << m_customInputFolder.value() <<
"'");
280 if (registerSystematics() != StatusCode::SUCCESS) {
281 return StatusCode::FAILURE;
286 return StatusCode::FAILURE;
289 for (
auto trigToy : m_replicaTriggerList)
290 m_replicaSet.insert(trigToy);
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) {
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") {
314 ATH_MSG_ERROR(
"Campaign " << m_campaign.value() <<
" is not supported. Please choose a valid campaign or leave empty to load all years.");
316 return StatusCode::SUCCESS;
319 CP::CorrectionCode MuonTriggerScaleFactors::getTriggerScaleFactor(
const xAOD::Muon& muon, Double_t& triggersf,
const std::string& trigger)
const {
321 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor This is an experimental function. If you really know what you are doing set UseExperimental property.");
325 if (trigger.empty()) {
326 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor Trigger must have value.");
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!");
337 return GetTriggerSF(triggersf, configuration, muon, trigger);
342 if (trigger.empty()) {
343 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor Trigger must have value.");
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) {
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());
375 if (trigger.empty()) {
376 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerEfficiency Trigger must have value.");
380 configuration.
isData = dataType;
396 std::string systype =
"";
397 if (appliedSystematics().matchSystematic(syst_down) && !dataType) {
398 systype =
"syst_down";
399 }
else if (appliedSystematics().matchSystematic(syst_up) && !dataType) {
401 }
else if (appliedSystematics().matchSystematic(stat_down)) {
402 systype =
"stat_down";
403 }
else if (appliedSystematics().matchSystematic(stat_up)) {
414 if (!appliedSystematics().
empty() && configuration.
isData ==
true) {
415 configuration.
replicaIndex = getReplica_index(appliedSystematics().begin()->
basename(), trigger);
416 if (configuration.
replicaIndex != -1) systype =
"replicas";
431 std::vector<TH1_Ptr> MuonTriggerScaleFactors::generateReplicas(TH1_Ptr
h,
int nrep,
int seed)
const {
433 std::vector<TH1_Ptr> replica_v;
434 const int xbins =
h->GetNbinsX(), ybins =
h->GetNbinsY();
436 for (
int t = 0; t < nrep; ++t) {
437 TH2* replica =
dynamic_cast<TH2*
>(
h->Clone(Form(
"rep%d_%s", t,
h->GetName())));
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)));
444 replica_v.push_back(TH1_Ptr(replica));
449 bool MuonTriggerScaleFactors::isTriggerSupported(
const std::string& trigger)
const{
450 TH1_Ptr H1 = getEfficiencyHistogram(trigger,
true,
"nominal");
451 return H1.get() !=
nullptr;
454 int MuonTriggerScaleFactors::getBinNumber(
const xAOD::Muon& muon,
const std::string& trigger)
const{
456 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getTriggerScaleFactor This is an experimental function. If you really know what you are doing set UseExperimental property.");
460 const double mu_eta = muon.eta();
461 const double mu_phi = muon.phi();
462 bool isBarrel = std::abs(mu_eta) < muon_barrel_endcap_boundary;
463 TH1_Ptr cit = getEfficiencyHistogram(trigger,
true,
"nominal", isBarrel);
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." );
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);
476 unsigned int MuonTriggerScaleFactors::encodeHistoName(
const std::string_view period,
const std::string& Trigger,
bool isData,
const std::string& Systematic,
bool isBarrel)
const {
478 const std::string histName = std::string{period} +
"_" + Trigger +
"_" + (isBarrel ?
"b" :
"e") +
"_" + (isData ?
"data" :
"mc") + Systematic;
479 return std::hash<std::string>()(histName);
482 unsigned int MuonTriggerScaleFactors::encodeHistoName(
const std::string& Trigger,
const TrigMuonEff::Configuration& configuration,
const std::string& Systematic,
bool isBarrel)
const {
484 return encodeHistoName(getDataPeriod(), Trigger, configuration.
isData, Systematic, isBarrel);
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);
491 if (Itr == m_efficiencyMap.end()) {
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);
502 const double mu_eta = muon.eta();
503 const double mu_phi = muon.phi();
504 bool isBarrel = std::abs(mu_eta) < muon_barrel_endcap_boundary;
506 TH1_Ptr eff_h2 =
nullptr;
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()) {
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.");
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.");
525 if (configuration.
replicaIndex >= (
int) cit->second.size()) {
526 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getMuonEfficiency ; index for replicated histograms is out of range.");
532 TH1_Ptr cit = getEfficiencyHistogram(trigger, configuration.
isData, systematic, isBarrel);
533 if (cit.get() ==
nullptr) {
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.");
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.");
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;
550 const int bin = eff_h2->FindFixBin(mu_eta, mu_phi_corr);
555 ATH_MSG_DEBUG(
"getMuonEfficiency [eta,phi,phi_corr]=[" << mu_eta <<
"," << mu_phi <<
"," << mu_phi_corr <<
"], ibin=" <<
bin <<
" eff=" << eff);
563 if (mucont.
size() != 2) {
564 ATH_MSG_FATAL(
"MuonTriggerScaleFactors::GetTriggerSF;Currently dimuon trigger chains only implemented for events with exactly 2 muons.");
568 Double_t eff_data = 0;
571 std::string data_err =
"";
572 std::string mc_err =
"";
575 data_err =
"nominal";
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";
584 data_err =
"stat_up";
587 data_err =
"nominal";
596 if (!appliedSystematics().
empty()) {
597 configuration.
replicaIndex = getReplica_index(appliedSystematics().begin()->
basename(), trigger);
598 if (configuration.
replicaIndex != -1) data_err =
"replicas";
601 configuration.
isData =
true;
602 CP::CorrectionCode result = getDimuonEfficiency(eff_data, configuration, mucont, trigger, data_err);
605 configuration.
isData =
false;
607 result = getDimuonEfficiency(eff_mc, configuration, mucont, trigger, mc_err);
610 double event_SF = 1.;
612 if (std::abs(1. - eff_mc) > 0.0001) {
613 event_SF = eff_data / eff_mc;
616 TriggerSF = event_SF;
625 double rate_not_fired_data = 1.;
626 double rate_not_fired_mc = 1.;
628 for (
const auto mu : mucont) {
630 double eff_data = 0., eff_mc = 0.;
639 std::string muon_trigger_name = trigger;
640 std::string data_err =
"";
641 std::string mc_err =
"";
649 if (appliedSystematics().matchSystematic(syst_down)) {
650 data_err =
"nominal";
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";
658 }
else if (appliedSystematics().matchSystematic(stat_up)) {
659 data_err =
"stat_up";
662 data_err =
"nominal";
671 if (!appliedSystematics().
empty()) {
672 configuration.
replicaIndex = getReplica_index(appliedSystematics().begin()->
basename(), trigger);
673 if (configuration.
replicaIndex != -1) data_err =
"replicas";
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);
684 rate_not_fired_data *= (1. - eff_data);
685 rate_not_fired_mc *= (1. - eff_mc);
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)) {
692 event_SF = (1. - rate_not_fired_data) / (1. - rate_not_fired_mc);
694 TriggerSF = event_SF;
705 double eff_data = 0., eff_mc = 0.;
714 std::string muon_trigger_name = trigger;
715 std::string data_err =
"";
716 std::string mc_err =
"";
724 if (appliedSystematics().matchSystematic(syst_down)) {
725 data_err =
"nominal";
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";
733 }
else if (appliedSystematics().matchSystematic(stat_up)) {
734 data_err =
"stat_up";
737 data_err =
"nominal";
741 if (!appliedSystematics().
empty()) {
742 configuration.
replicaIndex = getReplica_index(appliedSystematics().begin()->
basename(), trigger);
743 if (configuration.
replicaIndex != -1) data_err =
"replicas";
746 configuration.
isData =
true;
747 CP::CorrectionCode result_data = getMuonEfficiency(eff_data, configuration, mu, muon_trigger_name, data_err);
750 configuration.
isData =
false;
752 CP::CorrectionCode result_mc = getMuonEfficiency(eff_mc, configuration, mu, muon_trigger_name, mc_err);
757 if (std::abs(eff_mc) > 0.0001)
758 TriggerSF = eff_data / eff_mc;
764 std::string trigger = getTriggerCorrespondingToDimuonTrigger(chain);
774 CP::CorrectionCode result1 = getMuonEfficiency(eff1, configuration, (**mu1), trigger, systematic);
779 CP::CorrectionCode result2 = getMuonEfficiency(eff2, configuration, (**mu2), trigger, systematic);
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");
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;
804 ATH_MSG_ERROR(
"MuonTriggerScaleFactors::getThreshold Could not extract threshold for trigger " << trigger);
808 unsigned int MuonTriggerScaleFactors::getYear(
unsigned int run)
const {
809 if(m_forceYear != -1)
return m_forceYear;
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;
816 const std::string_view MuonTriggerScaleFactors::getDataPeriod()
const {
817 return getDataPeriod(getRunNumber());
820 const std::string_view MuonTriggerScaleFactors::getDataPeriod(
unsigned int run)
const {
821 return getDataPeriod(
run, getYear(
run));
824 const std::string_view MuonTriggerScaleFactors::getDataPeriod(
unsigned int runNumber,
unsigned year)
const {
825 if(!m_forcePeriod.empty())
return std::string_view{m_forcePeriod};
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);
832 ATH_MSG_FATAL(
"RunNumber " << runNumber <<
" does not belong to any data period in " << year);
833 throw std::invalid_argument{
""};
838 throw std::invalid_argument{
""};
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{
""};
850 ATH_MSG_DEBUG(
"The current event is a data event. Return runNumber instead.");
851 return info->runNumber();
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{
""};
863 return acc_rnd(*info);
866 TDirectory* MuonTriggerScaleFactors::getTemporaryDirectory(
void)
const {
868 TDirectory* tempDir = 0;
870 while (not tempDir) {
872 dirname <<
"MuonTriggerScaleFactorsTempDir_%i" << counter;
873 if (gROOT->GetDirectory((
dirname.str()).c_str())) {
877 tempDir = gROOT->mkdir((
dirname.str()).c_str());
879 ATH_MSG_ERROR(
"getTemporaryDirectory::Temporary directory could not be created");
889 if (!systematic.
empty()) {
891 return sys.find(systematic) != sys.end();
904 if (m_replicaTriggerList.size() == 0) {
908 for (
int i = 0; i < m_nReplicas; ++i) {
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;
923 return StatusCode::SUCCESS;
928 return affectingSystematics();
931 StatusCode MuonTriggerScaleFactors::applySystematicVariation(
const CP::SystematicSet& systConfig){
933 auto itr = m_systFilter.find(systConfig);
936 if (itr == m_systFilter.end()) {
942 ATH_MSG_ERROR(
"Unsupported combination of systematics passed to the tool!");
943 return StatusCode::FAILURE;
947 itr = m_systFilter.
insert(std::make_pair(systConfig, filteredSys)).first;
960 return StatusCode::FAILURE;
963 m_appliedSystematics = &mySysConf;
964 return StatusCode::SUCCESS;