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