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-2025 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('L1CaloPhase1Monitoring.py')
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","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
72# now parse
73
74parser = flags.getArgumentParser(epilog="""
75Extra flags are specified after a " -- " and the following are most relevant bool flags for this script:
76
77 Trigger.enableL1CaloPhase1 : turn on/off the offline simulation [default: True]
78 DQ.doMonitoring : turn on/off the monitoring [default: True]
79 Trigger.L1.doCaloInputs : controls input readout decoding and monitoring [default: False*]
80 Trigger.L1.doCalo : controls trex (legacy syst) monitoring [default: False]
81 Trigger.L1.doeFex : controls efex simulation and monitoring [default: False*]
82 Trigger.L1.dojFex : controls jfex simulation and monitoring [default: False*]
83 Trigger.L1.dogFex : controls gfex simulation and monitoring [default: False*]
84 Trigger.L1.doTopo : controls topo simulation and monitoring [default: False*] (from 2023 Onwards)
85 DQ.useTrigger : controls if JetEfficiency monitoring alg is run or not [default: False]
86 PerfMon.doFullMonMT : print info about execution time of algorithms and memory use etc [default: False]
87
88Note: If you do not specify any flags, then all the flags that are marked with a * will automatically become True
89
90E.g. to run just the jFex monitoring, without offline simulation, you can do:
91
92athena TrigT1CaloMonitoring/L1CalPhase1Monitoring.py .... -- Trigger.enableL1CaloPhase1=False Trigger.L1.doCaloInputs=False Trigger.L1.doeFex=False Trigger.L1.dogFex=False
93
94Further notes: Run with "--evtMax 0" to print flags and ca config, and generate a hanConfig file.
95 Run with "--evtMax 1" to dump StoreGate contents after the first event
96
97""")
98import argparse
99#class combinedFormatter(parser.formatter_class,argparse.RawDescriptionHelpFormatter): pass
100parser.formatter_class = argparse.RawDescriptionHelpFormatter
101parser.add_argument('--runNumber',default=None,help="specify to select a run number")
102parser.add_argument('--lumiBlock',default=None,help="specify to select a lumiBlock")
103parser.add_argument('--evtNumber',default=None,nargs="+",type=int,help="specify to select an evtNumber")
104parser.add_argument('--stream',default="*",help="stream to lookup files in")
105parser.add_argument('--fexReadoutFilter',action='store_true',help="If specified, will skip events without fexReadout")
106parser.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 ")
107parser.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.'")
108args,unknown_args = flags.fillFromArgs(parser=parser,return_unknown=True)
109args.postConfig += [x[4:] for x in unknown_args if x.startswith("cfg.")]
110if any([not x.startswith("cfg.") for x in unknown_args]):
111 raise KeyError("Unknown flags: " + " ".join([x for x in unknown_args if not x.startswith("cfg.")]))
112if 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]):
113 log.info("No steering flags specified, turning on phase 1 sim+monitoring (trex,efex,jfex,gfex,topo)")
114 flags.Trigger.L1.doCaloInputs = True # flag for saying if inputs should be decoded or not
115 flags.Trigger.L1.doCalo = True
116 flags.Trigger.L1.doeFex = True
117 flags.Trigger.L1.dojFex = True
118 flags.Trigger.L1.dogFex = True
119 flags.Trigger.L1.doTopo = True
120if args.runNumber is not None:
121 # todo: if an exact event number is provided, we can in theory use the event index and rucio to obtain a filename:
122 # e.g: event-lookup -D RAW "477048 3459682284"
123 # use GUID result to do:
124 # ~/getRucioLFNbyGUID.sh 264A4214-E922-EF11-AB28-B8CEF6444828
125 # gives a filename (last part): data24_13p6TeV.00477048.physics_Main.daq.RAW._lb0975._SFO-13._0001.data
126 from glob import glob
127 if args.lumiBlock is None: args.lumiBlock="*"
128 log.info(" ".join(("Looking up files in atlastier0 for run",args.runNumber,"lb =",args.lumiBlock)))
129 flags.Input.Files = []
130 for lb in args.lumiBlock.split(","):
131 if lb=="*":
132 tryStr = f"/eos/atlas/atlastier0/rucio/data*/{args.stream}/*{args.runNumber}/*RAW/*lb*.*"
133 else:
134 tryStr = f"/eos/atlas/atlastier0/rucio/data*/{args.stream}/*{args.runNumber}/*RAW/*lb{int(lb):04}.*"
135 log.info(" ".join(("Trying",tryStr)))
136 flags.Input.Files += glob(tryStr)
137 log.info(" ".join(("Found",str(len(flags.Input.Files)),"files")))
138
139standalone = False
140# require at least 1 input file if running offline, unless running config-generating mode ....
141if not partition.isValid() and len(flags.Input.Files)==0:
142 if flags.Exec.MaxEvents==0:
143 # this test file is used for generating the han config file
144 flags.Input.Files = ["/eos/atlas/atlascerngroupdisk/det-l1calo/OfflineSoftware/TestFiles/data24_13p6TeV/data24_13p6TeV.00477048.physics_Main.daq.RAW._lb0821._SFO-20._0001.data"]
145 else:
146 log.fatal("Running in offline mode but no input files provided")
147 exit(1)
148elif partition.isValid():
149 log.info("Running Online with Partition: "+partition.name())
150 standalone = (partition.name()!="ATLAS")
151 if standalone : log.info("Using local menu because partition is not ATLAS")
152 elif len(flags.Input.Files)==0:
153 # wait here for 2 minutes, to give LAr time to put fw info in the database
154 import time
155 log.info("Waiting 2 minutes for LATOME to get their databases in order")
156 time.sleep(120)
157
158# if running on an input file, change the DQ environment, which will allow debug tree creation from monitoring algs
159if len(flags.Input.Files)>0:
160 flags.DQ.Environment = "user"
161 # triggerConfig should default to DB which is appropriate if running on data
162 # standalone if project tag is data_test of dataXX_calib
163 standalone = ((flags.Input.ProjectName == "data_test") or (re.match(r"data\d\d_calib", flags.Input.ProjectName)))
164 if standalone : print("Using local menu because project_name=",flags.Input.ProjectName)
165 if flags.Input.isMC : flags.Trigger.triggerConfig='FILE' # uses the generated L1Menu (see below)
166 elif flags.Trigger.triggerConfig=='INFILE':
167 # this happens with AOD data files, but this is incompatible with the setup of the LVL1ConfigSvc
168 flags.Trigger.triggerConfig="DB" # so force onto DB usage
169 # legacy monitoring doesn't work with MC, so disable that if running on mc
170 if flags.Input.isMC and flags.Trigger.L1.doCalo:
171 log.info("Disabling legacy monitoring because it doesn't work with MC")
172 flags.Trigger.L1.doCalo=False
173
174if standalone :
175 flags.Trigger.triggerConfig='FILE' #Uses generated L1Menu In online on input files
176
177
178if flags.Exec.MaxEvents == 0:
179 # in this mode, ensure all monitoring activated, so that generated han config is complete
180 flags.DQ.doMonitoring=True
181 flags.Trigger.L1.doCalo=True
182 flags.Trigger.L1.doCaloInputs=True
183 flags.Trigger.L1.doeFex=True
184 flags.Trigger.L1.dojFex=True
185 flags.Trigger.L1.dogFex=True
186 flags.Trigger.L1.doTopo=True
187 flags.DQ.useTrigger=True # enables JetEfficiency algorithms
188 flags.Exec.OutputLevel = Constants.INFO
189
190# 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
191if flags.GeoModel.AtlasVersion is None:
192 from AthenaConfiguration.TestDefaults import defaultGeometryTags
193 flags.GeoModel.AtlasVersion = defaultGeometryTags.autoconfigure(flags)
194
195if (flags.Input.Format == Format.POOL): flags.Trigger.L1.doTopo = False #Deactivating L1Topo if Format is POOL
196if not flags.Trigger.L1.doTopo: flags.Trigger.L1.doMuon = False # don't do muons if not doing topo
197
198if flags.Trigger.enableL1CaloPhase1:
199 # add detector conditions flags required for rerunning simulation
200 # needs input files declared if offline, hence doing after parsing
201 from AthenaConfiguration.DetectorConfigFlags import setupDetectorsFromList
202 setupDetectorsFromList(flags,['LAr','Tile','MBTS'] + (['RPC','TGC','MDT'] if flags.Trigger.L1.doMuon else []),True)
203
204from AthenaConfiguration.MainServicesConfig import MainServicesCfg
205cfg = MainServicesCfg(flags)
206
207log.setLevel(logging.INFO)
208
209flags.lock()
210if flags.Exec.MaxEvents == 0: flags.dump(evaluate=True)
211
212# if nothing enabled, exit out here
213if 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]):
214 log.fatal("You did not set any flags to specify what to run. ")
215 log.fatal("Please set at least one of the flags in Trigger.L1.(doCaloInputs, doCalo, doeFex, dojFex, dogFex, doTopo) ")
216 log.fatal("or use '--all' option to turn on everything (but that is slow)")
217 log.fatal("See --help for more info about the flags")
218 exit(1)
219
220if partition.isValid() and len(flags.Input.Files)==0:
221 flags.dump(evaluate=True)
222 from ByteStreamEmonSvc.EmonByteStreamConfig import EmonByteStreamCfg
223 cfg.merge(EmonByteStreamCfg(flags)) # setup EmonSvc
224 bsSvc = cfg.getService("ByteStreamInputSvc")
225 bsSvc.Partition = partition.name()
226 bsSvc.Key = os.environ.get("L1CALO_PTIO_KEY", "REB" if partition.name()=="L1CaloStandalone" else "dcm") # set the Sampler Key Type name (default is SFI)
227 if partition.name()=="L1CaloSTF": bsSvc.Key = "SWROD"
228 bsSvc.KeyCount = int(os.environ.get("L1CALO_PTIO_KEY_COUNT","25"))
229 bsSvc.ISServer = "Histogramming" # IS server on which to create this provider
230 bsSvc.BufferSize = 10 # event buffer size for each sampler
231 bsSvc.UpdatePeriod = 30 # time in seconds between updating plots
232 bsSvc.Timeout = 240000 # timeout (not sure what this does)
233 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)
234 bsSvc.StreamType = os.getenv("L1CALO_PTIO_STREAM_TYPE","physics") # name of the stream type (physics,express, etc.)
235 bsSvc.ExitOnPartitionShutdown = False
236 bsSvc.ClearHistograms = True # clear hists at start of new run
237 bsSvc.GroupName = "RecExOnline"
238 # 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
239 bsSvc.StreamNames = os.getenv("L1CALO_PTIO_STREAM_NAME","L1Calo:Main:MinBias:MinBiasOverlay:UPC:EnhancedBias:ZeroBias:HardProbes:Standby:ALFACalib").split(":")
240 bsSvc.StreamLogic = os.getenv("L1CALO_PTIO_STREAM_LOGIC","Or") if partition.name() != "L1CaloStandalone" else "Ignore"
241 bsSvc.LVL1Names = [] # name of L1 items to select
242 bsSvc.LVL1Logic = "Ignore" # one of: Ignore, Or, And
243elif flags.Input.Format == Format.POOL:
244 log.info(f"Running Offline on {len(flags.Input.Files)} POOL files")
245 from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
246 cfg.merge(PoolReadCfg(flags))
247else:
248 log.info(f"Running Offline on {len(flags.Input.Files)} bytestream files")
249 #from ByteStreamCnvSvc.ByteStreamConfig import ByteStreamReadCfg
250 #TODO: Figure out why the above line causes CA conflict @ P1 if try to run on a RAW file there
251 from TriggerJobOpts.TriggerByteStreamConfig import ByteStreamReadCfg
252 cfg.merge(ByteStreamReadCfg(flags)) # configure reading bytestream
253
254# ensure histsvc is set up
255from AthenaMonitoring.AthMonitorCfgHelper import getDQTHistSvc
256cfg.merge(getDQTHistSvc(flags))
257
258# Create run3 L1 menu (needed for L1Calo EDMs)
259from TrigConfigSvc.TrigConfigSvcCfg import L1ConfigSvcCfg,generateL1Menu, createL1PrescalesFileFromMenu,getL1MenuFileName
260if flags.Trigger.triggerConfig=="FILE":
261 # for MC we set the TriggerConfig to "FILE" above, so must generate a menu for it to load (will be the release's menu)
262 generateL1Menu(flags)
263 createL1PrescalesFileFromMenu(flags)
264 menuFilename = getL1MenuFileName(flags)
265 if os.path.exists(menuFilename):
266 log.info(f"Using L1Menu: {menuFilename}")
267 else:
268 log.fatal(f"L1Menu file does not exist: {menuFilename}")
269 exit(1)
270cfg.merge(L1ConfigSvcCfg(flags))
271
272# -------- CHANGES GO BELOW ------------
273# setup the L1Calo software we want to monitor
274
275decoderTools = []
276
277if partition.isValid() or (flags.Input.Format != Format.POOL and not flags.Input.isMC):
278 from L1CaloFEXByteStream.L1CaloFEXByteStreamConfig import eFexByteStreamToolCfg, jFexRoiByteStreamToolCfg, jFexInputByteStreamToolCfg, gFexByteStreamToolCfg, gFexInputByteStreamToolCfg
279 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))]
280 if flags.Trigger.L1.dojFex: decoderTools += [cfg.popToolsAndMerge(jFexRoiByteStreamToolCfg(flags=flags,name="jFexBSDecoderTool",writeBS=False))]
281 if flags.Trigger.L1.dogFex: decoderTools += [cfg.popToolsAndMerge(gFexByteStreamToolCfg(flags=flags,name="gFexBSDecoderTool",writeBS=False))]
282
283 if flags.Trigger.L1.doMuon:
284 from MuonConfig.MuonBytestreamDecodeConfig import RpcBytestreamDecodeCfg,TgcBytestreamDecodeCfg
285 cfg.merge(RpcBytestreamDecodeCfg(flags))
286 cfg.merge(TgcBytestreamDecodeCfg(flags))
287 from TrigT1ResultByteStream.TrigT1ResultByteStreamConfig import MuonRoIByteStreamToolCfg
288 decoderTools += [cfg.popToolsAndMerge(MuonRoIByteStreamToolCfg(flags, name="L1MuonBSDecoderTool", writeBS=False))]
289
290
291 if flags.Trigger.L1.doCaloInputs:
292 if flags.Trigger.L1.dojFex: decoderTools += [cfg.popToolsAndMerge(jFexInputByteStreamToolCfg(flags=flags,name='jFexInputBSDecoderTool',writeBS=False))]
293 if flags.Trigger.L1.dogFex: decoderTools += [cfg.popToolsAndMerge(gFexInputByteStreamToolCfg(flags=flags,name='gFexInputBSDecoderTool',writeBS=False))]
294
295 if len(decoderTools) > 0:
296 from TrigT1ResultByteStream.TrigT1ResultByteStreamMonitoringConfig import L1TriggerByteStreamDecoderMonitoringCfg
297 cfg.addEventAlgo(CompFactory.L1TriggerByteStreamDecoderAlg(
298 name="L1TriggerByteStreamDecoder",
299 OutputLevel=Constants.ERROR, # hides warnings about non-zero status codes in fragments ... will show up in hists
300 DecoderTools=decoderTools,
301 ByteStreamMetadataRHKey = '', # seems necessary @ P1 if trying to run on a raw file
302 MaybeMissingROBs= [id for tool in decoderTools for id in tool.ROBIDs ] if partition.name()!="ATLAS" or not partition.isValid() else [], # allow missing ROBs away from online ATLAS partition
303 MonTool= cfg.popToolsAndMerge(L1TriggerByteStreamDecoderMonitoringCfg(flags,"L1TriggerByteStreamDecoder", decoderTools))
304 ),sequenceName='AthAlgSeq'
305 )
306
307# rerun sim if required
308if flags.Trigger.enableL1CaloPhase1:
309 from L1CaloFEXSim.L1CaloFEXSimCfg import L1CaloFEXSimCfg
310 # note to self ... could look into input key remapping to avoid conflict with sim from input:
311 # from SGComps.AddressRemappingConfig import InputRenameCfg
312 # acc.merge(InputRenameCfg('xAOD::TriggerTowerContainer', 'xAODTriggerTowers_rerun', 'xAODTriggerTowers'))
313 cfg.merge(L1CaloFEXSimCfg(flags,outputSuffix="_ReSim" if flags.Input.Format == Format.POOL else ""))
314
315 if flags.Trigger.L1.doeFex:
316 # print the algoVersions of the eFex from menu:
317 from TrigConfigSvc.TriggerConfigAccess import getL1MenuAccess
318 L1_menu = getL1MenuAccess(flags)
319 L1_menu.printSummary()
320 em_algoVersion = L1_menu.thresholdExtraInfo("eEM").get("algoVersion", 0)
321 tau_algoVersion = L1_menu.thresholdExtraInfo("eTAU").get("algoVersion", 0)
322 log.info(f"algoVersions: eEM: {em_algoVersion}, eTAU: {tau_algoVersion}")
323
324
325 # scheduling simulation of topo
326 if flags.Trigger.L1.doTopo:
327 from L1TopoSimulation.L1TopoSimulationConfig import L1TopoSimulationCfg
328 cfg.merge(L1TopoSimulationCfg(flags,readMuCTPI=True,doMonitoring=False)) # monitoring scheduled separately below
329
330 # do otf masking:
331 # from IOVDbSvc.IOVDbSvcConfig import addFolders,addOverride
332 # #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!
333 # 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
334 # cfg.addCondAlgo(CompFactory.LArBadChannelCondAlg(name="MaskedSCCondAlg",ReadKey="/LAR/BadChannels/MaskedSC",isSC=True,CablingKey="LArOnOffIdMapSC",WriteKey="LArMaskedSC"))
335 # # note to self, if need to flag extensible after loaded elsewhere, look at property: cfg.getService("IOVDbSvc").Folders ... extend relevant entry with "<extensible/>"
336 # print(cfg.getService("MessageSvc"))
337 # cfg.getService("MessageSvc").errorLimit = 0
338 #
339 # cfg.getEventAlgo("L1_eFexEmulatedTowers").LArBadChannelKey = "LArMaskedSC"
340
341
342
343if flags.DQ.doMonitoring:
344 if flags.Trigger.L1.doCalo:
345 from TrigT1CaloMonitoring.PprMonitorAlgorithm import PprMonitoringConfig
346 cfg.merge(PprMonitoringConfig(flags))
347 from TrigT1CaloMonitoring.PPMSimBSMonitorAlgorithm import PPMSimBSMonitoringConfig
348 cfg.merge(PPMSimBSMonitoringConfig(flags))
349 from TrigT1CaloMonitoring.OverviewMonitorAlgorithm import OverviewMonitoringConfig
350 cfg.merge(OverviewMonitoringConfig(flags))
351 # CPM was disabled for run 480893 onwards, so stop monitoring that part
352 # could have used detectorMask to determine if CPM is disabled, but will just assume it here
353 OverviewMonAlg = cfg.getEventAlgo("OverviewMonAlg")
354 OverviewMonAlg.CPMErrorLocation = ""
355 OverviewMonAlg.CPMMismatchLocation = ""
356
357 if flags.Trigger.L1.doeFex:
358 from TrigT1CaloMonitoring.EfexMonitorAlgorithm import EfexMonitoringConfig
359 cfg.merge(EfexMonitoringConfig(flags))
360 EfexMonAlg = cfg.getEventAlgo('EfexMonAlg')
361 # do we need next lines??
362 EfexMonAlg.eFexEMTobKeyList = ['L1_eEMRoI', 'L1_eEMxRoI'] # default is just L1_eEMRoI
363 EfexMonAlg.eFexTauTobKeyList = ['L1_eTauRoI', 'L1_eTauxRoI']
364 # Adjust eFEX containers to be monitored to also monitor the sim RoI unless running on raw without simulation
365 if flags.Input.Format == Format.POOL or flags.Trigger.enableL1CaloPhase1:
366 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 ]
367 # monitoring of simulation vs hardware
368 if not flags.Input.isMC and flags.Trigger.enableL1CaloPhase1:
369 from TrigT1CaloMonitoring.EfexSimMonitorAlgorithm import EfexSimMonitoringConfig
370 cfg.merge(EfexSimMonitoringConfig(flags))
371 # EfexSimMonitorAlgorithm = cfg.getEventAlgo('EfexSimMonAlg')
372 # and now book the histograms that depend on the containers
373 from TrigT1CaloMonitoring.EfexMonitorAlgorithm import EfexMonitoringHistConfig
374 cfg.merge(EfexMonitoringHistConfig(flags,EfexMonAlg))
375
376 if flags.Trigger.L1.dojFex:
377 from TrigT1CaloMonitoring.JfexMonitorAlgorithm import JfexMonitoringConfig
378 cfg.merge(JfexMonitoringConfig(flags))
379 if not flags.Input.isMC and flags.Trigger.enableL1CaloPhase1:
380 from TrigT1CaloMonitoring.JfexSimMonitorAlgorithm import JfexSimMonitoringConfig
381 cfg.merge(JfexSimMonitoringConfig(flags))
382 if flags.Trigger.L1.dogFex:
383 from TrigT1CaloMonitoring.GfexMonitorAlgorithm import GfexMonitoringConfig
384 cfg.merge(GfexMonitoringConfig(flags))
385 if not flags.Input.isMC and flags.Trigger.enableL1CaloPhase1:
386 from TrigT1CaloMonitoring.GfexSimMonitorAlgorithm import GfexSimMonitoringConfig
387 cfg.merge(GfexSimMonitoringConfig(flags))
388 # generally can't include efficiency monitoring because requires too many things we don't have
389 # but b.c. alg requires TrigDecisionTool, we activate it if DQ.useTrigger explicitly set
390 if flags.DQ.useTrigger:
391 from TrigT1CaloMonitoring.JetEfficiencyMonitorAlgorithm import JetEfficiencyMonitoringConfig
392 cfg.merge(JetEfficiencyMonitoringConfig(flags))
393
394 if flags.Trigger.L1.doTopo:
395 from L1TopoOnlineMonitoring.L1TopoOnlineMonitoringConfig import Phase1TopoMonitoringCfg
396 cfg.merge(Phase1TopoMonitoringCfg(flags))
397
398 # input data monitoring
399 if flags.Trigger.L1.doCaloInputs and not flags.Input.isMC:
400 from TrigT1CaloMonitoring.EfexInputMonitorAlgorithm import EfexInputMonitoringConfig
401 if flags.Trigger.L1.doeFex: cfg.merge(EfexInputMonitoringConfig(flags))
402 from TrigT1CaloMonitoring.JfexInputMonitorAlgorithm import JfexInputMonitoringConfig
403 if flags.Trigger.L1.dojFex: cfg.merge(JfexInputMonitoringConfig(flags))
404 from TrigT1CaloMonitoring.GfexInputMonitorAlgorithm import GfexInputMonitoringConfig
405 if flags.Trigger.L1.dogFex: cfg.merge(GfexInputMonitoringConfig(flags))
406
407mainSeq = "AthAllAlgSeq"
408if args.fexReadoutFilter:
409 # want to take existing AthAllSeqSeq and move it inside a new sequence
410 topSeq = cfg.getSequence("AthAlgEvtSeq")
411 algSeq = cfg.getSequence(mainSeq)
412 mainSeq = "New" + mainSeq
413 # topSeq has three sub-sequencers ... preserve first and last
414 topSeq.Members = [topSeq.Members[0],CompFactory.AthSequencer(mainSeq),topSeq.Members[-1]]
415 cfg.addEventAlgo(CompFactory.L1IDFilterAlgorithm(),sequenceName=mainSeq)
416 cfg.getSequence(mainSeq).Members += [algSeq]
417
418if args.evtNumber is not None:
419 print("filtering events",args.evtNumber)
420 # similar adjustment with an event filter
421 topSeq = cfg.getSequence("AthAlgEvtSeq")
422 algSeq = cfg.getSequence(mainSeq)
423 mainSeq = "New" + mainSeq
424 # topSeq has three sub-sequencers ... preserve first and last
425 topSeq.Members = [topSeq.Members[0],CompFactory.AthSequencer(mainSeq),topSeq.Members[-1]]
426 cfg.addEventAlgo(CompFactory.EventNumberFilterAlgorithm("EvtNumberFilter",EventNumbers=args.evtNumber),sequenceName=mainSeq)
427 cfg.getSequence(mainSeq).Members += [algSeq]
428
429from PerfMonComps.PerfMonCompsConfig import PerfMonMTSvcCfg
430cfg.merge( PerfMonMTSvcCfg(flags) )
431
432from AthenaConfiguration.Utils import setupLoggingLevels
433setupLoggingLevels(flags,cfg)
434
435if any([s.name=="AthenaEventLoopMgr" for s in cfg.getServices()]): cfg.getService("AthenaEventLoopMgr").IntervalInSeconds = 30
436if any([s.name=="AvalancheSchedulerSvc" for s in cfg.getServices()]):
437 cfg.getService("AvalancheSchedulerSvc").ShowDataDependencies=True
438
439# need to override a folder tag for LAr while testing v6 firmware...
440if not flags.Input.isMC:
441 from LArConditionsCommon.LArRunFormat import getLArDTInfoForRun
442 runinfo = getLArDTInfoForRun(flags.Input.RunNumbers[0], connstring="COOLONL_LAR/CONDBR2")
443 if runinfo.FWversion()==6:
444 # need a dbOverride ... add it
445 if args.dbOverrides is None: args.dbOverrides = []
446 args.dbOverrides += ["/LAR/Identifier/LatomeMapping:LARIdentifierLatomeMapping-fw6"]
447
448
449
450if type(args.dbOverrides)==list:
451 from IOVDbSvc.IOVDbSvcConfig import addOverride
452 #examples:
453 #cfg.merge( addOverride(flags, folder="/TRIGGER/L1Calo/V1/Calibration/EfexEnergyCalib", db="sqlite://;schema=mytest.db;dbname=CONDBR2",tag="" ) )
454 #cfg.merge( addOverride(flags, folder="/TRIGGER/L1Calo/V1/Calibration/EfexNoiseCuts", db="sqlite://;schema=/afs/cern.ch/user/w/will/calib.sqlite;dbname=L1CALO",tag="" ) )
455 for override in args.dbOverrides:
456 folderName,dbPath = override.split("=",1) if "=" in override else (override,"")
457 if folderName == "": raise ValueError("Cannot parse dbOverride: " + override)
458 db = ""
459 if dbPath != "":
460 if ";dbname=" not in dbPath: dbPath += ";dbname=CONDBR2"
461 dbPath,dbInst = dbPath.split(";dbname=")
462 if not os.path.exists(dbPath): raise ValueError("dbOverride file doesn't exist: " + dbPath)
463 db = f"sqlite://;schema={dbPath};dbname={dbInst}"
464 tag = ""
465 if ":" in folderName:
466 folderName,tag = folderName.split(":",1)
467 if folderName[0] != "/": folderName = "/TRIGGER/L1Calo/V1/Calibration/" + folderName
468 log.info(" ".join(("Overriding COOL folder=",folderName,"db=",db,"tag=",tag)))
469 if db=="":
470 cfg.merge( addOverride(flags,folder=folderName,tag=tag))
471 else:
472 cfg.merge( addOverride(flags,folder=folderName,db=db,tag=tag))
473
474
475# configure output AOD if requested
476if flags.Output.AODFileName != "":
477 def addEDM(edmType, edmName):
478 if edmName.endswith("Sim") and flags.Input.Format == Format.POOL: edmName = edmName.replace("Sim","_ReSim")
479 auxType = edmType.replace('Container','AuxContainer')
480 return [f'{edmType}#{edmName}', f'{auxType}#{edmName}Aux.']
481
482 outputEDM = []
483
484 if flags.Trigger.L1.doeFex:
485 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMRoI")
486 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMRoISim")
487 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMxRoI")
488 outputEDM += addEDM('xAOD::eFexEMRoIContainer' , "L1_eEMxRoISim")
489
490 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauRoI")
491 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauRoISim")
492 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauxRoI")
493 outputEDM += addEDM('xAOD::eFexTauRoIContainer' , "L1_eTauxRoISim")
494
495 if flags.Trigger.L1.dojFex:
496 outputEDM += addEDM('xAOD::jFexTowerContainer' , "L1_jFexDataTowers")
497 outputEDM += addEDM('xAOD::jFexTowerContainer' , "L1_jFexEmulatedTowers")
498 outputEDM += addEDM('xAOD::jFexSRJetRoIContainer', 'L1_jFexSRJetRoISim')
499 outputEDM += addEDM('xAOD::jFexLRJetRoIContainer', 'L1_jFexLRJetRoISim')
500 outputEDM += addEDM('xAOD::jFexTauRoIContainer' , 'L1_jFexTauRoISim' )
501 outputEDM += addEDM('xAOD::jFexFwdElRoIContainer', 'L1_jFexFwdElRoISim')
502 outputEDM += addEDM('xAOD::jFexSumETRoIContainer', 'L1_jFexSumETRoISim')
503 outputEDM += addEDM('xAOD::jFexMETRoIContainer' , 'L1_jFexMETRoISim' )
504 outputEDM += addEDM('xAOD::jFexSRJetRoIContainer', 'L1_jFexSRJetRoI')
505 outputEDM += addEDM('xAOD::jFexLRJetRoIContainer', 'L1_jFexLRJetRoI')
506 outputEDM += addEDM('xAOD::jFexTauRoIContainer' , 'L1_jFexTauRoI' )
507 outputEDM += addEDM('xAOD::jFexFwdElRoIContainer', 'L1_jFexFwdElRoI')
508 outputEDM += addEDM('xAOD::jFexSumETRoIContainer', 'L1_jFexSumETRoI')
509 outputEDM += addEDM('xAOD::jFexMETRoIContainer' , 'L1_jFexMETRoI' )
510
511 outputEDM += addEDM('xAOD::jFexSRJetRoIContainer', 'L1_jFexSRJetxRoI')
512 outputEDM += addEDM('xAOD::jFexLRJetRoIContainer', 'L1_jFexLRJetxRoI')
513 outputEDM += addEDM('xAOD::jFexTauRoIContainer' , 'L1_jFexTauxRoI' )
514 outputEDM += addEDM('xAOD::jFexFwdElRoIContainer', 'L1_jFexFwdElxRoI')
515 outputEDM += addEDM('xAOD::jFexSumETRoIContainer', 'L1_jFexSumETxRoI')
516 outputEDM += addEDM('xAOD::jFexMETRoIContainer' , 'L1_jFexMETxRoI' )
517
518 if flags.Trigger.L1.dogFex:
519 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMETComponentsJwoj')
520 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMETComponentsJwojSim')
521 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMHTComponentsJwoj')
522 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMHTComponentsJwojSim')
523 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMSTComponentsJwoj')
524 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gMSTComponentsJwojSim')
525 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarEJwoj')
526 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarEJwojSim')
527 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarENoiseCutSim')
528 outputEDM += addEDM('xAOD::gFexGlobalRoIContainer','L1_gScalarERmsSim')
529
530 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexLRJetRoI')
531 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexLRJetRoISim')
532 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexSRJetRoI')
533 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexSRJetRoISim')
534 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexRhoRoI')
535 outputEDM += addEDM('xAOD::gFexJetRoIContainer','L1_gFexRhoRoISim')
536
537
538
539 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
540 cfg.merge(OutputStreamCfg(flags, 'AOD', ItemList=outputEDM, takeItemsFromInput=True))
541 from xAODMetaDataCnv.InfileMetaDataConfig import SetupMetaDataForStreamCfg
542 cfg.merge(SetupMetaDataForStreamCfg(flags, 'AOD'))
543
544
545if "MuonAlignmentCondAlg" in [a.name for a in cfg.getCondAlgos()]: cfg.getCondAlgo("MuonAlignmentCondAlg").OutputLevel=Constants.ERROR # this alg produces warnings every time, silence it!
546
547
548if flags.Trigger.L1.doeFex and (args.evtNumber is not None):
549 # when debugging individual events, add the eFex event dumper to the job
550 cfg.addEventAlgo(CompFactory.LVL1.eFexEventDumper(TowersKey="L1_eFexDataTowers",EMRoIKey="L1_eEMRoI",TauRoIKey="L1_eTauRoI"))
551
552# example of adding user algorithm
553# cfg.addEventAlgo(CompFactory.AnotherPackageAlg(),sequenceName="AthAlgSeq")
554
555for conf in args.postConfig:
556 compName,propNameAndVal=conf.split(".",1)
557 propName,propVal=propNameAndVal.split("=",1)
558 applied = False
559 from collections import defaultdict
560 availableComps = defaultdict(list)
561 for comp in [c for c in cfg._allComponents()]+cfg.getServices():
562 availableComps[comp.getType()] += [comp.getName()]
563 if comp.getName()==compName or comp.getType()==compName or comp.toStringProperty()==compName:
564 applied = True
565 try:
566 log.info("Setting "+compName+" property: "+propNameAndVal)
567 exec(f"comp.{propNameAndVal}")
568 except AttributeError as e:
569 log.fatal("Unknown property of " + compName +" : " + propNameAndVal)
570 log.fatal("See next line for available properties:")
571 print(comp)
572 raise e
573 break
574 if not applied:
575 print("Available comps:")
576 for k,v in availableComps.items():
577 print(k,":",*v,sep="\n\t")
578 raise ValueError(f"postConfig {conf} had no effect ... typo? See list above of available components")
579
580# -------- CHANGES GO ABOVE ------------
581
582if flags.Exec.MaxEvents==0: cfg.printConfig(withDetails = True, summariseProps = True, printDefaults = True)
583log.info( " ".join(("Configured Services:",*[svc.name for svc in cfg.getServices()])) )
584#print("Configured EventAlgos:",*[alg.name for alg in cfg.getEventAlgos()])
585#print("Configured CondAlgos:",*[alg.name for alg in cfg.getCondAlgos()])
586
587if flags.Exec.MaxEvents==1:
588 # special debugging mode
589 cfg.getService("StoreGateSvc").Dump=True
590 cfg.getService("DetectorStore").Dump=True
591
592# ensure printout level is low enough if dumping
593if cfg.getService("StoreGateSvc").Dump:
594 cfg.getService("StoreGateSvc").OutputLevel=3
595if cfg.getService("DetectorStore").Dump:
596 cfg.getService("DetectorStore").OutputLevel=3
597
598if flags.Exec.MaxEvents==0:
599 # create a han config file if running in config-only mode
600 # command used to generate official config:
601 # athena TrigT1CaloMonitoring/L1CaloPhase1Monitoring.py --evtMax 0
602 from TrigT1CaloMonitoring.LVL1CaloMonitoringConfig import L1CaloMonitorCfgHelper
603 L1CaloMonitorCfgHelper.printHanConfig()
604 cfg._wasMerged = True # prevents spurious error message showing up about cfg that wasn't used
605 exit(0)
606
607if cfg.run().isFailure():
608 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:130
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177