ATLAS Offline Software
Loading...
Searching...
No Matches
MetAnalysisConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3# AnaAlgorithm import(s):
4from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
5from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
6
7
8class MetAnalysisConfig (ConfigBlock):
9 """the ConfigBlock for the MET configuration"""
10
11 def __init__ (self) :
12 super().__init__ ()
13 self.addOption('containerName', '', type=str,
14 noneAction='error',
15 info="the name of the output container.",
16 meta={'role':'container'})
17 self.addOption ('useJVT', True, type=bool,
18 info="whether to use the JVT decision in the MET calculation.")
19 self.addOption ('useFJVT', False, type=bool,
20 info="whether to use the forward JVT decision in the MET calculation.")
21 self.addOption ('selectionNameFJVT', "", type=str,
22 info="name of the forward JVT selection to be used if `useFJVT` is activated.",
23 meta={'role':'selection'})
24 self.addOption ('treatPUJets', False, type=bool,
25 info="whether to treat pile-up jets in the MET significance calculation.")
26 self.addOption ('setMuonJetEMScale', True, type=bool,
27 info="enables the handling of muons in jets for the MET calculation. "
28 "Should be turned off for analyses where muons are not reconstructed "
29 "at all.")
30 self.addOption ('jets', "", type=str,
31 info="the input jet container.",
32 meta={'role':'containerRef'})
33 self.addOption ('electrons', "", type=str,
34 info="the input electron container, with a possible selection, in "
35 "the format `container` or `container.selection`.",
36 meta={'role':'containerRef'})
37 self.addOption ('muons', "", type=str,
38 info="the input muon container, with a possible selection, in the "
39 "format `container` or `container.selection`.",
40 meta={'role':'containerRef'})
41 self.addOption ('photons', "", type=str,
42 info="the input photon container, with a possible selection, in "
43 "the format `container` or `container.selection`.",
44 meta={'role':'containerRef'})
45 self.addOption ('taus', "", type=str,
46 info="the input tau-jet container, with a possible selection, in "
47 "the format `container` or `container.selection`.",
48 meta={'role':'containerRef'})
49 self.addOption ('invisible', [], type=None,
50 info="any input containers to be treated as invisible particles, "
51 "as a single string or a list of strings in the format `container` or `container.selection`.",
52 meta={'role':'containerRef'})
53 self.addOption ('metWP', "Tight", type=str,
54 info="the MET working point to use: `Loose`, `Tight`, `Tighter`, "
55 "`Tenacious`.",
56 meta={'choices':(['Loose','Tight','Tighter','Tenacious'],1)})
57 self.addOption ('skipSystematicJetSelection', False, type=bool,
58 info="EXPERIMENTAL: whether to use simplified OR based on nominal jets "
59 "and for jet-related systematics only. "
60 "WARNING: this option is strictly for doing physics studies of the feasibility "
61 "of this OR scheme, it should not be used in a regular analysis.",
62 expertMode=True)
63 self.addOption ('saveSignificance', True, type=bool,
64 info="whether to save the MET significance.")
65 self.addOption ('jetCalibConfig', "", type=str,
66 info="config file used in jet calibration (for MET significance).")
67 self.addOption ('jetCalibSequence', "", type=str,
68 info="jet calibration sequence (for MET significance).")
69 self.addOption ('jetCalibArea', "", type=str,
70 info="name of the CalibArea used in jet calibration (for MET significance).")
71 self.addOption ('egammaESModel', "", type=str,
72 info="ESModel for EGamma calibration (for MET significance).")
73 self.addOption ('egammaDecorrelationModel', "", type=str,
74 info="decorrelation model for EGamma calibration (for MET significance).")
75 self.addOption ('tauTESConfig', "tauRecTools/R22_preprod/CombinedTES_R22_Round2.5_v2.root", type=str,
76 info="config file for tau energy scale calibration (for MET significance).")
77 self.addOption ('addExtraSignificanceVars', False, type=bool,
78 info="whether to save some additional (event-based) MET significance variables.")
79 self.addOption ('useLRT', False, type=bool,
80 info="whether to use LRT MET Core and association map.")
81 self.addOption ('useCaloSoftTerm', False, type=bool,
82 info="whether to use calo- instead of track-based soft term.",
83 expertMode=True)
84 self.addOption ('softTermResolution', -1.0, type=float,
85 info="override the default soft term resolution in METSignificance.",
86 expertMode=True)
87 self.addOption ('switchTauMuOrder', False, type=bool,
88 info="whether to switch order of taus and muons",
89 expertMode=True)
90 self.addOption ('useNN', False, type=bool,
91 info="use the METNet neural-network MET tool (met::METNet) instead of "
92 "met::METMaker. Produces the NN MET as the container's Final term.")
93 self.addOption ('networkFile', "", type=str,
94 info="path to the METNet ONNX network file (required when useNN=True).")
95
96 def instanceName (self) :
97 """Return the instance name for this block"""
98 return self.containerName
99
100 def makeAlgs (self, config) :
101
102 if config.isPhyslite() :
103 metSuffix = 'AnalysisMET'
104 else :
105 jetContainer = config.originalName (self.jets)
106 btIndex = jetContainer.find('_BTagging')
107 if btIndex != -1:
108 jetContainer = jetContainer[:btIndex]
109 if not jetContainer.endswith('Jets'):
110 raise ValueError(f"MissingET: jet container name \"{jetContainer}\" does not end in \"Jets\", cannot determine MET suffix.")
111 metSuffix = jetContainer.removesuffix('Jets')
112 if self.useLRT:
113 metSuffix += "_LRT"
114
115 # Set up the met maker algorithm:
116 alg = config.createAlgorithm( 'CP::MetMakerAlg', 'MetMakerAlg' )
117 if self.useNN:
118 if not self.networkFile:
119 raise ValueError("MissingET: useNN=True requires 'networkFile'.")
120 config.addPrivateTool( 'makerTool', 'met::METNet' )
121 alg.makerTool.NetworkFile = self.networkFile
122 alg.makerTool.JetContainer = config.readName (self.jets)
123 alg.evaluateNNMET = True
124 alg.doJetJVT = self.useJVT
125 # NOTE: no met::METSystematicsTool for the NN path — soft-term
126 # systematics are not defined for the network output.
127 else:
128 config.addPrivateTool( 'makerTool', 'met::METMaker' )
129 alg.makerTool.skipSystematicJetSelection = self.skipSystematicJetSelection
130
131 alg.doJetJVT = self.useJVT
132 if self.useJVT:
133 config.addPrivateTool( 'makerTool.JvtSelTool', 'CP::NNJvtSelectionTool' )
134 alg.makerTool.JvtSelTool.JetContainer = config.readName (self.jets)
135 alg.makerTool.JvtSelTool.JvtMomentName = "NNJvt"
136 if self.useFJVT:
137 # for backwards compatibility with "old" FJVT handling in JetAnalysisConfig.py
138 if not self.selectionNameFJVT:
139 alg.makerTool.JetRejectionDec = 'fjvt_selection'
140 # otherwise get the decoration from the selection
141 else:
142 fjvt_decoration = config.getFullSelection(self.jets, self.selectionNameFJVT, skipBase=True).replace(",as_char", "")
143 alg.makerTool.JetRejectionDec = fjvt_decoration
144
145 alg.makerTool.JetSelection = self.metWP
146 alg.makerTool.DoPFlow = 'PFlow' in metSuffix or metSuffix=="AnalysisMET"
147 alg.makerTool.DoSetMuonJetEMScale = self.setMuonJetEMScale if self.muons else False
148 alg.switchTauMu = self.switchTauMuOrder
149
150 if config.dataType() is not DataType.Data :
151 config.addPrivateTool( 'systematicsTool', 'met::METSystematicsTool' )
152
153 alg.metCore = 'MET_Core_' + metSuffix
154 alg.metAssociation = 'METAssoc_' + metSuffix
155 alg.jets = config.readName (self.jets)
156 alg.softTermKey = "PVSoftTrk" if not self.useCaloSoftTerm else "SoftClus"
157 if self.muons != "" :
158 alg.muons, alg.muonsSelection = config.readNameAndSelection (self.muons, excludeFrom={'or'})
159 if self.electrons != "" :
160 alg.electrons, alg.electronsSelection = config.readNameAndSelection (self.electrons, excludeFrom={'or'})
161 if self.photons != "" :
162 alg.photons, alg.photonsSelection = config.readNameAndSelection (self.photons, excludeFrom={'or'})
163 if self.taus != "" :
164 alg.taus, alg.tausSelection = config.readNameAndSelection (self.taus, excludeFrom={'or'})
165 if self.invisible:
166 invisible = [self.invisible] if isinstance(self.invisible, str) else self.invisible
167 invisibleContainers, invisibleSelections = zip(*[config.readNameAndSelection (container, excludeFrom={'or'}) for container in invisible])
168 alg.invisible = list(invisibleContainers)
169 alg.invisibleSelection = list(invisibleSelections)
170 alg.met = config.writeName (self.containerName, isMet = True)
171
172 # met/phi are decorated on every term by the maker alg (for the NN path
173 # directly via evaluateNNMET), so they are output on both paths.
174 config.addOutputVar (self.containerName, 'met', 'met', auxType='float')
175 config.addOutputVar (self.containerName, 'phi', 'phi', auxType='float')
176 config.addOutputVar (self.containerName, 'name', 'name', noSys=True, enabled=False)
177
178 # The NN path writes the Final term directly (a builder sum would clobber
179 # it) and produces no meaningful sumet/significance, so it needs neither
180 # the met builder nor the significance algorithm.
181 if self.useNN:
182 return
183
184 config.addOutputVar (self.containerName, 'sumet', 'sumet', auxType='float')
185
186 # Set up the met builder algorithm:
187 alg = config.createAlgorithm( 'CP::MetBuilderAlg', 'MetBuilderAlg' )
188 alg.softTerm = "PVSoftTrk" if not self.useCaloSoftTerm else "SoftClus"
189 alg.met = config.readName (self.containerName)
190
191
192 # Set up the met significance algorithm:
194 alg = config.createAlgorithm( 'CP::MetSignificanceAlg', 'MetSignificanceAlg' )
195 config.addPrivateTool( 'significanceTool', 'met::METSignificance' )
196 if self.muons != "" :
197 config.addPrivateTool( 'significanceTool.MuonCalibTool', 'CP::MuonCalibTool' )
198 # Retrieve the calibMode from the container name.selections
199 alg.significanceTool.MuonCalibTool.calibMode = (
200 config.getContainerMeta(self.muons.split(".")[0], 'calibMode', failOnMiss=True))
201
202 # Preliminary R22 recommendation is to use R21 jet resolutions from 2018 for MET significance.
203 # See Jet/Etmiss recommendation documentation for details.
204 jetCalibConfig = self.jetCalibConfig
205 jetCalibSequence = self.jetCalibSequence
206 jetCalibArea = self.jetCalibArea
207 if jetCalibConfig == "":
208 jetCalibConfig = "JES_data2017_2016_2015_Recommendation_PFlow_Aug2018_rel21.config"
209 jetCalibArea = "00-04-81"
210 # Include Smear and not InSitu, even when running on data.
211 # This is for technical reasons and allows access to the correct resolutions for both data and MC.
212 jetCalibSequence = 'JetArea_Residual_EtaJES_GSC_Smear'
213
214 # Standard e/gamma calibration. Must be kept in agreement with ElectronAnalysisConfig.py
215 egammaESModel = self.egammaESModel
216 egammaDecorrelationModel = self.egammaDecorrelationModel
217 if self.electrons != "" :
218 if egammaESModel == "":
219 egammaESModel = (
220 config.getContainerMeta(self.electrons.split(".")[0], 'ESModel', failOnMiss=True))
221 if egammaDecorrelationModel == "":
222 egammaDecorrelationModel = (
223 config.getContainerMeta(self.electrons.split(".")[0], 'decorrelationModel', failOnMiss=True))
224
225 alg.significanceTool.SoftTermParam = 0
226 if self.softTermResolution > 0:
227 alg.significanceTool.SoftTermReso = self.softTermResolution
228 alg.significanceTool.TreatPUJets = self.treatPUJets
229 alg.significanceTool.JetCalibConfig = jetCalibConfig
230 alg.significanceTool.JetCalibSequence = jetCalibSequence
231 alg.significanceTool.JetCalibArea = jetCalibArea
232 alg.significanceTool.EgammaESModel = egammaESModel
233 alg.significanceTool.EgammaDecorrelationModel = egammaDecorrelationModel
234 alg.significanceTool.EgammaUseFastsim = (config.dataType() is DataType.FastSim)
235 alg.significanceTool.TauTESConfig = self.tauTESConfig
236 alg.met = config.readName (self.containerName)
237 config.addOutputVar (self.containerName, 'significance_%SYS%', 'significance', auxType='float')
239 alg.sigDirectionalDecoration = "sigDirectional_%SYS%"
240 alg.METOverSqrtSumETDecoration = "METOverSqrtSumET_%SYS%"
241 alg.METOverSqrtHTDecoration = "METOverSqrtHT_%SYS%"
242 config.addOutputVar (self.containerName, 'sigDirectional_%SYS%', 'sigDirectional', auxType='float')
243 config.addOutputVar (self.containerName, 'METOverSqrtSumET_%SYS%', 'METOverSqrtSumET', auxType='float')
244 config.addOutputVar (self.containerName, 'METOverSqrtHT_%SYS%', 'METOverSqrtHT', auxType='float')
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:312
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179