ATLAS Offline Software
Loading...
Searching...
No Matches
LeptonSFCalculatorConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
4from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
5
6
7class LeptonSFCalculatorBlock(ConfigBlock):
8 """ConfigBlock for the common electron-muon-photon-tau SF calculator"""
9 """--> combine all the per-object SFs into a single per-event SF"""
10
11 def __init__(self):
12 super(LeptonSFCalculatorBlock, self).__init__()
13 self.addDependency("ElectronWorkingPointEfficiency", required=False)
14 self.addDependency("PhotonWorkingPointEfficiency", required=False)
15 self.addDependency("MuonWorkingPointEfficiency", required=False)
16 self.addDependency("TauWorkingPointEfficiency", required=False)
17 self.addOption('electrons', None, type=str,
18 info='the input electron container, with a possible selection, in the format `container` or `container.selection`.',
19 meta={'role':'containerRef'})
20 self.addOption('electronSFs', None, type=list,
21 info='list of decorated electron SFs to use in the computation. If not set, will use reconstruction x ID x isolation, also ECIDS (charge ID) if available.')
22 self.addOption('muons', None, type=str,
23 info='the input muon container, with a possible selection, in the format `container` or `container.selection`.',
24 meta={'role':'containerRef'})
25 self.addOption('muonSFs', None, type=list,
26 info='list of decorated muon SFs to use in the computation. If not set, will use reconstruction x isolation x TTVA.')
27 self.addOption('photons', None, type=str,
28 info='the input photon container, with a possible selection, in the format `container` or `container.selection`.',
29 meta={'role':'containerRef'})
30 self.addOption('photonSFs', None, type=list,
31 info='list of decorated photon SFs to use in the computation. If not set, will use ID x isolation.')
32 self.addOption('taus', None, type=str,
33 info='the input tau-jet container, with a possible selection, in the format `container` or `container.selection`.',
34 meta={'role':'containerRef'})
35 self.addOption('tauSFs', None, type=list,
36 info='list of decorated tau-jet SFs to use in the computation. If not set, will use reconstruction x ID x eVeto.')
37 self.addOption('lepton_postfix', None, type=str,
38 info='the name of the common lepton SF, e.g. `tight`.')
39 self.addOption('includeElectronChargeMisID', False, type=str,
40 info='whether to include the electron charge mis-ID SFs in the computation. The user is responsible for determining whether these are available.')
41 self.addOption('includeMuonBadVeto', False, type=str,
42 info='whether to include the muon bad veto SFs in the computation. The user is responsible for determining whether these are available.')
43
44 def instanceName (self) :
45 """Return the instance name for this block"""
46 return self.lepton_postfix
47
48 def makeAlgs(self, config):
49 if config.dataType() is DataType.Data: return
50
51 alg = config.createAlgorithm('CP::LeptonSFCalculatorAlg',
52 'leptonSFCalculator')
53
54 if self.electrons:
55 electrons, electronSelection = config.readNameAndSelection(self.electrons)
56 alg.electrons = electrons
57 alg.electronSelection = electronSelection
58 if self.electronSFs:
59 alg.electronSFs = self.electronSFs
60 else:
61 alg.electronSFs = [ f'el_reco_effSF_{self.electrons.split(".")[1]}_%SYS%',
62 f'el_id_effSF_{self.electrons.split(".")[1]}_%SYS%' ]
63 if 'isolated' in alg.electronSelection:
64 alg.electronSFs += [ f'el_isol_effSF_{self.electrons.split(".")[1]}_%SYS%' ]
65 if 'chargeID' in alg.electronSelection:
66 alg.electronSFs += [ f'el_ecids_effSF_{self.electrons.split(".")[1]}_%SYS%' ]
67 if self.includeElectronChargeMisID:
68 alg.electronSFs += [ f'el_charge_misid_effSF_{self.electrons.split(".")[1]}_%SYS%' ]
69
70 if self.muons:
71 muons, muonSelection = config.readNameAndSelection(self.muons)
72 alg.muons = muons
73 alg.muonSelection = muonSelection
74 if self.muonSFs:
75 alg.muonSFs = self.muonSFs
76 else:
77 alg.muonSFs = [ f'muon_reco_effSF_{self.muons.split(".")[1]}_%SYS%']
78 if 'trackSelection' in alg.muonSelection:
79 alg.muonSFs += [ f'muon_TTVA_effSF_{self.muons.split(".")[1]}_%SYS%' ]
80 if 'isolated' in alg.muonSelection:
81 alg.muonSFs += [ f'muon_isol_effSF_{self.muons.split(".")[1]}_%SYS%' ]
82 if self.includeMuonBadVeto:
83 alg.muonSFs += [ f'muon_BadMuonVeto_effSF_{self.muons.split(".")[1]}_%SYS%' ]
84
85 if self.photons:
86 photons, photonSelection = config.readNameAndSelection(self.photons)
87 alg.photons = photons
88 alg.photonSelection = photonSelection
89 if self.photonSFs:
90 alg.photonSFs = self.photonSFs
91 else:
92 alg.photonSFs = [ f'ph_id_effSF_{self.photons.split(".")[1]}_%SYS%' ]
93 if 'isolated' in alg.photonSelection:
94 alg.photonSFs += [ f'ph_isol_effSF_{self.photons.split(".")[1]}_%SYS%' ]
95
96 if self.taus:
97 taus, tauSelection = config.readNameAndSelection(self.taus)
98 alg.taus = taus
99 alg.tauSelection = tauSelection
100 if self.tauSFs:
101 alg.tauSFs = self.tauSFs
102 else:
103 alg.tauSFs = [ f'tau_Reco_effSF_{self.taus.split(".")[1]}_%SYS%',
104 f'tau_ID_effSF_{self.taus.split(".")[1]}_%SYS%']
105 if 'eVeto' in alg.tauSelection:
106 alg.tauSFs += [ f'tau_EvetoFakeTau_effSF_{self.taus.split(".")[1]}_%SYS%',
107 f'tau_EvetoTrueTau_effSF_{self.taus.split(".")[1]}_%SYS%']
108
109 alg.event_leptonSF = f'leptonSF_{self.lepton_postfix}_%SYS%'
110
111 config.addOutputVar('EventInfo', alg.event_leptonSF, f'weight_leptonSF_{self.lepton_postfix}')