830 def makeAlgs (self, config) :
831
832 if config.dataType() is not DataType.Data:
833 log = logging.getLogger('ElectronTriggerSFConfig')
834
835 if self.includeAllYearsPerRun and not self.useToolKeyAsOutput:
836 log.warning('`includeAllYearsPerRun` is set to True, but `useToolKeyAsOutput` is set to False. '
837 'This will cause multiple branches to be written out with the same content.')
838
839
840
841
842 triggerDict = TriggerDict()
843
844
845 version_Run2 = "2015_2025/rel22.2/2025_Run2Rel22_Recommendation_v3"
846 map_Run2 = f"ElectronEfficiencyCorrection/{version_Run2}/map1.txt"
847 version_Run3 = "2015_2025/rel22.2/2025_Run3_Consolidated_Recommendation_v4"
848 map_Run3 = f"ElectronEfficiencyCorrection/{version_Run3}/map2.txt"
849
850 version = version_Run2 if config.geometry() is LHCPeriod.Run2 else version_Run3
851
852
853
854 mapKeysDict = MapKeysDict(version)
855
856
857 def filterConfFromMap(conf, electronMapKeys):
858 if not conf:
859 raise ValueError("No configuration found for trigger chain.")
860 if len(conf) == 1:
861 return conf[0]
862
863 for c in conf:
864 if c in electronMapKeys:
865 return c
866
867 return conf[0]
868
869 if self.includeAllYearsPerRun:
870 years = [int(year) for year in self.triggerChainsPerYear.keys()]
871 else:
872 from TriggerAnalysisAlgorithms.TriggerAnalysisSFConfig import (
873 get_input_years)
874 years = get_input_years(config)
875
876
877 import ROOT
878 triggerChainsPerYear_Run2 = {}
879 triggerChainsPerYear_Run3 = {}
880 for year, chains in self.triggerChainsPerYear.items():
881 if not chains:
882 log.warning("No trigger chains configured for year %s. "
883 "Assuming this is intended, no Electron trigger SF will be computed.", year)
884 continue
885
886 chains_split = [chain.replace(
"HLT_",
"").
replace(
" || ",
"_OR_")
for chain
in chains]
887 if int(year) >= 2022:
888 triggerChainsPerYear_Run3[str(year)] = ' || '.join(chains_split)
889 else:
890 triggerChainsPerYear_Run2[str(year)] = ' || '.join(chains_split)
891 electronMapKeys_Run2 = ROOT.std.map("string", "string")()
892 electronMapKeys_Run3 = ROOT.std.map("string", "string")()
893
894 sc_Run2 = ROOT.TrigGlobalEfficiencyCorrectionTool.suggestElectronMapKeys(triggerChainsPerYear_Run2, version_Run2, electronMapKeys_Run2)
895 sc_Run3 = ROOT.TrigGlobalEfficiencyCorrectionTool.suggestElectronMapKeys(triggerChainsPerYear_Run3, version_Run3, electronMapKeys_Run3)
896 if sc_Run2.code() != 2 or sc_Run3.code() != 2:
897 raise RuntimeError("Failed to suggest electron map keys")
898 electronMapKeys = dict(electronMapKeys_Run2) | dict(electronMapKeys_Run3)
899
900
901 from TriggerAnalysisAlgorithms.TriggerAnalysisConfig import is_year_in_current_period
902 triggerConfigs = {}
903 for year in years:
904 if not is_year_in_current_period(config, year):
905 continue
906
907 triggerChains = self.triggerChainsPerYear.
get(int(year), self.triggerChainsPerYear.
get(str(year), []))
908 for chain in triggerChains:
909 chain = chain.replace(" || ", "_OR_")
910 chain_noHLT = chain.replace("HLT_", "")
911 chain_out = chain_noHLT if self.removeHLTPrefix else chain
912 legs = triggerDict[chain_noHLT]
913 if not legs:
914 if chain_noHLT[0] == 'e' and chain_noHLT[1].isdigit:
915 chain_key = f"{year}_{chain_noHLT}"
916 chain_conf = mapKeysDict[chain_key][0]
917 triggerConfigs[chain_conf if self.useToolKeyAsOutput else chain_out] = chain_conf
918 else:
919 for leg in legs:
920 if leg[0] == 'e' and leg[1].isdigit:
921 leg_out = leg if self.removeHLTPrefix else f"HLT_{leg}"
922 leg_key = f"{year}_{leg}"
923 leg_conf = filterConfFromMap(mapKeysDict[leg_key], electronMapKeys)
924 triggerConfigs[leg_conf if self.useToolKeyAsOutput else leg_out] = leg_conf
925
926 decorations = [self.prefixSF]
927 if self.saveEff:
928 decorations += [self.prefixEff]
929
930 for label, conf in triggerConfigs.items():
931 for deco in decorations:
932 alg = config.createAlgorithm('CP::ElectronEfficiencyCorrectionAlg',
933 'EleTrigEfficiencyCorrectionsAlg' + deco +
934 '_' + label)
935 config.addPrivateTool( 'efficiencyCorrectionTool',
936 'AsgElectronEfficiencyCorrectionTool' )
937
938
939 alg.efficiencyCorrectionTool.MapFilePath = map_Run3 if config.geometry() is LHCPeriod.Run3 else map_Run2
940 alg.efficiencyCorrectionTool.IdKey = self.electronID.
replace(
"LH",
"")
941 alg.efficiencyCorrectionTool.IsoKey = self.electronIsol
942 alg.efficiencyCorrectionTool.TriggerKey = (
943 ("Eff_" if deco == self.prefixEff else "") + conf)
944 alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
945 alg.efficiencyCorrectionTool.ForceDataType = \
946 PATCore.ParticleDataType.Full
947
948 alg.scaleFactorDecoration = f"el_{deco}_{label}_%SYS%"
949
950 alg.outOfValidity = 2
951 alg.outOfValidityDeco = f"bad_eff_ele{deco}_{label}"
952 alg.electrons = config.readName (self.containerName)
953 alg.preselection = config.getPreselection (self.containerName, "")
954 config.addOutputVar (self.containerName, alg.scaleFactorDecoration, f"{deco}_{label}")
955
956
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?)