ATLAS Offline Software
Loading...
Searching...
No Matches
TrigJetHypoToolConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3from AthenaConfiguration.ComponentFactory import CompFactory
4from AthenaCommon.SystemOfUnits import GeV
5
6from TriggerMenuMT.HLT.Menu.Physics_pp_run3_v1 import SingleJetGroup
7from TriggerMenuMT.HLT.Config.Utility.ChainDefInMenu import ChainProp
8from TriggerMenuMT.HLT.Config.ControlFlow.HLTCFTools import NoHypoToolCreated
9from TrigHLTJetHypo.hypoConfigBuilder import hypotool_from_chaindict
10from TrigHLTJetHypo.TrigJetHypoMonitoringConfig import TrigJetHypoToolMonitoring
11from AthenaCommon.Logging import logging
12logger = logging.getLogger(__name__)
13import re
14
15import os
16debug = 'JETHYPODEBUG' in os.environ
17if debug:
18 from AthenaCommon.Constants import DEBUG
19 logger.setLevel(DEBUG)
20
21def _find_momemfrac_cut(chain_dict):
22 """
23 Return momemfrac cut value as string from chain_dict, or None if not found.
24 """
25 parts = chain_dict.get("chainParts") or []
26
27 for idx, cp in enumerate(parts):
28 momcuts = (cp.get("momCuts") or "").strip()
29 if not momcuts:
30 continue
31
32 m = re.search(r"momemfrac(?P<cut>\d{3})(?!\d)", momcuts)
33 if not m:
34 continue
35
36 val = m.group("cut")
37
38 return val
39
40 return None
41
42def trigJetHypoToolFromDict(flags, chain_dict):
43
44 from DecisionHandling.TrigCompositeUtils import isLegId, getLegIndexInt
45 chain_name = chain_dict['chainName']
46 chain_mg = chain_dict['monGroups']
47 jet_signature_identifiers = ['Jet:Jet', 'Bjet:Bjet', 'Tau:Ditau']
48
49 if isLegId(chain_name):
50 # For multi-leg chains which include jet legs we have a -- SPECIAL BEHAVIOUR --
51 # We instantiate a HypoTool only for the *first* jet leg, whichever leg that happens to be in the chain
52 # This single HypoTool gets configured to perform the selection for _all_ of the jet legs, and to report
53 # the per-jet passing status for all of these legs.
54 #
55 # Here we determine if this is the 2nd+ jet leg of a multi-leg chain which has jet legs, and return no tool if it is
56
57 # Can we fetch this from elsewhere?
58
59 leg_id = getLegIndexInt(chain_name)
60 chain_sig_w_sub_sig = [f'{sig}:{subsig}' for sig, subsigs in chain_dict['sigDicts'].items() for subsig in subsigs]
61 # CHECK: If we have called trigJetHypoToolFromDict, then the chain_sig_w_sub_sig list must contain at minimum one entry from the jet_signature_identifiers list.
62 if not any(signature in chain_sig_w_sub_sig for signature in jet_signature_identifiers):
63 raise Exception("[trigJetHypoToolFromDict] No {} in {} for chain {}. Please update this list of jet signatures.".format(tuple(jet_signature_identifiers),tuple(chain_sig_w_sub_sig),chain_name))
64
65 # CHECK: All Jet and Bjet legs (i.e. signatures from jet_signature_identifiers) must be contiguous
66 # (this check is probable best put somewhere else?)
67 status = 0
68 for entry in chain_sig_w_sub_sig:
69 if status == 0 and entry in jet_signature_identifiers:
70 status = 1
71 elif status == 1 and entry not in jet_signature_identifiers:
72 status = 2
73 elif status == 2 and entry in jet_signature_identifiers:
74 raise Exception("[trigJetHypoToolFromDict] All {} legs should be contiguous in the signatures list, modify the ordering of the chain {}. Signatures:{}.".format(tuple(jet_signature_identifiers),chain_name, tuple(chain_sig_w_sub_sig)))
75
76 # CHECK: The leg_id must correspond to a Signature from jet_signature_identifiers. At the time of implementation, this is not guaranteed and can be affected by alignment.
77 # If this check fails for any chain, then we need to look again at how the legXXX ordering maps to the chain_sig_w_sub_sig ordering.
78 if not any(signature in chain_sig_w_sub_sig[leg_id] for signature in jet_signature_identifiers):
79 raise Exception("[trigJetHypoToolFromDict] For this code to work for chain {}, the signature at index {} must be one of {}. But the signature list is: {}".format(chain_name,leg_id,tuple(jet_signature_identifiers),tuple(chain_sig_w_sub_sig)))
80
81 # Locate the first index within chain_sig_w_sub_sig which contains an signature listed in jet_signature_identifiers
82 first_leg_index = 999
83 for signature in jet_signature_identifiers:
84 if signature in chain_sig_w_sub_sig:
85 first_leg_index = min(first_leg_index, chain_sig_w_sub_sig.index(signature))
86
87 if leg_id > first_leg_index:
88 logger.debug("Not returning a HypoTool for %s as this is not the first leg "
89 "with any of %s (leg signatures are %s)",
90 chain_name, tuple(jet_signature_identifiers), tuple(chain_sig_w_sub_sig))
91 raise NoHypoToolCreated("No HypoTool created for %s" % chain_name)
92
93 logger.debug("Returning a HypoTool for %s as this is the first leg with any of %s (leg signatures are %s)",
94 chain_name, tuple(jet_signature_identifiers), tuple(chain_dict['signatures']))
95
96 hypo_tool = hypotool_from_chaindict(chain_dict, debug)
97
98 #if menu has chain in an online monitoring group, unpack the recoalg(s) and hyposcenario(s) to configure monitoring
99 if any('jetMon:online' in group for group in chain_mg):
100 cpl = chain_dict["chainParts"]
101 histFlags = []
102 for cp in cpl:
103 histFlags += [ cp['recoAlg'] ] + [ cp['hypoScenario']]
104 hypo_tool.MonTool = TrigJetHypoToolMonitoring(flags, "HLTJetHypo/"+chain_name, histFlags)
105 return hypo_tool
106
107
108def trigJetTLAHypoToolFromDict(flags, chain_dict):
109 return CompFactory.TrigJetTLAHypoTool(chain_dict['chainName'])
110
111def trigJetEJsHypoToolFromDict(flags, chain_dict):
112 if len(chain_dict['chainParts']) > 1:
113 raise Exception("misconfiguration of emerging jet chain")
114
115 if len(chain_dict['chainParts'][0]['exotHypo']) > 0:
116 exot_hypo = chain_dict['chainParts'][0]['exotHypo'][0]
117 else:
118 raise Exception("Unable to extract exotHypo emerging jet configuration from chain dict")
119
120 if 'emerging' in exot_hypo:
121 trackless = int(0)
122 ptf = float(exot_hypo.split('PTF')[1].split('dR')[0].replace('p', '.'))
123 dr = float(exot_hypo.split('dR')[1].split('_')[0].replace('p', '.'))
124 elif 'trackless' in exot_hypo:
125 trackless = int(1)
126 ptf = 0.0
127 dr = float(exot_hypo.split('dR')[1].split('_')[0].replace('p', '.'))
128 else:
129 raise Exception("misconfiguration of emerging jet chain")
130
131 chain_name = chain_dict['chainName']
132
133 hypo = CompFactory.TrigJetEJsHypoTool(chain_name)
134 hypo.PTF = ptf
135 hypo.dR = dr
136 hypo.Trackless = trackless
137
138 return hypo
139
140def trigJetCRVARHypoToolFromDict(flags, chain_dict):
141 chain_name = chain_dict['chainName']
142 doBIBrm = int(0)
143 doExoCal = int(0)
144 ExoCalCut = 220
145 if len(chain_dict['chainParts'][0]['exotHypo']) > 0:
146 exot_hypo = chain_dict['chainParts'][0]['exotHypo'][0]
147 calratioX_matched = re.match(r'.*calratiovar(?P<cut>\d{1,3}[\d\D]*)', chain_dict['chainParts'][0]['exotHypo'][0])
148 if calratioX_matched:
149 doExoCal= int(1)
150 ExoCalCut = calratioX_matched.groupdict()['cut']
151 else:
152 if len(chain_dict['chainParts'][1]['exotHypo']) > 0:
153 exot_hypo = chain_dict['chainParts'][1]['exotHypo'][0]
154 logger.warning(chain_dict)
155 calratioX_matched = re.match(r'.*calratiovar(?P<cut>\d{1,3}[\d\D]*)', chain_dict['chainParts'][1]['exotHypo'][0])
156 if calratioX_matched:
157 doExoCal= int(1)
158 ExoCalCut = calratioX_matched.groupdict()['cut']
159 else:
160 raise Exception("Unable to extract exotHypo calratio jet configuration from chain dict")
161 if 'calratiovar' in exot_hypo:
162 if 'calratiovarrmbib' in exot_hypo:
163 doBIBrm = int(1)
164 else:
165 raise Exception("misconfiguration of new calratio jet chain")
166
167 presel_matched = re.match(r'.*emf(?P<cut>\d?\d?[\d\D]+)', chain_dict['chainParts'][0]['trkpresel'])
168 if presel_matched:
169 emf_cut = presel_matched.groupdict()['cut']
170 elif len(chain_dict['chainParts'])>1:
171 presel_matched = re.match(r'.*emf(?P<cut>\d?\d?[\d\D]+)', chain_dict['chainParts'][1]['trkpresel'])
172 if presel_matched:
173 emf_cut = presel_matched.groupdict()['cut']
174 elif len(chain_dict['chainParts'])>3:
175 presel_matched = re.match(r'.*emf(?P<cut>\d?\d?[\d\D]+)', chain_dict['chainParts'][3]['trkpresel'])
176 if presel_matched:
177 emf_cut = presel_matched.groupdict()['cut']
178 else:
179 raise Exception("misconfiguration of Exotic jet chain")
180 else:
181 raise Exception("misconfiguration of Exotic jet chain")
182
183 import math
184 hypo = CompFactory.TrigJetCRVARHypoTool(chain_name)
185 hypo.MpufixLogRatio = math.log10(1./(float(emf_cut)*0.01) - 1.)
186 hypo.MinjetlogR = 1.2
187 if doExoCal:
188 hypo.MinjetlogR = (float(ExoCalCut)*0.01) - 1.
189 hypo.MintrackPt = 2*GeV
190 hypo.MindeltaR = 0.2
191 hypo.countBIBcells = 4
192 hypo.doBIBremoval = doBIBrm
193
194 return hypo
195
196def trigJetCRHypoToolFromDict(flags, chain_dict):
197 chain_name = chain_dict['chainName']
198
199 doBIBrm = int(0)
200 if len(chain_dict['chainParts'][0]['exotHypo']) > 0:
201 exot_hypo = chain_dict['chainParts'][0]['exotHypo'][0]
202 else:
203 raise Exception("Unable to extract exotHypo calratio jet configuration from chain dict")
204 if 'calratio' in exot_hypo and ('calratiovar' not in exot_hypo):
205 if 'calratiormbib' in exot_hypo:
206 doBIBrm = int(1)
207 else:
208 raise Exception("misconfiguration of new calratio jet chain")
209
210 hypo = CompFactory.TrigJetCRHypoTool(chain_name)
211
212
213 hypo = CompFactory.TrigJetCRHypoTool(chain_name)
214 hypo.MinjetlogR = 1.2
215 import math
216 emf_cut = _find_momemfrac_cut(chain_dict)
217 if emf_cut is None:
218 pass
219 else:
220 try:
221 emf_val = int(emf_cut) / 100.0
222 except (TypeError, ValueError):
223 logger.warning(
224 "Invalid emf_cut '%s' for chain %s; using default MinjetlogR=%s",
225 emf_cut, chain_name, 1.2,
226 )
227 else:
228 if not (0.0 < emf_val < 1.0):
229 logger.warning(
230 "emf_cut '%s' -> %s out of (0,1) range for chain %s; using default MinjetlogR=%s",
231 emf_cut, emf_val, chain_name, 1.2,
232 )
233 else:
234 try:
235 hypo.MinjetlogR = math.log10(1.0 / emf_val - 1.0)
236 except (ValueError, OverflowError):
237 logger.warning(
238 "Computed MinjetlogR invalid for emf_cut='%s' (emf_val=%s) in chain %s; using default %s",
239 emf_cut, emf_val, chain_name, 1.2,
240 )
241
242 hypo.MintrackPt = 2*GeV
243 hypo.MindeltaR = 0.2
244 hypo.countBIBcells = 4
245 hypo.doBIBremoval = doBIBrm
246
247 return hypo
248
249import unittest
250class TestStringMethods(unittest.TestCase):
252 from TriggerMenuMT.HLT.Config.Utility.DictFromChainName import (
253 dictFromChainName,)
254
255 chain_names = (
256 'HLT_j0_FBDJNOSHARED10etXX20etXX34massXX50fbet_L1J20',)
257
258 from AthenaConfiguration.AllConfigFlags import initConfigFlags
259 flags = initConfigFlags()
260 flags.Input.Files = []
261
262 flags.lock()
263
264 wid = max(len(c) for c in chain_names)
265 for chain_name in chain_names:
266 props = ChainProp(name=chain_name, l1SeedThresholds=['FSNOSEED'], groups=SingleJetGroup)
267 chain_dict = dictFromChainName(flags, props)
268 tool = trigJetHypoToolFromDict(flags, chain_dict)
269 self.assertIsNotNone(tool)
270 logger.debug(chain_name.rjust(wid), str(tool))
271
272
273
274if __name__ == '__main__':
275 unittest.main()
276
277 # other local tests have been moved to testChainDictMaker.py
bool isLegId(const HLT::Identifier &legIdentifier)
Recognise whether the chain ID is a leg ID.
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
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
trigJetEJsHypoToolFromDict(flags, chain_dict)
trigJetCRVARHypoToolFromDict(flags, chain_dict)
trigJetTLAHypoToolFromDict(flags, chain_dict)
trigJetCRHypoToolFromDict(flags, chain_dict)
trigJetHypoToolFromDict(flags, chain_dict)