ATLAS Offline Software
scenario_simple.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
2 
3 from TrigHLTJetHypo.RepeatedConditionParams import RepeatedConditionParams
4 from TrigHLTJetHypo.HelperConfigToolParams import HelperConfigToolParams
5 from TrigHLTJetHypo.ConditionDefaults import defaults
6 from TrigHLTJetHypo.make_treevec import make_treevec
7 
8 from AthenaCommon.Logging import logging
9 log = logging.getLogger(__name__)
10 
11 
12 # make a list of all possible cut items for the simple scenario
13 all_elemental_keys = ('etaRange', 'nnJvt', 'jvt', 'smc',
14  'threshold', 'momCuts', 'bsel', 'gntau', 'uht1tau',
15  'clrsel','pileuprm', 'timing', 'timeSig')
16 
17 # Extract moment cuts
18 def _cuts_from_momCuts(momCuts):
19  separator = 'XX'
20  args = momCuts.split(separator)
21  if len(args) > 1:
22  return args
23  return ''
24 
26  # determine which cut variable are present in this chain part,
27  # and find their chain part values
28  elemental_keys = [k for k in all_elemental_keys if k in cp]
29  cp_elemental_args = {k : cp[k] for k in elemental_keys if cp[k]}
30 
31  # remove place holders
32  todelete = []
33  for k, v in cp_elemental_args.items():
34  if v == 'nosmc': todelete.append(k)
35 
36  for k in todelete: del cp_elemental_args[k]
37 
38  # decode the chain part cut values to find the numerical cut values
39 
40  condargs = list()
41 
42  for k, v in cp_elemental_args.items():
43  if k == 'threshold':
44  key = 'pt'
45  vals = defaults(key, lo=v)
46  condargs.append((key, vals))
47 
48  if k == 'etaRange':
49  key='eta'
50  lo, hi = v.split(key)
51  vals = defaults(key, lo=lo, hi=hi)
52  condargs.append((key, vals))
53 
54  if k == 'smc':
55  key = 'smc'
56  lo, hi = v.split(key)
57  vals = defaults(key, lo=lo, hi=hi)
58  condargs.append((key, vals))
59 
60  # Capitalisation to avoid clash with pure 'jvt' key
61  if k == 'nnJvt':
62  key = 'nnJvt'
63  values = v.split(key)
64  assert values[0]=='','nnJvt condition takes only version post-argument'
65  assert values[1].startswith('v'),'nnJvt condition expects version as post-argument'
66 
67  version_to_name = dict(
68  v1='NNJvtTrkAugV1',
69  )
70 
71  vals = {
72  'min': '', #not used
73  'max': '', #not used
74  'nnJvtName': version_to_name[values[1]]
75  }
76 
77  condargs.append((key, vals))
78 
79  if k == 'jvt':
80  key = 'jvt'
81  values = v.split(key)
82  assert values[1] == '','jvt condition takes only one argument, two were given' # protection when an upper (not supported) cut is requested
83  lo = values[0]
84  vals = defaults(key, lo=lo)
85  condargs.append((key, vals))
86 
87  if k == 'timing':
88  key = 'timing'
89  values = v.split(key)
90  lo, hi = v.split(key)
91  vals = defaults(key, lo=lo, hi=hi)
92  condargs.append((key, vals))
93 
94  if k == 'timeSig':
95  key = 'timeSig'
96  values = v.split(key)
97  lo, hi = v.split(key)
98  vals = defaults(key, lo=lo, hi=hi)
99  condargs.append((key, vals))
100 
101  if k =='clrsel':
102  key = 'clrsel'
103  values = v.split(key)
104  lo = values[0]
105  vals = defaults(key, lo=lo)
106  condargs.append((key, vals))
107 
108  if k == 'bsel':
109  if 'bgnone' in v:
110  key = 'bgnone'
111  values = v.split(key)
112  assert values[1] == '', 'bgn1 condition takes only one argument, two were given'
113 
114  gn1_WPs = {
115  '': float('-inf'),
116  "95": -2.0886,
117  "90": -0.7981,
118  "85": 0.4462,
119  "82": 1.0965,
120  "80": 1.4991,
121  "77": 2.0717,
122  "75": 2.4110,
123  "60": 4.5465,
124  }
125 
126  assert (values[0] in gn1_WPs.keys()),f"The efficiency of the specified GN1 cut \'{v}\' can not be found in the WP dictionary. Please add or remove the WP from the GN1 WP dictionary."
127 
128  lo = gn1_WPs[values[0]]
129 
130  vals = {
131  'min': str(lo),
132  'max': '',
133  'cfrac': '0.018',
134  'namePb': 'fastGN120230331_pb',
135  'namePc': 'fastGN120230331_pc',
136  'namePu': 'fastGN120230331_pu',
137  'nameValid': 'TracksForMinimalJetTag_isValid'
138  }
139 
140  condargs.append((k, vals))
141 
142  # Retrained Xbb tagger
143  # Has to go before the rest of "bgntwo*"
144  elif 'bgntwoxt' in v:
145  key = 'bgntwoxt'
146  values = v.split(key)
147  assert values[1] == '','bgntwoxt condition takes only one argument, two were given'
148 
149  #This dictionary maps the bgntwoxt efficiency into the WP cut to be applied to the GN2XTrig output
150  gn2xt_WPs = {
151  '': float('-inf'),
152  '95': -1.35026,
153  '90': -0.25403,
154  '85': 0.50616,
155  '80': 1.10348,
156  '75': 1.57464,
157  '70': 1.96391,
158  '65': 2.29533,
159  '60': 2.58698,
160  }
161 
162  assert (values[0] in gn2xt_WPs.keys()),f"The efficiency of the specified gn2xt cut \'{v}\' can not be found in the WP dictionary. Please add or remove the WP from the gn2xt WP dictionary."
163 
164  lo = gn2xt_WPs[values[0]]
165  vals = {
166  'min': str(lo),
167  'max': '',
168  'cfrac': '0.25',
169  'namePb': 'GN2XTrig_phbb',
170  'namePc': 'GN2XTrig_ptop',
171  'namePu': 'GN2XTrig_pqcd',
172  }
173  condargs.append((k, vals))
174 
175  # GN2x has to go before GN2 in order to avoid ` elif 'bgntwo' in v:` l149 to pass 'bgntwox'
176  elif 'bgntwox' in v:
177  key = 'bgntwox'
178  values = v.split(key)
179  assert values[1] == '','bgntwox condition takes only one argument, two were given'
180 
181  #This dictionary maps the bdips efficiency into the WP cut to be applied to the DIPS output
182  gn2x_WPs = {
183  '': float('-inf'),
184  '79': 3.1077,
185  '86': 2.2998,
186  '91': 1.2486,
187  '96': -0.4298,
188  }
189 
190  assert (values[0] in gn2x_WPs.keys()),f"The efficiency of the specified gn2x cut \'{v}\' can not be found in the WP dictionary. Please add or remove the WP from the gn2x WP dictionary."
191 
192  lo = gn2x_WPs[values[0]]
193  vals = {
194  'min': str(lo),
195  'max': '',
196  'cfrac': '0.25',
197  'namePb': 'GN2Xv01_phbb',
198  'namePc': 'GN2Xv01_ptop',
199  'namePu': 'GN2Xv01_pqcd',
200  }
201  condargs.append((k, vals))
202 
203  elif 'bgntwo' in v:
204  key = 'bgntwo'
205  values = v.split(key)
206  assert values[1] == '', 'bgn2 condition takes only one argument, two were given'
207 
208  gn2_WPs = {
209  '': float('-inf'),
210  "95": -2.432,
211  "90": -1.351,
212  "85": -0.150,
213  "82": 0.5105,
214  "80": 0.931,
215  "77": 1.471,
216  "75": 1.832,
217  "60": 4.054,
218  }
219 
220  assert (values[0] in gn2_WPs.keys()),f"The efficiency of the specified GN2 cut \'{v}\' can not be found in the WP dictionary. Please add or remove the WP from the GN2 WP dictionary."
221 
222  lo = gn2_WPs[values[0]]
223 
224  vals = {
225  'min': str(lo),
226  'max': '',
227  'cfrac': '0.018',
228  'namePb': 'fastGN220240122_pb',
229  'namePc': 'fastGN220240122_pc',
230  'namePu': 'fastGN220240122_pu',
231  'nameValid': 'TracksForMinimalJetTag_isValid'
232  }
233 
234  condargs.append((k, vals))
235 
236  elif 'bdips' in v:
237  key = 'bdips'
238  values = v.split(key)
239  assert values[1] == '','bdips condition takes only one argument, two were given' # protection when an upper (not supported) cut is requested
240 
241  #This dictionary maps the bdips efficiency into the WP cut to be applied to the DIPS output
242  dips_WPs = {
243  '': float('-inf'),
244  '95': -1.6495,
245  '90': -0.8703,
246  '85': -0.0295,
247  '82': 0.4560,
248  '80': 0.7470,
249  '77': 1.1540,
250  '75': 1.4086,
251  '60': 3.0447,
252  }
253 
254  assert (values[0] in dips_WPs.keys()),f"The efficiency of the specified dips cut \'{v}\' can not be found in the WP dictionary. Please add or remove the WP from the dips WP dictionary."
255 
256  lo = dips_WPs[values[0]]
257  vals = {
258  'min': str(lo),
259  'max': '',
260  'cfrac': '0.018',
261  'namePb': 'fastDips_pb',
262  'namePc': 'fastDips_pc',
263  'namePu': 'fastDips_pu',
264  'nameValid': 'TracksForMinimalJetTag_isValid'
265  }
266  condargs.append((k, vals))
267 
268  else:
269  raise ValueError(f'btagger {v} not supported')
270 
271  # for the love of all that is whole could we turn these into functions
272  # instead of copy/paste?!
273  elif k == "gntau":
274  assert k in v
275  values = v.split(k)
276  assert values[1] == '' , 'gntau condition takes only one argument, two were given' # protection when an upper (not supported) cut is requested
277 
278  gntau_WPs = \
279  { '': float('-inf')
280  , '90': -0.846
281  , '85': 0.048
282  , '80': 0.693
283  , '75': 1.229
284  }
285 
286  assert (values[0] in gntau_WPs.keys()),f"The efficiency of the specified gntau cut \'{v}\' can not be found in the WP dictionary. Please add or remove the WP from the gntau WP dictionary."
287 
288  lo = gntau_WPs[values[0]]
289  vals = {
290  'min': str(lo),
291  'max': '',
292  'namePtau': 'fastGNTau20240216_ptau',
293  'namePu': 'fastGNTau20240216_pu',
294  'nameValid': 'TracksForMinimalJetTag_isValid'
295  }
296  condargs.append((k, vals))
297 
298  log.info("Adding HLT preselection: gntau %s", values[0])
299 
300  elif k == "uht1tau":
301  assert k in v
302  values = v.split(k)
303  assert values[1] == '' , 'uht1tau condition takes only one argument, two were given' # protection when an upper (not supported) cut is requested
304 
305  uht1tau_WPs = \
306  { '': float('-inf')
307  , '90': 0.556
308  , '87': 1.379
309  , '85': 1.936
310  , '82': 2.752
311  , '80': 3.259
312  }
313 
314  assert (values[0] in uht1tau_WPs.keys()),f"The efficiency of the specified uht1tau cut \'{v}\' can not be found in the WP dictionary. Please add or remove the WP from the gntau WP dictionary."
315 
316  lo = uht1tau_WPs[values[0]]
317  vals = {
318  'min': str(lo),
319  'max': '',
320  'namePtau': 'fastUHT120250605_ptau',
321  'namePu': 'fastUHT120250605_pu',
322  'nameValid': 'TracksForMinimalJetTag_isValid'
323  }
324  condargs.append((k, vals))
325 
326  log.info("Adding HLT preselection: uht1tau %s", values[0])
327 
328 
329  elif k == 'momCuts':
330  from TrigHLTJetHypo.FastReductionAlgToolFactory import jetMoments
331  if 'XX' in v: # several moment cuts are requested
332 
333  # loop over requested moment strings
334  for cutstr in _cuts_from_momCuts(v):
335  for moment in jetMoments: # loop over possible jet moments
336  if moment in cutstr:
337  key='mom{}'.format(moment)
338  lo, hi = cutstr.split(key)
339  vals = defaults(k, lo=lo, hi=hi)
340  vals["moment"] = jetMoments[moment]
341  condargs.append((key, vals))
342  else: # a single moment cut is requested
343  for moment in jetMoments: # loop over possible jet moments
344  if moment in v:
345  key='mom{}'.format(moment)
346  lo, hi = v.split(key)
347  vals = defaults(k, lo=lo, hi=hi)
348  vals["moment"] = jetMoments[moment]
349  condargs.append((key, vals))
350 
351  elif k =='pileuprm':
352  key = 'pileuprm'
353  values = v.split(key)
354  if "n" in values[0]:
355  lo=values[0].replace("n","-",1)
356  if "n" in values[1]:
357  hi=values[1].replace("n","-",1)
358  vals = defaults(key, lo=lo, hi=hi)
359  condargs.append((key, vals))
360 
361  return condargs
362 
363 
364 def scenario_simple(chain_parts):
365  """build two lists of RepeatedConditionConfig objects
366  one list contains the Conditions to be used by FastReducer,
367  and the other Contains the conditions used to filter the Condition.
368  Each list has one entry per chain part"""
369 
370  assert chain_parts, 'routing error, module %s: no chain parts' % __name__
371 
372  repcondargs = []
373  filterparams = []
374  filterparam_inds = []
375 
376  ncp = 0
377 
378  # keep track of identical cond_args, which are given the same
379  # clique number.
380  # the C++ code will use the clique number for optimisation of
381  # the calculation of the combinations
382  #
383  # current implementation: condition filter not included.
384  clique_list = []
385  for cp in chain_parts:
386  ncp += 1
387 
388  # get the Condition parameters (cut values) for the
389  # elemental Conditions
390 
391  condargs = get_condition_args_from_chainpart(cp)
392 
393  multiplicity = int(cp['multiplicity'])
394  chainPartInd = cp['chainPartIndex']
395 
396  # no condition filtering
397  filterparam_inds.append(-1) # no Condition filter
398 
399  clique = None
400  try:
401  clique = clique_list.index(condargs)
402  except ValueError:
403  # seen for the first time
404  clique_list.append(condargs)
405  clique = len(clique_list)-1
406 
407  repcondargs.append(RepeatedConditionParams(tree_id = ncp,
408  tree_pid=0,
409  clique=clique,
410  chainPartInd=chainPartInd,
411  multiplicity=multiplicity,
412  condargs=condargs))
413 
414 
415  # treevec[i] gives the tree_id of the parent of the
416  # node with tree_id = i
417  treevec = make_treevec(repcondargs)
418  assert treevec == [0 for i in range(len(chain_parts) + 1)]
419 
420  assert len(repcondargs) == len(filterparam_inds)
421  helper_params = HelperConfigToolParams(treevec=treevec,
422  repcondargs=repcondargs,
423  filterparams=filterparams,
424  filterparam_inds=filterparam_inds)
425 
426  return [helper_params] # a list is one entry per FastReduction tree
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
vtune_athena.format
format
Definition: vtune_athena.py:14
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.scenario_simple.get_condition_args_from_chainpart
def get_condition_args_from_chainpart(cp)
Definition: scenario_simple.py:25
Base_Fragment.defaults
dictionary defaults
This includes now the top quark, the leptons and the bosons.
Definition: GeneratorFilters/share/common/Base_Fragment.py:79
python.make_treevec.make_treevec
def make_treevec(repcondargs)
Definition: make_treevec.py:3
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
str
Definition: BTagTrackIpAccessor.cxx:11
python.scenario_simple.scenario_simple
def scenario_simple(chain_parts)
Definition: scenario_simple.py:364
python.scenario_simple._cuts_from_momCuts
def _cuts_from_momCuts(momCuts)
Definition: scenario_simple.py:18
python.LArMinBiasAlgConfig.float
float
Definition: LArMinBiasAlgConfig.py:65