ATLAS Offline Software
Loading...
Searching...
No Matches
L1CaloPhase1Monitoring.py
Go to the documentation of this file.
1#!/usr/bin/env athena
2# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3
4
10
11from AthenaCommon.Logging import logging
12from AthenaCommon.Logging import log as topLog
13topLog.setLevel(logging.WARNING) # default to suppressing all info logging except our own
14log = logging.getLogger('l1calo-ath-mon')
15log.setLevel(logging.INFO)
16
17from TrigT1CaloMonitoring.LVL1CaloMonitoringConfig import L1CaloMonitorCfgHelper
18L1CaloMonitorCfgHelper.embargoed = ["Expert/Efficiency/gFEX/MuonReferenceTrigger/SRpt_L1_gJ400p0ETA25"]#,"Expert/Sim/L1TopoAlgoMismatchRateVsLB","Expert/Sim/L1TopoMultiplicityMismatchRateVsLumi"]
19
20
21
22from AthenaConfiguration.ComponentFactory import CompFactory
23from AthenaConfiguration.AllConfigFlags import initConfigFlags
24from AthenaConfiguration.Enums import LHCPeriod,Format
25from AthenaCommon import Constants
26import os
27import ispy
28import re
29partition = ispy.IPCPartition(os.getenv("TDAQ_PARTITION","ATLAS"))
30
31flags = initConfigFlags()
32flags.Input.Files = [] # so that when no files given we can detect that
33
34# Note: The order in which all these flag defaults get set is very fragile
35# so don't reorder the setup of this flags stuff
36
37
38flags.Exec.OutputLevel = Constants.WARNING # by default make everything output at WARNING level
39flags.Exec.InfoMessageComponents = ["AthenaEventLoopMgr","AthenaHiveEventLoopMgr","THistSvc","PerfMonMTSvc","ApplicationMgr","AvalancheSchedulerSvc"] # Re-enable some info messaging though
40flags.Exec.PrintAlgsSequence = True # print the alg sequence at the start of the job (helpful to see what is scheduled)
41# flags.Exec.FPE = -2 # disable FPE auditing ... set to 0 to re-enable
42
43
44flags.GeoModel.Run = LHCPeriod.Run3 # needed for LArGMConfig - or can infer from above
45flags.Common.useOnlineLumi = True # needed for lumi-scaled monitoring, only have lumi in online DB at this time
46flags.DQ.doMonitoring = True # use this flag to turn on/off monitoring in this application
47flags.DQ.enableLumiAccess = False # in fact, we don't need lumi access for now ... this turns it all off
48flags.DQ.FileKey = "" if partition.isValid() else "EXPERT" # histsvc file "name" to record to - Rafal asked it to be blank @ P1 ... means monitoring.root will be empty
49flags.Output.HISTFileName = os.getenv("L1CALO_ATHENA_JOB_NAME","") + "monitoring.root" # control names of monitoring root file - ensure each online monitoring job gets a different filename to avoid collision between processes
50flags.DQ.useTrigger = False # don't do TrigDecisionTool in MonitorCfg helper methods
51flags.Trigger.L1.doCaloInputs = partition.isValid() # flag for saying if inputs should be decoded or not
52flags.Trigger.enableL1CaloPhase1 = True # used by this script to turn on/off the simulation
53# flags for rerunning simulation - on by default only in online environment
54flags.Trigger.L1.doCalo = partition.isValid()
55flags.Trigger.L1.doeFex = partition.isValid()
56flags.Trigger.L1.dojFex = partition.isValid()
57flags.Trigger.L1.dogFex = partition.isValid()
58flags.Trigger.L1.doTopo = partition.isValid()
59# if running online, override these with autoconfig values
60# will set things like the GlobalTag automatically
61if partition.isValid():
62 # must ensure doLVL1 and doHLT are False, otherwise will get ByteStreamCnvSvc conflicts (TrigByteStreamCnvSvc is setup, but EMon setup provides ByteStreamCnvSvc)
63 # see TriggerByteStreamConfig.py
64 flags.Trigger.doLVL1 = False
65 flags.Trigger.doHLT = False
66 from AthenaConfiguration.AutoConfigOnlineRecoFlags import autoConfigOnlineRecoFlags
67 autoConfigOnlineRecoFlags(flags, partition.name()) # sets things like projectName etc which would otherwise be inferred from input file
68else:
69 flags.Trigger.doLVL1 = True # set this just so that IOBDb.GlobalTag is autoconfigured based on release setup if running on RAW (autoconfig will take it from POOL file if running on that)
70#flags.IOVDb.GlobalTag = lambda s: "OFLCOND-MC23-SDR-RUN3-02" if s.Input.isMC else "CONDBR2-ES1PA-2022-07" #"CONDBR2-HLTP-2022-02"
71
72import sys
73if "--help" in sys.argv:
74 # remove unused flag categories to clean up help printout.
75 neededCats = ["DQ","Trigger","PerfMon"]
76 for cat in list(flags._dynaflags.keys()):
77 if cat not in neededCats: del flags._dynaflags[cat]
78
79# now parse
80
81parser = flags.getArgumentParser(epilog="""
82Extra flags are specified after a " -- " and the following are most relevant flags for this script:
83
84 Trigger.enableL1CaloPhase1 : turn on/off the offline simulation [default: True]
85 DQ.doMonitoring : turn on/off the monitoring [default: True]
86 Trigger.L1.doCaloInputs : controls input readout decoding and monitoring [default: False*]
87 Trigger.L1.doCalo : controls trex (legacy syst) monitoring [default: False]
88 Trigger.L1.doeFex : controls efex simulation and monitoring [default: False*]
89 Trigger.L1.dojFex : controls jfex simulation and monitoring [default: False*]
90 Trigger.L1.dogFex : controls gfex simulation and monitoring [default: False*]
91 Trigger.L1.doTopo : controls topo simulation and monitoring [default: False*] (from 2023 Onwards)
92 Trigger.L1.doGlobal : controls global simulation and monitoring [default: False]
93 DQ.useTrigger : controls if JetEfficiency monitoring alg is run or not [default: False]
94 PerfMon.doFullMonMT : print info about execution time of algorithms and memory use etc [default: False]
95 Trigger.triggerConfig : if you specifying this as "FILE:<filename>" the script will use that L1 json menu. [default: "DB" (takes menu from DB for data)]
96
97Note: If you do not specify any flags, then all the flags that are marked with a * will automatically become True
98
99E.g. to run just the jFex monitoring, without offline simulation, you can do:
100
101l1calo-ath-mon .... -- Trigger.enableL1CaloPhase1=False Trigger.L1.doCaloInputs=False Trigger.L1.doeFex=False Trigger.L1.dogFex=False
102
103To run with a plugin you can do e.g:
104
105l1calo-ath-mon PluginPackage/plugin.py --evtMax 10 ...
106
107Further notes: Run with "--evtMax 0" to print flags and ca config, and generate a hanConfig file.
108 Run with "--evtMax 1" to dump StoreGate contents after the first event
109
110""")
111import argparse
112#class combinedFormatter(parser.formatter_class,argparse.RawDescriptionHelpFormatter): pass
113parser.formatter_class = argparse.RawDescriptionHelpFormatter
114parser.add_argument('--runNumber',default=None,help="specify to select a run number")
115parser.add_argument('--lumiBlock',default=None,help="specify to select a lumiBlock")
116parser.add_argument('--evtNumber',default=None,nargs="+",type=int,help="specify to select an evtNumber")
117parser.add_argument('--stream',default="*",help="stream to lookup files in")
118parser.add_argument('--fexReadoutFilter',action='store_true',help="If specified, will skip events without fexReadout")
119parser.add_argument('--dbOverrides',default=None,nargs="+",type=str,help="specify overrides of COOL database folders in form <folder>=<dbPath> or <folder>:<tag>[=<dbPath>] to override a tag, example: /TRIGGER/L1Calo/V1/Calibration/EfexEnergyCalib=mytest.db ")
120parser.add_argument('--postConfig',default=[],nargs="+",type=str,help="specify component properties to apply at the end of the config. Can also specify in the flags section if start with 'cfg.' Use '--postHelp' option to explore the configurables and their properties")
121parser.add_argument('--postInclude',default=[],nargs="+",type=str,help="specify python files to call before configuration completes")
122parser.add_argument('--postHelp',default=None,nargs="*",help="Displays configurables and their properties")
123args,unknown_args = flags.fillFromArgs(parser=parser,return_unknown=True)
124# check for files in unknown_args list ... will assume are plugins
125# this is copied from Include.py ... seems if I try import it, I get CA behaviour blockage
126try:
127 optionsPathEnv = os.environ[ 'JOBOPTSEARCHPATH' ]
128except Exception:
129 optionsPathEnv = os.curdir
130optionsPath = re.split( ',|' + os.pathsep, optionsPathEnv )
131if '' in optionsPath:
132 optionsPath[ optionsPath.index( '' ) ] = str(os.curdir)
133for fn in unknown_args:
134 from AthenaCommon.Utils.unixtools import FindFile
135 name = FindFile( os.path.expanduser( os.path.expandvars( fn ) ), optionsPath, os.R_OK )
136 if not name: name = FindFile( os.path.basename( fn ), optionsPath, os.R_OK )
137 if name:
138 args.postInclude += [fn]
139 unknown_args.remove(fn)
140
141
142args.postConfig += [x[4:] for x in unknown_args if x.startswith("cfg.")]
143if any([not x.startswith("cfg.") for x in unknown_args]):
144 raise KeyError("Unknown flags: " + " ".join([x for x in unknown_args if not x.startswith("cfg.")]))
145if not any([flags.Trigger.L1.doCalo,flags.Trigger.L1.doCaloInputs,flags.Trigger.L1.doeFex,flags.Trigger.L1.dojFex,flags.Trigger.L1.dogFex,flags.Trigger.L1.doTopo,flags.DQ.useTrigger]):
146 log.info("No steering flags specified, turning on all phase 1 systems (trex,efex,jfex,gfex,topo)")
147 flags.Trigger.L1.doCaloInputs = True # flag for saying if inputs should be decoded or not
148 flags.Trigger.L1.doCalo = True
149 flags.Trigger.L1.doeFex = True
150 flags.Trigger.L1.dojFex = True
151 flags.Trigger.L1.dogFex = True
152 flags.Trigger.L1.doTopo = True
153
154# check input files
155if len(flags.Input.Files)>0:
156 # check input files list for alias to default test files ... substituting them
157 from AthenaConfiguration.TestDefaults import defaultTestFiles
158 flags.Input.Files = [getattr(defaultTestFiles,f,f) for f in flags.Input.Files]
159 flags.Input.Files = [item for x in flags.Input.Files for item in (x if isinstance(x,list) else [x])] # flatten mix of str and list
160 # now also check for non-existent input files before continuing
161 for f in flags.Input.Files:
162 if not os.path.exists(f):
163 log.fatal(f"file '{f}' does not exist")
164 exit(-1)
165
166if args.runNumber is not None:
167 # todo: if an exact event number is provided, we can in theory use the event index and rucio to obtain a filename:
168 # e.g: event-lookup -D RAW "477048 3459682284"
169 # use GUID result to do:
170 # ~/getRucioLFNbyGUID.sh 264A4214-E922-EF11-AB28-B8CEF6444828
171 # gives a filename (last part): data24_13p6TeV.00477048.physics_Main.daq.RAW._lb0975._SFO-13._0001.data
172 from glob import glob
173 if args.lumiBlock is None: args.lumiBlock="*"
174 log.info(" ".join(("Looking up files in atlastier0 for run",args.runNumber,"lb =",args.lumiBlock)))
175 flags.Input.Files = []
176 for lb in args.lumiBlock.split(","):
177 if lb=="*":
178 tryStr = f"/eos/atlas/atlastier0/rucio/data*/{args.stream}/*{args.runNumber}/*RAW/*lb*.*"
179 else:
180 tryStr = f"/eos/atlas/atlastier0/rucio/data*/{args.stream}/*{args.runNumber}/*RAW/*lb{int(lb):04}.*"
181 log.info(" ".join(("Trying",tryStr)))
182 flags.Input.Files += glob(tryStr)
183 log.info(" ".join(("Found",str(len(flags.Input.Files)),"files")))
184
185customMenuFile = ""
186if type(flags.Trigger.triggerConfig)==str and flags.Trigger.triggerConfig.startswith("FILE:"):
187 customMenuFile = flags.Trigger.triggerConfig.split(":",1)[-1]
188 flags.Trigger.triggerConfig="FILE"
189
190standalone = False
191# require at least 1 input file if running offline, unless running config-generating mode ....
192if not flags.Common.isOnline and len(flags.Input.Files)==0:
193 if flags.Exec.MaxEvents==0:
194 # this test file is used for generating the han config file
195 flags.Input.Files = ["/eos/atlas/atlascerngroupdisk/det-l1calo/OfflineSoftware/TestFiles/data24_13p6TeV/data24_13p6TeV.00477048.physics_Main.daq.RAW._lb0821._SFO-20._0001.data"]
196 else:
197 log.fatal("Running in offline mode but no input files provided. Please specify with: --filesInput <file>")
198 from AthenaConfiguration.TestDefaults import defaultTestFiles
199 log.fatal("You can specify one of the default test files:" + ",".join([f for f in dir(defaultTestFiles) if f[0].isupper()]))
200 exit(-1)
201elif flags.Common.isOnline:
202 log.info("Running Online with Partition: "+partition.name())
203 # if the partition name is not set in the flags, run the autoconfig again
204 # this occurs when running the online monitoring config in offline environment for testing
205 if flags.Trigger.Online.partitionName == '':
206 # must ensure doLVL1 and doHLT are False, otherwise will get ByteStreamCnvSvc conflicts (TrigByteStreamCnvSvc is setup, but EMon setup provides ByteStreamCnvSvc)
207 # see TriggerByteStreamConfig.py
208 flags.Trigger.doLVL1 = False
209 flags.Trigger.doHLT = False
210 from AthenaConfiguration.AutoConfigOnlineRecoFlags import autoConfigOnlineRecoFlags
211 autoConfigOnlineRecoFlags(flags, partition.name())
212 standalone = (partition.name()!="ATLAS")
213 if standalone : log.info("Using local menu because partition is not ATLAS")
214 elif len(flags.Input.Files)==0 and partition.isValid():
215 # wait here for 2 minutes, to give LAr time to put fw info in the database
216 import time
217 log.info("Waiting 2 minutes for LATOME to get their databases in order")
218 time.sleep(120)
219
220# if running on an input file, change the DQ environment, which will allow debug tree creation from monitoring algs
221if len(flags.Input.Files)>0:
222 flags.DQ.Environment = "user"
223 # triggerConfig should default to DB which is appropriate if running on data
224 # standalone if project tag is data_test of dataXX_calib
225 standalone = ((flags.Input.ProjectName == "data_test") or (re.match(r"data\d\d_calib", flags.Input.ProjectName)))
226 if standalone : print("Using local menu because project_name=",flags.Input.ProjectName)
227 if flags.Input.isMC : flags.Trigger.triggerConfig='FILE' # uses the generated L1Menu (see below)
228 elif flags.Trigger.triggerConfig=='INFILE':
229 # this happens with AOD data files, but this is incompatible with the setup of the LVL1ConfigSvc
230 flags.Trigger.triggerConfig="DB" # so force onto DB usage
231 # legacy monitoring doesn't work with MC, so disable that if running on mc
232 if flags.Input.isMC and flags.Trigger.L1.doCalo:
233 log.info("Disabling legacy monitoring because it doesn't work with MC")
234 flags.Trigger.L1.doCalo=False
235
236if standalone :
237 flags.Trigger.triggerConfig='FILE' #Uses generated L1Menu In online on input files
238
239
240if flags.Exec.MaxEvents == 0:
241 # in this mode, ensure all monitoring activated, so that generated han config is complete
242 flags.DQ.doMonitoring=True
243 flags.Trigger.L1.doCalo=True
244 flags.Trigger.L1.doCaloInputs=True
245 flags.Trigger.L1.doeFex=True
246 flags.Trigger.L1.dojFex=True
247 flags.Trigger.L1.dogFex=True
248 flags.Trigger.L1.doTopo=True
249 flags.DQ.useTrigger=True # enables JetEfficiency algorithms
250 flags.Exec.OutputLevel = Constants.INFO
251
252# due to https://gitlab.cern.ch/atlas/athena/-/merge_requests/65253 must now specify geomodel explicitly if cant take from input file, but can autoconfigure it based on LHCPeriod set above
253if flags.GeoModel.AtlasVersion is None:
254 from AthenaConfiguration.TestDefaults import defaultGeometryTags
255 flags.GeoModel.AtlasVersion = defaultGeometryTags.autoconfigure(flags)
256
257if flags.Trigger.triggerConfig=="FILE" and flags.Trigger.L1.doCalo:
258 # HLTConfgSvc fails to load if using a json file for the menu
259 # so disable the legacy monitoring which triggers that svc
260 log.warning("Cannot run Legacy sim/mon when using json l1 menu. Disabling")
261 flags.Trigger.L1.doCalo=False
262
263if (flags.Input.Format == Format.POOL): flags.Trigger.L1.doTopo = False #Deactivating L1Topo if Format is POOL
264if not flags.Trigger.L1.doTopo: flags.Trigger.L1.doMuon = False # don't do muons if not doing topo
265
266if flags.Trigger.enableL1CaloPhase1:
267 # add detector conditions flags required for rerunning simulation
268 # needs input files declared if offline, hence doing after parsing
269 from AthenaConfiguration.DetectorConfigFlags import setupDetectorsFromList
270 setupDetectorsFromList(flags,['LAr','Tile','MBTS'] + (['RPC','TGC','MDT'] if flags.Trigger.L1.doMuon else []),True)
271
272from AthenaConfiguration.MainServicesConfig import MainServicesCfg
273cfg = MainServicesCfg(flags)
274
275log.setLevel(logging.INFO)
276
277if len(args.postInclude):
278 # call setup methods if any exist in the postIncludes
279 from AthenaCommon.Configurable import ConfigurableCABehavior
280 with ConfigurableCABehavior():
281 from AthenaCommon.Utils.unixtools import FindFile
282 import ast
283
284 def load_function(file_path, function_name):
285 with open(file_path, "r", encoding="utf-8") as f:
286 source = f.read()
287 tree = ast.parse(source, filename=file_path)
288 for node in tree.body:
289 if isinstance(node, ast.FunctionDef) and node.name == function_name:
290 # Create a module containing only this function
291 mod = ast.Module(body=[node], type_ignores=[])
292 # Compile it
293 code = compile(mod, filename=file_path, mode="exec")
294 namespace = {}
295 # Execute only the function definition
296 exec(code, namespace)
297 return namespace[function_name]
298 for fn in args.postInclude:
299 name = FindFile( os.path.expanduser( os.path.expandvars( fn ) ), optionsPath, os.R_OK )
300 if not name:
301 name = FindFile( os.path.basename( fn ), optionsPath, os.R_OK )
302 if not name: raise RuntimeError( 'plugin file %s can not be found' % fn )
303 func = load_function(name,"setup")
304 if func:
305 func(flags)
306
307
308flags.lock()
309if flags.Exec.MaxEvents == 0: flags.dump(evaluate=True)
310
311# if nothing enabled, exit out here
312if not any([flags.Trigger.L1.doCaloInputs,flags.Trigger.L1.doCalo,flags.Trigger.L1.doeFex,flags.Trigger.L1.dojFex,flags.Trigger.L1.dogFex,flags.Trigger.L1.doTopo]):
313 log.fatal("You did not set any flags to specify what to run. ")
314 log.fatal("Please set at least one of the flags in Trigger.L1.(doCaloInputs, doCalo, doeFex, dojFex, dogFex, doTopo) ")
315 log.fatal("or use '--all' option to turn on everything (but that is slow)")
316 log.fatal("See --help for more info about the flags")
317 exit(1)
318
319if flags.Common.isOnline and len(flags.Input.Files)==0:
320 flags.dump(evaluate=True)
321 from ByteStreamEmonSvc.EmonByteStreamConfig import EmonByteStreamCfg
322 cfg.merge(EmonByteStreamCfg(flags)) # setup EmonSvc
323 bsSvc = cfg.getService("ByteStreamInputSvc")
324 bsSvc.Partition = partition.name()
325 bsSvc.Key = os.environ.get("L1CALO_PTIO_KEY", "REB" if partition.name()=="L1CaloStandalone" else "dcm") # set the Sampler Key Type name (default is SFI)
326 if partition.name()=="L1CaloSTF": bsSvc.Key = "SWROD"
327 bsSvc.KeyCount = int(os.environ.get("L1CALO_PTIO_KEY_COUNT","25"))
328 bsSvc.ISServer = "Histogramming" # IS server on which to create this provider
329 bsSvc.BufferSize = 10 # event buffer size for each sampler
330 bsSvc.UpdatePeriod = 30 # time in seconds between updating plots
331 bsSvc.Timeout = 240000 # timeout (not sure what this does)
332 bsSvc.PublishName = os.getenv("L1CALO_ATHENA_JOB_NAME","testing") # set name of this publisher as it will appear in IS (default is "l1calo-athenaHLT"; change to something sensible for testing)
333 bsSvc.StreamType = os.getenv("L1CALO_PTIO_STREAM_TYPE","physics") # name of the stream type (physics,express, etc.)
334 bsSvc.ExitOnPartitionShutdown = False
335 bsSvc.ClearHistograms = True # clear hists at start of new run
336 bsSvc.GroupName = "RecExOnline"
337 # name of the stream (Egamma,JetTauEtmiss,MinBias,Standby, etc.), this can be a colon(:) separated list of streams that use the 'streamLogic' to combine stream for 2016 HI run
338 bsSvc.StreamNames = os.getenv("L1CALO_PTIO_STREAM_NAME","L1Calo:Main:MinBias:MinBiasOverlay:UPC:EnhancedBias:ZeroBias:HardProbes:Standby:ALFACalib").split(":")
339 bsSvc.StreamLogic = os.getenv("L1CALO_PTIO_STREAM_LOGIC","Or") if partition.name() != "L1CaloStandalone" else "Ignore"
340 bsSvc.LVL1Names = [] # name of L1 items to select
341 bsSvc.LVL1Logic = "Ignore" # one of: Ignore, Or, And
342elif flags.Input.Format == Format.POOL:
343 log.info(f"Running Offline on {len(flags.Input.Files)} POOL files: {flags.Input.Files[0]} ...")
344 from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
345 cfg.merge(PoolReadCfg(flags))
346else:
347 log.info(f"Running Offline on {len(flags.Input.Files)} bytestream files: {flags.Input.Files[0]} ...")
348 #from ByteStreamCnvSvc.ByteStreamConfig import ByteStreamReadCfg
349 #TODO: Figure out why the above line causes CA conflict @ P1 if try to run on a RAW file there
350 from TriggerJobOpts.TriggerByteStreamConfig import ByteStreamReadCfg
351 cfg.merge(ByteStreamReadCfg(flags)) # configure reading bytestream
352
353# ensure histsvc is set up
354from AthenaMonitoring.AthMonitorCfgHelper import getDQTHistSvc
355cfg.merge(getDQTHistSvc(flags))
356
357# Create run3 L1 menu (needed for L1Calo EDMs)
358from TrigConfigSvc.TrigConfigSvcCfg import L1ConfigSvcCfg,generateL1Menu, createL1PrescalesFileFromMenu,getL1MenuFileName
359if flags.Trigger.triggerConfig=="FILE":
360 # for MC we set the TriggerConfig to "FILE" above, so must generate a menu for it to load (will be the release's menu)
361 menuFilename = getL1MenuFileName(flags)
362 if customMenuFile == "":
363 if os.path.exists(menuFilename): os.remove(menuFilename)
364 generateL1Menu(flags)
365 else:
366 # create a symlink to the custom file
367 import os,errno
368 try:
369 os.symlink(customMenuFile, menuFilename)
370 except OSError as e:
371 if e.errno == errno.EEXIST:
372 os.remove(menuFilename)
373 os.symlink(customMenuFile, menuFilename)
374 else:
375 raise e
376 menuFilename = customMenuFile
377 if os.path.exists(menuFilename):
378 log.info(f"Using L1Menu: {menuFilename}")
379 else:
380 log.fatal(f"L1Menu file does not exist: {menuFilename}")
381 exit(1)
382 createL1PrescalesFileFromMenu(flags)
383cfg.merge(L1ConfigSvcCfg(flags))
384
385# -------- CHANGES GO BELOW ------------
386# setup the L1Calo software we want to monitor
387
388decoderTools = []
389
390if flags.Common.isOnline or (flags.Input.Format != Format.POOL and not flags.Input.isMC):
391 from L1CaloFEXByteStream.L1CaloFEXByteStreamConfig import eFexByteStreamToolCfg, jFexRoiByteStreamToolCfg, jFexInputByteStreamToolCfg, gFexByteStreamToolCfg, gFexInputByteStreamToolCfg
392 if flags.Trigger.L1.doeFex: decoderTools += [cfg.popToolsAndMerge(eFexByteStreamToolCfg(flags=flags,name='eFexBSDecoderTool',TOBs=flags.Trigger.L1.doeFex,xTOBs=flags.Trigger.L1.doeFex,decodeInputs=flags.Trigger.L1.doCaloInputs,multiSlice=True))]
393 if flags.Trigger.L1.dojFex: decoderTools += [cfg.popToolsAndMerge(jFexRoiByteStreamToolCfg(flags=flags,name="jFexBSDecoderTool",writeBS=False))]
394 if flags.Trigger.L1.dogFex: decoderTools += [cfg.popToolsAndMerge(gFexByteStreamToolCfg(flags=flags,name="gFexBSDecoderTool",writeBS=False))]
395 if flags.Trigger.L1.doTopo:
396 from L1TopoByteStream.L1TopoByteStreamConfig import L1TopoPhase1ByteStreamToolCfg
397 decoderTools += [cfg.popToolsAndMerge(L1TopoPhase1ByteStreamToolCfg(flags=flags,name="L1TopoBSDecoderTool",writeBS=False))]
398
399 if flags.Trigger.L1.doMuon:
400 from MuonConfig.MuonBytestreamDecodeConfig import RpcBytestreamDecodeCfg,TgcBytestreamDecodeCfg
401 cfg.merge(RpcBytestreamDecodeCfg(flags))
402 cfg.merge(TgcBytestreamDecodeCfg(flags))
403 from TrigT1ResultByteStream.TrigT1ResultByteStreamConfig import MuonRoIByteStreamToolCfg
404 decoderTools += [cfg.popToolsAndMerge(MuonRoIByteStreamToolCfg(flags, name="L1MuonBSDecoderTool", writeBS=False))]
405
406
407 if flags.Trigger.L1.doCaloInputs:
408 if flags.Trigger.L1.dojFex: decoderTools += [cfg.popToolsAndMerge(jFexInputByteStreamToolCfg(flags=flags,name='jFexInputBSDecoderTool',writeBS=False))]
409 if flags.Trigger.L1.dogFex: decoderTools += [cfg.popToolsAndMerge(gFexInputByteStreamToolCfg(flags=flags,name='gFexInputBSDecoderTool',writeBS=False))]
410
411 if len(decoderTools) > 0:
412 from TrigT1ResultByteStream.TrigT1ResultByteStreamMonitoringConfig import L1TriggerByteStreamDecoderMonitoringCfg
413 cfg.addEventAlgo(CompFactory.L1TriggerByteStreamDecoderAlg(
414 name="L1TriggerByteStreamDecoder",
415 OutputLevel=Constants.ERROR, # hides warnings about non-zero status codes in fragments ... will show up in hists
416 DecoderTools=decoderTools,
417 ByteStreamMetadataRHKey = '', # seems necessary @ P1 if trying to run on a raw file
418 MaybeMissingROBs= [id for tool in decoderTools for id in tool.ROBIDs ] if partition.name()!="ATLAS" or not flags.Common.isOnline else [], # allow missing ROBs away from online ATLAS partition
419 MonTool= cfg.popToolsAndMerge(L1TriggerByteStreamDecoderMonitoringCfg(flags,"L1TriggerByteStreamDecoder", decoderTools))
420 ),sequenceName='AthAlgSeq'
421 )
422
423# rerun sim if required
424if flags.Trigger.enableL1CaloPhase1:
425 from L1CaloFEXSim.L1CaloFEXSimCfg import L1CaloFEXSimCfg
426 # create a subsequence for the sim to live in; primarily keeps the config tidy
427 cfg.addSequence(CompFactory.AthSequencer("L1Sim",StopOverride=True),parentName="AthAlgSeq") # this matches the sequence name the helpers will create
428
429 # note to self ... could look into input key remapping to avoid conflict with sim from input:
430 # from SGComps.AddressRemappingConfig import InputRenameCfg
431 # acc.merge(InputRenameCfg('xAOD::TriggerTowerContainer', 'xAODTriggerTowers_rerun', 'xAODTriggerTowers'))
432 cfg.merge(L1CaloFEXSimCfg(flags,outputSuffix="_ReSim" if flags.Input.Format == Format.POOL else ""),sequenceName="L1Sim")
433 # scheduling simulation of topo
434 if flags.Trigger.L1.doTopo:
435 from L1TopoSimulation.L1TopoSimulationConfig import L1TopoSimulationCfg
436 cfg.merge(L1TopoSimulationCfg(flags,readMuCTPI=True,doMonitoring=False),sequenceName="L1Sim") # monitoring scheduled separately below
437 # check there aren't any duplicates in L1sim that are already in the main sequence
438 for alg in cfg.getSequence("L1Sim").Members:
439 if alg.name in [a.name for a in cfg.getSequence("AthAlgSeq").Members]:
440 cfg.getSequence("L1Sim").Members.remove(alg)
441
442
443 # Phase II Global simulation...
444 if "doGlobal" in flags.Trigger.L1 and flags.Trigger.L1.doGlobal:
445 # we will create a subsequence just for globalsim too
446 cfg.addSequence(CompFactory.AthSequencer("L1GlobalSim",StopOverride=True),parentName="AthAlgSeq")
447 from GlobalSimulation.GlobalSimulationConfig import GlobalSimulationCfg
448 cfg.merge(GlobalSimulationCfg(flags),sequenceName="L1GlobalSim")
449
450 if flags.Trigger.L1.doeFex:
451 # print the algoVersions of the eFex from menu:
452 from TrigConfigSvc.TriggerConfigAccess import getL1MenuAccess
453 L1_menu = getL1MenuAccess(flags)
454 L1_menu.printSummary()
455 em_algoVersion = L1_menu.thresholdExtraInfo("eEM").get("algoVersion", 0)
456 tau_algoVersion = L1_menu.thresholdExtraInfo("eTAU").get("algoVersion", 0)
457 log.info(f"algoVersions: eEM: {em_algoVersion}, eTAU: {tau_algoVersion}")
458
459
460
461 # do otf masking:
462 # from IOVDbSvc.IOVDbSvcConfig import addFolders,addOverride
463 # #cfg.merge(addFolders(flags,"<db>sqlite://;schema=/afs/cern.ch/user/w/will/new_maskedSCs_run457976.db;dbname=CONDBR2</db> /LAR/BadChannels/NoisyChannelsSC",className="CondAttrListCollection")) # dmCorr from DB!
464 # cfg.merge(addFolders(flags,"/LAR/BadChannels/MaskedSC","LAR_ONL",tag="LARBadChannelsMaskedSC-RUN3-UPD1-00",className="CondAttrListCollection",extensible=False)) # when run online, need folder to be extensible to force reload each event
465 # cfg.addCondAlgo(CompFactory.LArBadChannelCondAlg(name="MaskedSCCondAlg",ReadKey="/LAR/BadChannels/MaskedSC",isSC=True,CablingKey="LArOnOffIdMapSC",WriteKey="LArMaskedSC"))
466 # # note to self, if need to flag extensible after loaded elsewhere, look at property: cfg.getService("IOVDbSvc").Folders ... extend relevant entry with "<extensible/>"
467 # print(cfg.getService("MessageSvc"))
468 # cfg.getService("MessageSvc").errorLimit = 0
469 #
470 # cfg.getEventAlgo("L1_eFexEmulatedTowers").LArBadChannelKey = "LArMaskedSC"
471
472
473
474if flags.DQ.doMonitoring:
475 # create a subsequence for the sim to live in; primarily keeps the config tidy
476 cfg.addSequence(CompFactory.AthSequencer("L1Mon",StopOverride=True),parentName="AthAlgSeq") # this matches the sequence name the helpers will create
477 if flags.Trigger.L1.doCalo:
478 from TrigT1CaloMonitoring.PprMonitorAlgorithm import PprMonitoringConfig
479 cfg.merge(PprMonitoringConfig(flags),sequenceName="L1Mon")
480 from TrigT1CaloMonitoring.PPMSimBSMonitorAlgorithm import PPMSimBSMonitoringConfig
481 cfg.merge(PPMSimBSMonitoringConfig(flags),sequenceName="L1Mon")
482 from TrigT1CaloMonitoring.OverviewMonitorAlgorithm import OverviewMonitoringConfig
483 cfg.merge(OverviewMonitoringConfig(flags),sequenceName="L1Mon")
484 # CPM was disabled for run 480893 onwards, so stop monitoring that part
485 # could have used detectorMask to determine if CPM is disabled, but will just assume it here
486 OverviewMonAlg = cfg.getEventAlgo("OverviewMonAlg")
487 OverviewMonAlg.CPMErrorLocation = ""
488 OverviewMonAlg.CPMMismatchLocation = ""
489
490 if flags.Trigger.L1.doeFex:
491 from TrigT1CaloMonitoring.EfexMonitorAlgorithm import EfexMonitoringConfig
492 cfg.merge(EfexMonitoringConfig(flags),sequenceName="L1Mon")
493 EfexMonAlg = cfg.getEventAlgo('EfexMonAlg')
494 # do we need next lines??
495 EfexMonAlg.eFexEMTobKeyList = ['L1_eEMRoI', 'L1_eEMxRoI'] # default is just L1_eEMRoI
496 EfexMonAlg.eFexTauTobKeyList = ['L1_eTauRoI', 'L1_eTauxRoI']
497 # Adjust eFEX containers to be monitored to also monitor the sim RoI unless running on raw without simulation
498 if flags.Input.Format == Format.POOL or flags.Trigger.enableL1CaloPhase1:
499 for l in [EfexMonAlg.eFexEMTobKeyList,EfexMonAlg.eFexTauTobKeyList]: l += [x + ("_ReSim" if flags.Input.Format == Format.POOL and flags.Trigger.enableL1CaloPhase1 else "Sim") for x in l ]
500 # monitoring of simulation vs hardware
501 if not flags.Input.isMC and flags.Trigger.enableL1CaloPhase1:
502 from TrigT1CaloMonitoring.EfexSimMonitorAlgorithm import EfexSimMonitoringConfig
503 cfg.merge(EfexSimMonitoringConfig(flags),sequenceName="L1Mon")
504 # EfexSimMonitorAlgorithm = cfg.getEventAlgo('EfexSimMonAlg')
505 # and now book the histograms that depend on the containers
506 from TrigT1CaloMonitoring.EfexMonitorAlgorithm import EfexMonitoringHistConfig
507 cfg.merge(EfexMonitoringHistConfig(flags,EfexMonAlg),sequenceName="L1Mon")
508
509 if flags.Trigger.L1.dojFex:
510 from TrigT1CaloMonitoring.JfexMonitorAlgorithm import JfexMonitoringConfig
511 cfg.merge(JfexMonitoringConfig(flags),sequenceName="L1Mon")
512 if not flags.Input.isMC and flags.Trigger.enableL1CaloPhase1:
513 from TrigT1CaloMonitoring.JfexSimMonitorAlgorithm import JfexSimMonitoringConfig
514 cfg.merge(JfexSimMonitoringConfig(flags),sequenceName="L1Mon")
515 if flags.Trigger.L1.dogFex:
516 from TrigT1CaloMonitoring.GfexMonitorAlgorithm import GfexMonitoringConfig
517 cfg.merge(GfexMonitoringConfig(flags),sequenceName="L1Mon")
518 if not flags.Input.isMC and flags.Trigger.enableL1CaloPhase1:
519 from TrigT1CaloMonitoring.GfexSimMonitorAlgorithm import GfexSimMonitoringConfig
520 cfg.merge(GfexSimMonitoringConfig(flags),sequenceName="L1Mon")
521 # generally can't include efficiency monitoring because requires too many things we don't have
522 # but b.c. alg requires TrigDecisionTool, we activate it if DQ.useTrigger explicitly set
523 if flags.DQ.useTrigger:
524 from TrigT1CaloMonitoring.JetEfficiencyMonitorAlgorithm import JetEfficiencyMonitoringConfig
525 cfg.merge(JetEfficiencyMonitoringConfig(flags),sequenceName="L1Mon")
526
527 if flags.Trigger.L1.doTopo:
528 from L1TopoOnlineMonitoring.L1TopoOnlineMonitoringConfig import Phase1TopoMonitoringCfg
529 cfg.merge(Phase1TopoMonitoringCfg(flags))
530
531 # input data monitoring
532 if flags.Trigger.L1.doCaloInputs and not flags.Input.isMC:
533 from TrigT1CaloMonitoring.EfexInputMonitorAlgorithm import EfexInputMonitoringConfig
534 if flags.Trigger.L1.doeFex: cfg.merge(EfexInputMonitoringConfig(flags),sequenceName="L1Mon")
535 from TrigT1CaloMonitoring.JfexInputMonitorAlgorithm import JfexInputMonitoringConfig
536 if flags.Trigger.L1.dojFex: cfg.merge(JfexInputMonitoringConfig(flags),sequenceName="L1Mon")
537 from TrigT1CaloMonitoring.GfexInputMonitorAlgorithm import GfexInputMonitoringConfig
538 if flags.Trigger.L1.dogFex: cfg.merge(GfexInputMonitoringConfig(flags),sequenceName="L1Mon")
539
540mainSeq = "AthAllAlgSeq"
541if args.fexReadoutFilter:
542 # want to take existing AthAllSeqSeq and move it inside a new sequence
543 topSeq = cfg.getSequence("AthAlgEvtSeq")
544 algSeq = cfg.getSequence(mainSeq)
545 mainSeq = "New" + mainSeq
546 # topSeq has three sub-sequencers ... preserve first and last
547 topSeq.Members = [topSeq.Members[0],CompFactory.AthSequencer(mainSeq),topSeq.Members[-1]]
548 cfg.addEventAlgo(CompFactory.L1IDFilterAlgorithm(),sequenceName=mainSeq)
549 cfg.getSequence(mainSeq).Members += [algSeq]
550
551if args.evtNumber is not None:
552 print("filtering events",args.evtNumber)
553 # similar adjustment with an event filter
554 topSeq = cfg.getSequence("AthAlgEvtSeq")
555 algSeq = cfg.getSequence(mainSeq)
556 mainSeq = "New" + mainSeq
557 # topSeq has three sub-sequencers ... preserve first and last
558 topSeq.Members = [topSeq.Members[0],CompFactory.AthSequencer(mainSeq),topSeq.Members[-1]]
559 cfg.addEventAlgo(CompFactory.EventNumberFilterAlgorithm("EvtNumberFilter",EventNumbers=args.evtNumber),sequenceName=mainSeq)
560 cfg.getSequence(mainSeq).Members += [algSeq]
561
562from PerfMonComps.PerfMonCompsConfig import PerfMonMTSvcCfg
563cfg.merge( PerfMonMTSvcCfg(flags) )
564
565from AthenaConfiguration.Utils import setupLoggingLevels
566setupLoggingLevels(flags,cfg)
567
568if any([s.name=="AthenaEventLoopMgr" for s in cfg.getServices()]): cfg.getService("AthenaEventLoopMgr").IntervalInSeconds = 30
569if any([s.name=="AthenaHiveEventLoopMgr" for s in cfg.getServices()]): cfg.getService("AthenaHiveEventLoopMgr").EventPrintoutInterval = 100
570if any([s.name=="AvalancheSchedulerSvc" for s in cfg.getServices()]): cfg.getService("AvalancheSchedulerSvc").ShowDataDependencies=True
571
572# need to override a folder tag for LAr while testing v6 firmware...
573if not flags.Input.isMC:
574 from LArConditionsCommon.LArRunFormat import getLArDTInfoForRun
575 runinfo = getLArDTInfoForRun(flags.Input.RunNumbers[0], connstring="COOLONL_LAR/CONDBR2")
576 if runinfo.FWversion()==6:
577 # need a dbOverride ... add it
578 if args.dbOverrides is None: args.dbOverrides = []
579 args.dbOverrides += ["/LAR/Identifier/LatomeMapping:LARIdentifierLatomeMapping-fw6"]
580
581
582
583if type(args.dbOverrides)==list:
584 from IOVDbSvc.IOVDbSvcConfig import addOverride
585 #examples:
586 #cfg.merge( addOverride(flags, folder="/TRIGGER/L1Calo/V1/Calibration/EfexEnergyCalib", db="sqlite://;schema=mytest.db;dbname=CONDBR2",tag="" ) )
587 #cfg.merge( addOverride(flags, folder="/TRIGGER/L1Calo/V1/Calibration/EfexNoiseCuts", db="sqlite://;schema=/afs/cern.ch/user/w/will/calib.sqlite;dbname=L1CALO",tag="" ) )
588 for override in args.dbOverrides:
589 folderName,dbPath = override.split("=",1) if "=" in override else (override,"")
590 if folderName == "": raise ValueError("Cannot parse dbOverride: " + override)
591 db = ""
592 if dbPath != "":
593 if ";dbname=" not in dbPath: dbPath += ";dbname=CONDBR2"
594 dbPath,dbInst = dbPath.split(";dbname=")
595 if not os.path.exists(dbPath): raise ValueError("dbOverride file doesn't exist: " + dbPath)
596 db = f"sqlite://;schema={dbPath};dbname={dbInst}"
597 tag = ""
598 if ":" in folderName:
599 folderName,tag = folderName.split(":",1)
600 if folderName[0] != "/": folderName = "/TRIGGER/L1Calo/V1/Calibration/" + folderName
601 log.info(" ".join(("Overriding COOL folder=",folderName,"db=",db,"tag=",tag)))
602 if db=="":
603 cfg.merge( addOverride(flags,folder=folderName,tag=tag))
604 else:
605 cfg.merge( addOverride(flags,folder=folderName,db=db,tag=tag))
606
607
608# configure output AOD if requested
609if flags.Output.AODFileName != "":
610 def addEDM(edmType, edmName):
611 if edmName.endswith("Sim") and flags.Input.Format == Format.POOL: edmName = edmName.replace("Sim","_ReSim")
612 auxType = edmType.replace('Container','AuxContainer')
613 return [f'{edmType}#{edmName}', f'{auxType}#{edmName}Aux.']
614
615 outputEDM = []
616
617 if flags.Trigger.L1.doeFex:
618 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMRoI")
619 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMRoISim")
620 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMxRoI")
621 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMxRoISim")
622
623 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauRoI")
624 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauRoISim")
625 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauxRoI")
626 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauxRoISim")
627
628 if flags.Trigger.L1.dojFex:
629 outputEDM += addEDM('xAOD::jFexTowerContainer' , "L1_jFexDataTowers")
630 outputEDM += addEDM('xAOD::jFexTowerContainer' , "L1_jFexEmulatedTowers")
631 outputEDM += addEDM('xAOD::jFexSRJetRoIContainer', 'L1_jFexSRJetRoISim')
632 outputEDM += addEDM('xAOD::jFexLRJetRoIContainer', 'L1_jFexLRJetRoISim')
633 outputEDM += addEDM('xAOD::jFexTauRoIContainer' , 'L1_jFexTauRoISim' )
634 outputEDM += addEDM('xAOD::jFexFwdElRoIContainer', 'L1_jFexFwdElRoISim')
635 outputEDM += addEDM('xAOD::jFexSumETRoIContainer', 'L1_jFexSumETRoISim')
636 outputEDM += addEDM('xAOD::jFexMETRoIContainer' , 'L1_jFexMETRoISim' )
637 outputEDM += addEDM('xAOD::jFexSRJetRoIContainer', 'L1_jFexSRJetRoI')
638 outputEDM += addEDM('xAOD::jFexLRJetRoIContainer', 'L1_jFexLRJetRoI')
639 outputEDM += addEDM('xAOD::jFexTauRoIContainer' , 'L1_jFexTauRoI' )
640 outputEDM += addEDM('xAOD::jFexFwdElRoIContainer', 'L1_jFexFwdElRoI')
641 outputEDM += addEDM('xAOD::jFexSumETRoIContainer', 'L1_jFexSumETRoI')
642 outputEDM += addEDM('xAOD::jFexMETRoIContainer' , 'L1_jFexMETRoI' )
643
644 outputEDM += addEDM('xAOD::jFexSRJetRoIContainer', 'L1_jFexSRJetxRoI')
645 outputEDM += addEDM('xAOD::jFexLRJetRoIContainer', 'L1_jFexLRJetxRoI')
646 outputEDM += addEDM('xAOD::jFexTauRoIContainer' , 'L1_jFexTauxRoI' )
647 outputEDM += addEDM('xAOD::jFexFwdElRoIContainer', 'L1_jFexFwdElxRoI')
648 outputEDM += addEDM('xAOD::jFexSumETRoIContainer', 'L1_jFexSumETxRoI')
649 outputEDM += addEDM('xAOD::jFexMETRoIContainer' , 'L1_jFexMETxRoI' )
650
651 if flags.Trigger.L1.dogFex:
652 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMETComponentsJwoj')
653 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMETComponentsJwojSim')
654 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMHTComponentsJwoj')
655 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMHTComponentsJwojSim')
656 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMSTComponentsJwoj')
657 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMSTComponentsJwojSim')
658 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarEJwoj')
659 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarEJwojSim')
660 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarENoiseCutSim')
661 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarERmsSim')
662
663 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexLRJetRoI')
664 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexLRJetRoISim')
665 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexSRJetRoI')
666 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexSRJetRoISim')
667 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexRhoRoI')
668 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexRhoRoISim')
669
670
671
672 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
673 cfg.merge(OutputStreamCfg(flags, 'AOD', ItemList=outputEDM, takeItemsFromInput=True))
674 from xAODMetaDataCnv.InfileMetaDataConfig import SetupMetaDataForStreamCfg
675 cfg.merge(SetupMetaDataForStreamCfg(flags, 'AOD'))
676
677# configure RAW output if requested
678if flags.Output.BSFileName != "":
679 from TrigT1ResultByteStream.TrigT1ResultByteStreamConfig import L1TriggerByteStreamEncoderCfg
680 cfg.merge(L1TriggerByteStreamEncoderCfg(flags))
681
682 # create A TrigCompositeContainer with the things we want to write out
683 algo = CompFactory.L1TriggerResultMaker("OutputBSTCCMaker",
684 MuRoIKeys=[],
685 eFexEMRoIKeys=[], eFexTauRoIKeys=[],
686 jFexFwdElRoIKeys=[], jFexTauRoIKeys = [],
687 jFexSRJetRoIKeys = [], jFexLRJetRoIKeys = [],
688 gFexSRJetRoIKeys = [], gFexLRJetRoIKeys = [],
689 cTauRoIKey = "", cjTauLinkKey = "", ThresholdPatternTools= [],
690 L1TriggerResultWHKey = "OutputBSTCC")
691 if flags.Trigger.L1.doeFex:
692 algo.eFexEMRoIKeys = ["L1_eEMRoI","L1_eEMxRoI"] # will write these containers
693 algo.eFexTauRoIKeys = ["L1_eTauRoI","L1_eTauxRoI"]
694
695 if flags.Trigger.L1.dojFex:
696 algo.jFexSRJetRoIKeys = ["L1_jFexSRJetRoI"]
697 algo.jFexLRJetRoIKeys = ["L1_jFexLRJetRoI"]
698 algo.jFexTauRoIKeys = ["L1_jFexTauRoI"]
699 algo.jFexFwdElRoIKeys = ["L1_jFexFwdElRoI"]
700
701 if flags.Trigger.L1.dogFex:
702 algo.gFexSRJetRoIKeys = ["L1_gFexSRJetRoI"]
703 algo.gFexLRJetRoIKeys = ["L1_gFexLRJetRoI"]
704 algo.gScalarEJwojKeys = ["L1_gScalarEJwoj"]
705 algo.gMETComponentsJwojKeys = ["L1_gMETComponentsJwoj"]
706
707 cfg.addEventAlgo(algo)
708 from ByteStreamCnvSvc.ByteStreamConfig import ByteStreamWriteCfg
709 write = ByteStreamWriteCfg(flags, ["xAOD::TrigCompositeContainer#OutputBSTCC"])
710 cfg.merge(write)
711
712if "MuonAlignmentCondAlg" in [a.name for a in cfg.getCondAlgos()]: cfg.getCondAlgo("MuonAlignmentCondAlg").OutputLevel=Constants.ERROR # this alg produces warnings every time, silence it!
713
714
715if flags.Trigger.L1.doeFex and (args.evtNumber is not None):
716 # when debugging individual events, add the eFex event dumper to the job
717 cfg.addEventAlgo(CompFactory.LVL1.eFexEventDumper(TowersKey="L1_eFexDataTowers",EMRoIKey="L1_eEMRoI",TauRoIKey="L1_eTauRoI"))
718
719# example of adding user algorithm
720# cfg.addEventAlgo(CompFactory.AnotherPackageAlg(),sequenceName="AthAlgSeq")
721
722from AthenaCommon.Include import include
723from AthenaCommon.Configurable import ConfigurableCABehavior
724with ConfigurableCABehavior():
725 for inc in args.postInclude: include(inc)
726
727for conf in args.postConfig:
728 compName,propNameAndVal=conf.split(".",1)
729 propName,propVal=propNameAndVal.split("=",1)
730 applied = False
731 from collections import defaultdict
732 availableComps = defaultdict(list)
733 for comp in [c for c in cfg._allComponents()]+cfg.getServices():
734 availableComps[comp.getType()] += [comp.getName()]
735 if comp.getName()==compName or comp.getType()==compName or comp.toStringProperty()==compName:
736 applied = True
737 try:
738 log.info("Setting "+compName+" property: "+propNameAndVal)
739 exec(f"comp.{propNameAndVal}")
740 except AttributeError as e:
741 log.fatal("Unknown property of " + compName +" : " + propNameAndVal)
742 log.fatal("See next line for available properties:")
743 print(comp)
744 raise e
745 break
746 if not applied:
747 print("Available comps:")
748 for k,v in availableComps.items():
749 print(k,":",*v,sep="\n\t")
750 raise ValueError(f"postConfig {conf} had no effect ... typo? See list above of available components")
751
752if args.postHelp is not None:
753 from collections import defaultdict
754 availableComps = defaultdict(list)
755 for comp in [c for c in cfg._allComponents()]+cfg.getServices():
756 availableComps[comp.getType()] += [comp.getName()]
757 print("Available comps:")
758 for k,v in availableComps.items():
759 print("",k,":",", ".join(v))
760 exit(0)
761
762# -------- CHANGES GO ABOVE ------------
763
764if flags.Exec.MaxEvents==0: cfg.printConfig(withDetails = True, summariseProps = True, printDefaults = True)
765log.info( " ".join(("Configured Services:",*[svc.name for svc in cfg.getServices()])) )
766#print("Configured EventAlgos:",*[alg.name for alg in cfg.getEventAlgos()])
767#print("Configured CondAlgos:",*[alg.name for alg in cfg.getCondAlgos()])
768
769if flags.Exec.MaxEvents==1:
770 # special debugging mode
771 cfg.getService("StoreGateSvc").Dump=True
772 cfg.getService("DetectorStore").Dump=True
773
774# ensure printout level is low enough if dumping
775if cfg.getService("StoreGateSvc").Dump:
776 cfg.getService("StoreGateSvc").OutputLevel=3
777if cfg.getService("DetectorStore").Dump:
778 cfg.getService("DetectorStore").OutputLevel=3
779
780if args.interactive:
781 from AthenaConfiguration.ComponentAccumulator import startInteractive
782 oldLevel = int(cfg._msg.getEffectiveLevel()) # need effectivelevel to account for inheriting
783 cfg._msg.setLevel(logging.INFO) # reverting to info level to ease interactive
784 print("\n\nEntering interactive configuration mode. You can explore and edit the cfg object. Ctrl+D to configure application and move to pre-initialize step")
785 startInteractive(locals()|{"self":cfg})
786 cfg._msg.setLevel(oldLevel)
787 # force writing the history file so that if job fails we still get our history
788 import readline, os
789 readline.write_history_file(os.path.expanduser( '~/.athena.history' ))
790
791if flags.Exec.MaxEvents==0:
792 # create a han config file if running in config-only mode
793 # command used to generate official config:
794 # athena TrigT1CaloMonitoring/L1CaloPhase1Monitoring.py --evtMax 0
795 from TrigT1CaloMonitoring.LVL1CaloMonitoringConfig import L1CaloMonitorCfgHelper
796 L1CaloMonitorCfgHelper.printHanConfig()
797 cfg._wasMerged = True # prevents spurious error message showing up about cfg that wasn't used
798 exit(0)
799
800if cfg.run().isFailure():
801 exit(1)
void print(char *figname, TCanvas *c1)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
load_function(file_path, function_name)