ATLAS Offline Software
TopoAlgoDefMultiplicity.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 from collections import namedtuple
3 from AthenaCommon.Logging import logging
4 log = logging.getLogger(__name__)
5 
6 from ..Base.TopoAlgos import EMMultiplicityAlgo, TauMultiplicityAlgo, JetMultiplicityAlgo, XEMultiplicityAlgo, LArSaturationAlgo, ZeroBiasAlgo
7 from ..Base.TopoAlgorithms import AlgType, AlgCategory
8 
10  """
11  Defines the TopoAlgorithms that calculate multiplicities for L1Calo thresholds
12  The thresholds have to be explicitly defined here.
13  """
14  @staticmethod
16 
17  emThresholds_3bits = [
18  'eEM5', 'eEM7', 'eEM9', 'eEM10L',
19  ]
20  emThresholds_2bits = [
21  'eEM12L', 'eEM15', 'eEM18', 'eEM18L', 'eEM18M', 'eEM22M',
22  'eEM24L',
23  'eEM22A', 'eEM22C',
24  'eEM12',
25  ]
26  emVarThresholds_2bits = [
27  'eEM24VM', 'eEM26', 'eEM26L', 'eEM26M', 'eEM26T', 'eEM28M',
28  'eEM1', 'eEM2',
29  'eEM40L',
30 
31  # spares
32  'eEMSPARE1',
33  ]
34 
35  for em in emThresholds_3bits:
36  alg = EMMultiplicityAlgo( name = em,
37  threshold = em,
38  nbits = 3, classtype='eEmMultiplicity')
39  tm.registerTopoAlgo(alg)
40 
41  for em in emThresholds_2bits:
42  alg = EMMultiplicityAlgo( name = em,
43  threshold = em,
44  nbits = 2, classtype='eEmMultiplicity')
45  tm.registerTopoAlgo(alg)
46 
47  for em in emVarThresholds_2bits:
48  alg = EMMultiplicityAlgo( name = em,
49  threshold = em,
50  nbits = 2, classtype='eEmVarMultiplicity')
51  tm.registerTopoAlgo(alg)
52 
53  emThresholds_2bits = [
54  'jEM20', 'jEM20M',
55 
56  #spares
57  'jEMSPARE1',
58  ]
59  for em in emThresholds_2bits:
60  alg = EMMultiplicityAlgo( name = em,
61  threshold = em,
62  nbits = 2, classtype='jEmMultiplicity')
63  tm.registerTopoAlgo(alg)
64 
65  etauThresholds_3bits = [
66  'eTAU1', 'eTAU12', 'eTAU20',
67  ]
68  jtauThresholds_3bits = [
69  'jTAU20'
70  ]
71  ctauThresholds_3bits = [
72  'cTAU12M', 'cTAU20M', 'cTAUSPARE1',
73  ]
74  etauThresholds_2bits = [
75  'eTAU20L', 'eTAU20M', 'eTAU30', 'eTAU30M', 'eTAU35', 'eTAU35M', 'eTAU40HM', 'eTAU60', 'eTAU80', 'eTAU140',
76  'eTAU40HT', 'eTAU60HM','eTAU60HL', 'eTAU80HL',
77  ]
78  jtauThresholds_2bits = [
79  'jTAU1',
80  ]
81  ctauThresholds_2bits = [
82  'cTAU30M', 'cTAU35M',
83 
84  # spares
85  'cTAUSPARE2',
86  'cTAUSPARE3',
87  ]
88 
89  for tau in etauThresholds_3bits:
90  alg = TauMultiplicityAlgo( name = tau,
91  threshold = tau,
92  nbits = 3, classtype='eTauMultiplicity')
93  tm.registerTopoAlgo(alg)
94 
95  for tau in jtauThresholds_3bits:
96  alg = TauMultiplicityAlgo( name = tau,
97  threshold = tau,
98  nbits = 3, classtype='jTauMultiplicity')
99  tm.registerTopoAlgo(alg)
100 
101  for tau in ctauThresholds_3bits:
102  alg = TauMultiplicityAlgo( name = tau,
103  threshold = tau,
104  nbits = 3, classtype='cTauMultiplicity')
105  tm.registerTopoAlgo(alg)
106 
107  for tau in etauThresholds_2bits:
108  alg = TauMultiplicityAlgo( name = tau,
109  threshold = tau,
110  nbits = 2, classtype='eTauMultiplicity')
111  tm.registerTopoAlgo(alg)
112 
113  for tau in jtauThresholds_2bits:
114  alg = TauMultiplicityAlgo( name = tau,
115  threshold = tau,
116  nbits = 2, classtype='jTauMultiplicity')
117  tm.registerTopoAlgo(alg)
118 
119  for tau in ctauThresholds_2bits:
120  alg = TauMultiplicityAlgo( name = tau,
121  threshold = tau,
122  nbits = 2, classtype='cTauMultiplicity')
123  tm.registerTopoAlgo(alg)
124 
125 
126  jJThresholds_3bits = [
127  'jJ5', 'jJ10', 'jJ20', 'jJ30', 'jJ30p0ETA25', 'jJ40', 'jJ40p0ETA25', 'jJ50', 'jJ55', 'jJ55p0ETA23', 'jJ60',
128  ]
129  jJThresholds_2bits = [
130  'jJ70p0ETA23', 'jJ80', 'jJ80p0ETA25', 'jJ85p0ETA21',
131  'jJ90', 'jJ125',
132  'jJ140', 'jJ160', 'jJ180', 'jJ500',
133 
134  'jJ40p30ETA49', 'jJ50p30ETA49', 'jJ60p30ETA49', 'jJ90p30ETA49', 'jJ125p30ETA49',
135 
136  'jJ50p0ETA25',
137 
138  # spares
139  'jJSPARE1',
140  'jJSPARE2',
141  'jJSPARE3',
142 
143  ]
144 
145  for jJet in jJThresholds_3bits:
146  alg = JetMultiplicityAlgo( name = jJet,
147  threshold = jJet,
148  nbits = 3, classtype='jJetMultiplicity')
149  tm.registerTopoAlgo(alg)
150 
151  for jJet in jJThresholds_2bits:
152  alg = JetMultiplicityAlgo( name = jJet,
153  threshold = jJet,
154  nbits = 2, classtype='jJetMultiplicity')
155  tm.registerTopoAlgo(alg)
156 
157  jLJThresholds_2bits = [
158  # jLJ thresholds for commissioning
159  'jLJ80', 'jLJ120', 'jLJ140', 'jLJ180',
160 
161  # jLJ thresholds for production
162  'jLJ60', 'jLJ100', 'jLJ160', 'jLJ200',
163  ]
164 
165  for jLJet in jLJThresholds_2bits:
166  alg = JetMultiplicityAlgo( name = jLJet,
167  threshold = jLJet,
168  nbits = 2, classtype='jLJetMultiplicity')
169  tm.registerTopoAlgo(alg)
170 
171  gJThresholds_3bits = [ 'gJ20p0ETA25', 'gJ20p25ETA49', 'gJSPARE1', ]
172  gJThresholds_2bits = [ 'gJ50p0ETA25', 'gJ100p0ETA25', 'gJ400p0ETA25' ]
173 
174  for gJet in gJThresholds_3bits:
175  alg = JetMultiplicityAlgo( name = gJet,
176  threshold = gJet,
177  nbits = 3, classtype='gJetMultiplicity')
178  tm.registerTopoAlgo(alg)
179 
180  for gJet in gJThresholds_2bits:
181  alg = JetMultiplicityAlgo( name = gJet,
182  threshold = gJet,
183  nbits = 2, classtype='gJetMultiplicity')
184  tm.registerTopoAlgo(alg)
185 
186  gLJThresholds_2bits = [
187  'gLJ80p0ETA25', 'gLJ100p0ETA25', 'gLJ140p0ETA25', 'gLJ160p0ETA25',
188 
189  # spares
190  'gLJSPARE1', 'gLJSPARE2', 'gLJSPARE3', 'gLJSPARE4',
191  ]
192 
193  for gLJet in gLJThresholds_2bits:
194  alg = JetMultiplicityAlgo( name = gLJet,
195  threshold = gLJet,
196  nbits = 2, classtype='gLJetMultiplicity')
197  tm.registerTopoAlgo(alg)
198 
199  XEThresholds = [
200  'gXEJWOJ60', 'gXEJWOJ70', 'gXEJWOJ80', 'gXEJWOJ100', 'gXEJWOJ110', 'gXEJWOJ120', 'gXEJWOJ500',
201  #'gXERHO70', 'gXERHO100',
202  'gXENC70', 'gXENC100',
203 
204  'jXE60', 'jXE70', 'jXE80', 'jXE90', 'jXE100', 'jXE110', 'jXE120', 'jXE500',
205 
206  'jXEC100', 'jTE200', 'jTEC200', 'jTEFWD100', 'jTEFWDA100', 'jTEFWDC100',
207  'gTE3', 'gTE5', 'gTE10', 'gTE200',
208 
209  # additional jTE thresholds needed for heavy ion runs
210  'jTE3','jTE4','jTE5', 'jTE10', 'jTE20','jTE50',
211  'jTE100', 'jTE600', 'jTE1500', 'jTE4000', 'jTE6500', 'jTE8300', 'jTE9000', 'jTE10000', 'jTE12000',
212  'jTEFWDA1', 'jTEFWDC1', 'jTEFWDA5', 'jTEFWDC5',
213 
214  'gMHT500',
215 
216  'jXEPerf100',
217 
218  # spares (for any energy thresholds)
219  'jXESPARE1',
220 
221  ]
222 
223  for XE in XEThresholds:
224  alg = XEMultiplicityAlgo( name = XE,
225  threshold = XE,
226  nbits = 1)
227  tm.registerTopoAlgo(alg)
228 
229  tm.registerTopoAlgo(LArSaturationAlgo())
230 
231  tm.registerTopoAlgo(ZeroBiasAlgo("ZeroBiasA"))
232  tm.registerTopoAlgo(ZeroBiasAlgo("ZeroBiasB"))
233 
234 
235  @staticmethod
237  """
238  List of the constraints in terms of multiplicity algorithms, to make sure the menu fits
239  in the Topo1 FW.
240 
241  The Phase-I L1Topo boards contain 2 FPGAs, with 2 output fibers each (connected to the CTP).
242  Up to 96 bits per fiber.
243  """
244 
245  # Any changes in this mapping intended for use in P1 require changes in the L1Topo firmware!
246 
247  # If you include additional algorithms to the L1 MC Menu only for development and tests in Athena,
248  # that will still require reserving additional space space in each fiber for the new thrsholds.
249  # Please add them to the end of each fiber, and label those lines.
250 
251  # Thresholds containing "Perf" in the name are explicitly for development only within Athena,
252  # and don't require declaring dedicated bits (they're ignored by this check)
253 
254  multLimits = namedtuple('ML', ['thrtype', 'conn', 'nbit', 'startbit', 'endbit'])
255  multiplicities = [
256  # FPGA 0, Topo1 fiber 0
257  multLimits(thrtype='eEM', conn='Topo1Opt0', nbit=3, startbit=0, endbit=11),
258  multLimits(thrtype='eEM', conn='Topo1Opt0', nbit=2, startbit=24, endbit=43),
259  multLimits(thrtype='eEMV', conn='Topo1Opt0', nbit=2, startbit=44, endbit=63),
260  multLimits(thrtype='ZeroBiasA', conn='Topo1Opt0', nbit=1, startbit=64, endbit=64),
261 
262  # FPGA 0, Topo1 fiber 1
263  multLimits(thrtype='eTAU', conn='Topo1Opt1', nbit=3, startbit=0, endbit=8 ),
264  multLimits(thrtype='eTAU', conn='Topo1Opt1', nbit=2, startbit=12, endbit=35),
265  multLimits(thrtype='gLJ', conn='Topo1Opt1', nbit=2, startbit=40, endbit=55),
266  multLimits(thrtype='gJ', conn='Topo1Opt1', nbit=3, startbit=58, endbit=66),
267  multLimits(thrtype='gJ', conn='Topo1Opt1', nbit=2, startbit=70, endbit=75),
268  multLimits(thrtype='eTAU', conn='Topo1Opt1', nbit=2, startbit=78, endbit=81), # L1 MC pp Menu only
269 
270  # FPGA 1, Topo1 fiber 2
271  multLimits(thrtype='jJ', conn='Topo1Opt2', nbit=3, startbit=0, endbit=32),
272  multLimits(thrtype='jJ', conn='Topo1Opt2', nbit=2, startbit=36, endbit=73),
273  multLimits(thrtype='jLJ', conn='Topo1Opt2', nbit=2, startbit=78, endbit=93),
274 
275  # FPGA 1, Topo1 fiber 3
276  multLimits(thrtype='jTAU', conn='Topo1Opt3', nbit=3, startbit=0, endbit=2 ),
277  multLimits(thrtype='jTAU', conn='Topo1Opt3', nbit=2, startbit=6, endbit=7 ),
278  multLimits(thrtype='cTAU', conn='Topo1Opt3', nbit=3, startbit=14, endbit=22),
279  multLimits(thrtype='cTAU', conn='Topo1Opt3', nbit=2, startbit=23, endbit=30),
280  multLimits(thrtype='jEM', conn='Topo1Opt3', nbit=2, startbit=31, endbit=36),
281  multLimits(thrtype='LArSaturation', conn='Topo1Opt3', nbit=1, startbit=37, endbit=37),
282  multLimits(thrtype='ZeroBiasB', conn='Topo1Opt3', nbit=1, startbit=38, endbit=38),
283  multLimits(thrtype='EN', conn='Topo1Opt3', nbit=1, startbit=39, endbit=86),
284  ]
285 
286  for conn in l1menu.connectors:
287  if 'Topo1' not in conn.name or conn.legacy: continue
288 
289  for tl in conn.triggerLines:
290  if 'Perf' in tl.name: continue
291 
292  algo = l1menu.topoAlgos.topoAlgos[AlgCategory.MULTI][AlgType.MULT][f'Mult_{tl.name}']
293 
294  thrtype = algo.input
295  if 'LArSaturation' in algo.name:
296  thrtype = 'LArSaturation'
297  elif 'XE' in algo.input or 'TE' in algo.input or 'MHT' in algo.input:
298  thrtype = 'EN'
299  elif 'eEmVar' in algo.classtype:
300  thrtype = 'eEMV'
301 
302  for ml in multiplicities:
303  if conn.name == ml.conn and thrtype == ml.thrtype and algo.nbits == ml.nbit and tl.startbit >= ml.startbit and tl.endbit <= ml.endbit:
304  break
305  else:
306  raise RuntimeError(f'The multiplicity algorithm {algo.name} with startbit {tl.startbit} does not fit in the current Topo1 and CTP FWs. If this is intended, please correct the multiplicity constraints and communicate the new menu to the L1Topo and CTP groups.')
307 
308  # To ensure the correct alignment, also check for the Empty and (Empty, nbits) instances in the L1 Menu input fibers
309  for etl in conn.emptyTriggerLines:
310  log.debug('Empty Multiplicity placeholder in bits %i-%i of %s', etl.startbit, etl.endbit, conn.name)
311  for ml in multiplicities:
312  # We don't want to have any overlaps with the multiplicity declarations
313  if conn.name == ml.conn and etl.startbit >= ml.startbit and etl.endbit <= ml.endbit:
314  raise RuntimeError(f'One of the Empty or (Empty, nbits) Multiplicity algorithm placeholders in the L1 Menu is overlapping with the declared multiplicity algorithm bit ranges ({conn.name}, bits {etl.startbit}-{etl.endbit}). Check the bit mapping and algorithm alignments!')
python.L1.Base.TopoAlgos.JetMultiplicityAlgo
Definition: TopoAlgos.py:226
python.L1.Base.TopoAlgos.TauMultiplicityAlgo
Definition: TopoAlgos.py:216
python.L1.Base.TopoAlgos.XEMultiplicityAlgo
Definition: TopoAlgos.py:236
python.L1.Base.TopoAlgos.ZeroBiasAlgo
Definition: TopoAlgos.py:268
python.L1.Config.TopoAlgoDefMultiplicity.TopoAlgoDefMultiplicity
Definition: TopoAlgoDefMultiplicity.py:9
python.L1.Base.TopoAlgos.LArSaturationAlgo
Definition: TopoAlgos.py:263
python.L1.Config.TopoAlgoDefMultiplicity.TopoAlgoDefMultiplicity.registerTopoAlgos
def registerTopoAlgos(tm)
Definition: TopoAlgoDefMultiplicity.py:15
python.L1.Config.TopoAlgoDefMultiplicity.TopoAlgoDefMultiplicity.checkMultAlgoFWconstraints
def checkMultAlgoFWconstraints(l1menu)
Definition: TopoAlgoDefMultiplicity.py:236
python.L1.Base.TopoAlgos.EMMultiplicityAlgo
Definition: TopoAlgos.py:206