ATLAS Offline Software
Loading...
Searching...
No Matches
plugin_miniSim.py
Go to the documentation of this file.
1# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3
4# this plugin is for mini simulation of a set of GlobalSim algorithms
5
6# Example:
7# l1global-minisim --algs JET1 --filesInput JET1.topoc_pu_type:/eos/atlas/atlascerngroupdisk/trig-gbl/online/ValidationGate/input_data/hex/mc_events/JET1/myfile_tree.hex.txt --filesOutput JET1.topoc_pu_type:loopback.txt JET1.main_output:output.txt
8
9# example with pool output and presim:
10# l1global-minisim --presim efex --filesInput /eos/atlas/atlascerngroupdisk/trig-gbl/offline/validation/valid.mc21_14TeV.537540.MGPy8EG_hh_bbbb_vbf_novhh_5fs_l1cvv1cv1.recon.AOD.e8557_s4422_r16130/AOD.41930061._000069.pool.root.1 --evtMax 10 --filesOutput eFEXDriver.eFEXSysSimTool.Key_eFexTauxTOBOutputContainer:my.pool.root eFEXDriver.eFEXSysSimTool.Key_eFexEMxTOBOutputContainer:my.pool.root
11
12
13def setup(flags):
14 from AthenaCommon.Logging import logging
15 log = logging.getLogger('plugin_miniSim')
16
17 # turn off everything else from the steering script by default, unless user requested through flags
18 flags.DQ.doMonitoring=False
19 flags.Trigger.enableL1CaloPhase1=any([flags.Trigger.L1.doeFex,flags.Trigger.L1.dojFex,flags.Trigger.L1.dogFex])
20
21 flags.addFlag("GlobalSim.Algs",[])
22 flags.addFlag("GlobalSim.txtInputs",[])
23 flags.addFlag("GlobalSim.txtOutputs",[])
24 flags.addFlag("GlobalSim.poolOutputs",[])
25
26 from AthenaConfiguration.ComponentFactory import CompFactory
27 excludeAlgs = ["LArCellPreparationAlg", "GlobalSimulationAlg", "PU1SuppTestBenchAlg", "LArCellMuxAlg", "Egamma1_OnlineMapNbhoodAlg"]
28 availableAlgs = [f[:-3] for f in CompFactory.GlobalSim._getEntries()[-1] if f.endswith('Alg') and f not in excludeAlgs]
29
30
31 if flags.hasFlag("L1CaloAthMon.UnknownArgs"):
32 # declare additional parser arguments, and parse!
33 import argparse
34 parser = argparse.ArgumentParser(prog='l1global-minisim',formatter_class=argparse.RawTextHelpFormatter)
35 parser.add_argument('--presim',nargs='+',default=[],choices=["efex","jfex","gfex","muon"],help="What to pre-simulate")
36 parser.add_argument('--algs',nargs='*',default=[],help=f"algs to run. Available are: {', '.join(availableAlgs)}")
37 parser.add_argument('--filesInput',nargs='*',default=[],help="inputs. If nibbler, specify as <key>:<path>. <key> can be storegate key or algorithm input property (<alg>.<input>)") # just here for help dialog
38 parser.add_argument('--filesOutput',nargs='*',default=[],help="outputs to save, specify similarly to inputs")
39 if "--help" in flags.L1CaloAthMon.UnknownArgs:
40 # before parsing, set the epilog to list of alg parameters
41 epilog = "Availble Algorithm Parameters:\n"
42 from GaudiKernel.DataHandle import DataHandle
43 from AthenaCommon import CfgMgr
44 for algType in availableAlgs:
45 epilog += f" {algType}:\n"
46 propDocs = getattr(CfgMgr,f"GlobalSim__{algType}Alg")._propertyDocDct
47 for propName,propVal in getattr(CompFactory.GlobalSim,algType+"Alg").getDefaultProperties().items():
48 # skip properties that aren't part of the algorithm itself
49 description = propDocs[propName]
50 if f"[GlobalSim::{algType}Alg]" not in description: continue
51 description = description.replace(f"[GlobalSim::{algType}Alg]","")
52 epilog += f" .{propName}: {description}\n"
53 parser.epilog = epilog + "\n"
54 args,unknown = parser.parse_known_args(flags.L1CaloAthMon.UnknownArgs)
55 flags.L1CaloAthMon.UnknownArgs = unknown
56 flags.GlobalSim.Algs = args.algs
57 flags.GlobalSim.txtOutputs = args.filesOutput
58
59 if "efex" in args.presim: flags.Trigger.L1.doeFex=True
60 if "jfex" in args.presim: flags.Trigger.L1.dojFex=True
61 if "gfex" in args.presim: flags.Trigger.L1.dogFex=True
62 if "muon" in args.presim: flags.Trigger.L1.doMuon=True
63 flags.Trigger.enableL1CaloPhase1=any([flags.Trigger.L1.doeFex,flags.Trigger.L1.dojFex,flags.Trigger.L1.dogFex])
64
65 # determine inputs required (while checking algs exist)
66 algInputs = set()
67 algOutputs = set()
68 inputsMap = {}
69 outputsMap = {}
70 knownTypes = {} # if can identify the type from the alg metadata, will collect the types here
71 for alg in flags.GlobalSim.Algs:
72 # check alg exists
73 algType,algName = (alg.split("/") if "/" in alg else [alg,alg])
74 if not hasattr(CompFactory.GlobalSim,algType+"Alg"):
75 log.fatal(f"Unknown Alg: {algType}")
76 log.fatal(f"Available Algs: {availableAlgs}")
77 exit(-1)
78 # now iterate through read and write handles
79 from GaudiKernel.DataHandle import DataHandle
80 from AthenaCommon import CfgMgr
81 propDocs = getattr(CfgMgr,f"GlobalSim__{algType}Alg")._propertyDocDct
82 for propName,propVal in getattr(CompFactory.GlobalSim,algType+"Alg").getDefaultProperties().items():
83 if not isinstance(propVal,DataHandle): continue # skip non-handle properties
84 sgKey = propVal.Path.split('+')[-1]
85 # try to get the "type" from the property description
86 for item in propDocs[propName].split(";"):
87 item = item.strip()
88 if item.startswith("type="):
89 knownTypes[sgKey] = item[len("type="):]
90 knownTypes[f"{algName}.{propName}"] = item[len("type="):]
91 break
92 if propVal.Mode == 'W':
93 algOutputs.add(sgKey)
94 if sgKey not in outputsMap: outputsMap[sgKey] = []
95 outputsMap[sgKey] += [f"{algName}.{propName}"]
96 else:
97 algInputs.add(sgKey)
98 if sgKey not in inputsMap: inputsMap[sgKey] = []
99 inputsMap[sgKey] += [f"{algName}.{propName}"]
100
101 # remove from inputs the outputs of the other algs
102 # what is left will be what we need provided externally
103 algInputs -= algOutputs
104
105 log.info(f"Your algorithms {flags.GlobalSim.Algs} require the following inputs: {[i for a in algInputs for i in inputsMap[a]]}")
106 log.info(f"and produces the following outputs: {[i for a in algOutputs for i in outputsMap[a]]}")
107
108 # move any txt inputs into the txtInputs flag
109 cleanList = []
110 for f in flags.Input.Files:
111 if f.endswith(".txt"):
112 # must have two ":" in it ... check
113 if f.count(":") != 2:
114 if f.count(":")==1:
115 if f.split(":")[0] in knownTypes:
116 f = knownTypes[f.split(":")[0]] + ":" + f
117 else:
118 log.fatal(f"{f.split(':')[0]} has no known type. Add to algorithm metadata or otherwise specify it explicitly with '<type>:' prefix")
119 exit(-1)
120 else:
121 log.fatal("txt input must be specified in form <type>:<SGkey>:<filepath>")
122 exit(-1)
123 flags.GlobalSim.txtInputs += [f]
124 else:
125 cleanList += [f]
126 flags.Input.Files = cleanList
127
128 if len(flags.GlobalSim.txtInputs):
129 flags.Input.isMC = True # tell parts of job to behave as this was a simulation
130
131 if flags.Exec.MaxEvents==-1:
132 # determine max number of events of given input file types
133 maxVals = {}
134 for f in flags.GlobalSim.txtInputs:
135 typeAndName,path = f.rsplit(":",1)
136 if typeAndName not in maxVals: maxVals[typeAndName]=0
137 maxVals[typeAndName] += sum(1 for _ in open(path))
138 flags.Exec.MaxEvents = max(maxVals.values())
139 # use the total number of lines in all the input files as the max events
140 log.info(f"Processing {flags.Exec.MaxEvents} events from txt filesInput")
141
142 txtOutputs = list(flags.GlobalSim.txtOutputs)
143 flags.GlobalSim.txtOutputs = []
144 filenameMap = {}
145 for f in txtOutputs:
146 if f.endswith(".txt"):
147 # must have two ":" in it ... check
148 if f.count(":") != 2:
149 if f.count(":")==1:
150 if f.split(":")[0] in knownTypes:
151 f = knownTypes[f.split(":")[0]] + ":" + f
152 else:
153 log.fatal(f"{f.split(':')[0]} has no known type. Add to algorithm metadata or otherwise specify it explicitly with '<type>:' prefix")
154 exit(-1)
155 else:
156 log.fatal("txt output must be specified in form <type>:<SGkey>:<filepath>")
157 exit(-1)
158 flags.GlobalSim.txtOutputs += [f]
159 elif f.endswith(".pool.root"):
160 # need to add filenames to available outputs
161 filename = f.split(":")[-1]
162 if filename not in filenameMap:
163 filenameMap[filename] = f"GSIM{len(filenameMap)}"
164 flags.addFlag("Output."+filenameMap[filename]+"FileName",filename) # used by OutputStreamConfig
165 flags.GlobalSim.poolOutputs += [f.replace(filename,filenameMap[filename])]
166
167
168# I may move this subsequence creation up into the steering script if I can figure out way to control `addEventAlgo` calls
169sequenceName = "GlobalSim"
170cfg.addSequence(CompFactory.AthSequencer(sequenceName,StopOverride=True),parentName="AthAlgSeq")
171
172
173# ---------------
174# algorithms added here:
175
176# create algos first, as will use properties to create readers
177algos = []
178for alg in flags.GlobalSim.Algs:
179 algType,algName = (alg.split("/") if "/" in alg else [alg,alg])
180 theAlg = getattr(CompFactory.GlobalSim,algType+"Alg")(algName)
181 algos += [theAlg]
182
183
184# add any readers for processing txt files
185readerNames = []
186for f in flags.GlobalSim.txtInputs:
187 tobType,sgKey,filepath = f.split(":")
188 if "." in sgKey:
189 # is an algo property not a key
190 foundProp = False
191 for a in algos:
192 if a.name == sgKey.split(".")[0]:
193 sgKey = getattr(a,sgKey.split(".")[1]).Path.split('+')[-1]
194 foundProp=True
195 break
196 if not foundProp:
197 log.fatal(f"Unknown input property: {sgKey}")
198 exit(-1)
199
200 cfg.addEventAlgo( CompFactory.GlobalSim.TOBTextReader(
201 sgKey+"Reader",BitSpec=tobType,
202 InputFile=filepath,
203 Output=sgKey), sequenceName=sequenceName )
204 readerNames += [sgKey+"Reader"]
205
206# now add the algs
207for theAlg in algos: cfg.addEventAlgo( theAlg, sequenceName=sequenceName )
208
209# add any writers
210for f in flags.GlobalSim.txtOutputs:
211 tobType,sgKey,filepath = f.split(":")
212 if "." in sgKey:
213 # is an algo property not a key
214 foundProp = False
215 for a in algos:
216 if a.name == sgKey.split(".")[0]:
217 sgKey = getattr(a,sgKey.split(".")[1]).Path.split('+')[-1]
218 foundProp=True
219 break
220 if not foundProp:
221 log.fatal(f"Unknown output property: {sgKey}")
222 exit(-1)
223 cfg.addEventAlgo( CompFactory.GlobalSim.TOBTextWriter(
224 sgKey+"Writer",
225 BitSpec=tobType,
226 Input=sgKey,
227 OutputFile=filepath), sequenceName=sequenceName )
228
229
230
231# ----------------
232
233# add the GraphSvc to visualize job
234cfg.addService( CompFactory.GlobalSim.GraphSvc(SequenceNameFilter=sequenceName,OutputLevel=3), create=True )
235
236if len(flags.GlobalSim.poolOutputs):
237 # we have pool file outputting ... build the output streams
238
239 allOutputs = {} # list of all outputs created during the job (i.e. writehandlekeys)
240
241 # get possible outputs from L1Calo presim:
242 from GaudiKernel.DataHandle import DataHandle
243 from GaudiConfig2 import Configurable
244 def getOutputs(c,prefix=""):
245 out = {}
246 for prop in c.getDefaultProperties().keys():
247 propVal = getattr(c,prop)
248 if isinstance(propVal,DataHandle) and propVal.Mode=='W':
249 out[prefix+"."+prop] = propVal
250 elif isinstance(propVal,Configurable):
251 out.update(getOutputs(propVal,prefix+"."+prop)) # recurse into subtools etc
252 return out
253 for alg in cfg.getEventAlgos("L1Sim")+cfg.getEventAlgos(sequenceName):
254 if alg is None: continue # if there is no L1Sim, seems getEventAlgos returns [None]
255 outputs = getOutputs(alg,alg.name)
256 allOutputs.update(outputs)
257
258 # build item lists
259 itemLists = {}
260 import ROOT
261 for output in flags.GlobalSim.poolOutputs:
262 what,stream = output.split(":")
263 if stream not in itemLists: itemLists[stream] = []
264 if what in allOutputs:
265 p = allOutputs[what]
266 theType = ROOT.TClass.GetClass(p.Type).GetName()
267 for a in ROOT.gROOT.GetListOfTypes():
268 if a.GetFullTypeName() == theType and "_v" not in a.GetName():
269 theType = a.GetName()
270 break
271 itemLists[stream] += [f"{theType}#{p.Path.split('+')[-1]}",f"{'xAOD::AuxContainerBase' if theType=='xAOD::BaseContainer' else theType.replace('Container','AuxContainer')}#{p.Path.split('+')[-1]}Aux."]
272
273 # register streams
274 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
275 for stream,items in itemLists.items():
276 print(stream,":",items)
277 cfg.merge(OutputStreamCfg(flags, stream, ItemList=items,takeItemsFromInput=False,disableEventTag=True))
278 cfg.getEventAlgo(f"Stream{stream}").WritingTool.SubLevelBranchName = "<key>"
279
void print(char *figname, TCanvas *c1)
#define max(a, b)
Definition cfImp.cxx:41
STL class.
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
getOutputs(c, prefix="")