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