948 def makeAlgs (self, config) :
949
950 if config.dataType() is not DataType.Data:
951 log = logging.getLogger('ElectronTriggerSFConfig')
952
953 if self.includeAllYearsPerRun and not self.useToolKeyAsOutput:
954 log.warning('`includeAllYearsPerRun` is set to True, but `useToolKeyAsOutput` is set to False. '
955 'This will cause multiple branches to be written out with the same content.')
956
957
958
959
960 triggerDict = TriggerDict()
961
962
963 version_Run2 = "2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v3"
964 map_Run2 = f"ElectronEfficiencyCorrection/{version_Run2}/map1.txt"
965 version_Run3 = "2015_2025/rel22.2/2025_Run3_Consolidated_Recommendation_v4"
966 map_Run3 = f"ElectronEfficiencyCorrection/{version_Run3}/map2.txt"
967
968 version = version_Run2 if config.geometry() is LHCPeriod.Run2 else version_Run3
969
970
971
972 mapKeysDict = MapKeysDict(version)
973
974
975 def filterConfFromMap(conf, electronMapKeys):
976 if not conf:
977 raise ValueError("No configuration found for trigger chain.")
978 if len(conf) == 1:
979 return conf[0]
980
981 for c in conf:
982 if c in electronMapKeys:
983 return c
984
985 return conf[0]
986
987 if self.includeAllYearsPerRun:
988 years = [int(year) for year in self.triggerChainsPerYear.keys()]
989 else:
990 from TriggerAnalysisAlgorithms.TriggerAnalysisSFConfig import (
991 get_input_years)
992 years = get_input_years(config)
993
994
995 import ROOT
996 triggerChainsPerYear_Run2 = {}
997 triggerChainsPerYear_Run3 = {}
998 for year, chains in self.triggerChainsPerYear.items():
999 if not chains:
1000 warnings.warn_explicit(
1001 f"No trigger chains configured for year {year}."
1002 " Assuming this is intended, no Electron trigger SF"
1003 " will be computed.",
1004 TriggerSFWarning, filename='', lineno=0)
1005 continue
1006
1007 chains_split = [chain.replace(
"HLT_",
"").
replace(
" || ",
"_OR_")
for chain
in chains]
1008 if int(year) >= 2022:
1009 triggerChainsPerYear_Run3[
str(year)] =
' || '.join(chains_split)
1010 else:
1011 triggerChainsPerYear_Run2[
str(year)] =
' || '.join(chains_split)
1012 electronMapKeys_Run2 = ROOT.std.map("string", "string")()
1013 electronMapKeys_Run3 = ROOT.std.map("string", "string")()
1014
1015 sc_Run2 = ROOT.TrigGlobalEfficiencyCorrectionTool.suggestElectronMapKeys(triggerChainsPerYear_Run2, version_Run2, electronMapKeys_Run2)
1016 sc_Run3 = ROOT.TrigGlobalEfficiencyCorrectionTool.suggestElectronMapKeys(triggerChainsPerYear_Run3, version_Run3, electronMapKeys_Run3)
1017 if sc_Run2.code() != 2 or sc_Run3.code() != 2:
1018 raise RuntimeError("Failed to suggest electron map keys")
1019 electronMapKeys = dict(electronMapKeys_Run2) | dict(electronMapKeys_Run3)
1020
1021
1022 from TriggerAnalysisAlgorithms.TriggerAnalysisConfig import is_year_in_current_period
1023 triggerConfigs = {}
1024 for year in years:
1025 if not is_year_in_current_period(config, year):
1026 continue
1027
1028 triggerChains = self.triggerChainsPerYear.
get(int(year), self.triggerChainsPerYear.
get(
str(year), []))
1029 for chain in triggerChains:
1030 chain = chain.replace(" || ", "_OR_")
1031 chain_noHLT = chain.replace("HLT_", "")
1032 chain_out = chain_noHLT if self.removeHLTPrefix else chain
1033 legs = triggerDict[chain_noHLT]
1034 if not legs:
1035 if chain_noHLT[0] == 'e' and chain_noHLT[1].isdigit:
1036 chain_key = f"{year}_{chain_noHLT}"
1037 chain_conf = mapKeysDict[chain_key][0]
1038 triggerConfigs[chain_conf if self.useToolKeyAsOutput else chain_out] = chain_conf
1039 else:
1040 for leg in legs:
1041 if leg[0] == 'e' and leg[1].isdigit:
1042 leg_out = leg if self.removeHLTPrefix else f"HLT_{leg}"
1043 leg_key = f"{year}_{leg}"
1044 leg_conf = filterConfFromMap(mapKeysDict[leg_key], electronMapKeys)
1045 triggerConfigs[leg_conf if self.useToolKeyAsOutput else leg_out] = leg_conf
1046
1047 decorations = [self.prefixSF]
1048 if self.saveEff:
1049 decorations += [self.prefixEff]
1050
1051 for label, conf in triggerConfigs.items():
1052 for deco in decorations:
1053 alg = config.createAlgorithm('CP::ElectronEfficiencyCorrectionAlg',
1054 'EleTrigEfficiencyCorrectionsAlg' + deco +
1055 '_' + label)
1056 config.addPrivateTool( 'efficiencyCorrectionTool',
1057 'AsgElectronEfficiencyCorrectionTool' )
1058
1059
1060 alg.efficiencyCorrectionTool.MapFilePath = map_Run3 if config.geometry() is LHCPeriod.Run3 else map_Run2
1061 alg.efficiencyCorrectionTool.IdKey = self.electronID.
replace(
"LH",
"")
1062 alg.efficiencyCorrectionTool.IsoKey = self.electronIsol
1063 alg.efficiencyCorrectionTool.TriggerKey = (
1064 ("Eff_" if deco == self.prefixEff else "") + conf)
1065 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
1066 alg.efficiencyCorrectionTool.ForceDataType = \
1067 PATCore.ParticleDataType.Full
1068
1069 alg.scaleFactorDecoration = f"el_{deco}_{label}_%SYS%"
1070
1071 alg.outOfValidity = 2
1072 alg.outOfValidityDeco = f"bad_eff_ele{deco}_{label}"
1073 alg.electrons = config.readName (self.containerName)
1074 alg.preselection = config.getPreselection (self.containerName, "")
1075 config.addOutputVar (self.containerName, alg.scaleFactorDecoration, f"{deco}_{label}")
1076
1077
std::string replace(std::string s, const std::string &s2, const std::string &s3)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)