213 onlyComponents = [], printDefaults=False, printSequenceTreeOnly=False, prefix=None):
214 msg = logging.getLogger(prefix)
if prefix
else self.
_msg
216 msg.info(
"Event Algorithm Sequences" )
218 def printSeqAndAlgs(seq, nestLevel = 0,
219 onlyComponents = []):
221 if name
in seq._properties:
222 return seq._properties[name]
223 return seq._descriptors[name].default
225 msg.info(
"%s\\__ %s (seq: %s %s)",
" "*nestLevel, seq.name,
226 "SEQ" if __prop(
"Sequential")
else "PAR",
229 msg.info(
"%s\\__ %s",
" "*nestLevel, seq.name)
234 printSeqAndAlgs(c, nestLevel, onlyComponents = onlyComponents )
237 msg.info(
"%s\\__ %s (alg) %s",
" "*nestLevel, c.getFullJobOptName(), self.
_componentsContext.
get(c.name,
""))
239 msg.info(
"%s\\__ %s",
" "*nestLevel, c.name )
240 if summariseProps
and flag:
245 msg.info(
"Top sequence %d", n )
246 printSeqAndAlgs(s, onlyComponents = onlyComponents)
248 if printSequenceTreeOnly:
252 onlyComponents = onlyComponents)
253 msg.info(
"Services" )
254 msg.info( [ s[0].name + (
" (created) " if s[0].name
in self.
_servicesToCreate else "")
255 for s
in filterComponents (self.
_services, onlyComponents) ] )
256 msg.info(
"Public Tools" )
258 for (t, flag)
in filterComponents (self.
_publicTools, onlyComponents):
261 if summariseProps
and flag:
264 msg.info(
"Private Tools")
273 msg.info(
"Auditors" )
276 msg.info(
"theApp properties" )
278 msg.info(
" %s : %s", k, v)
464 def addEventAlgo(self, algorithms,sequenceName=None,primary=False,domain=None):
465 if not isinstance(algorithms, Sequence):
467 algorithms=[algorithms,]
469 if sequenceName
is None:
472 seq = findSubSequence(self.
_sequence,
'AthAlgSeq')
476 seq = findSubSequence(self.
_sequence, sequenceName)
481 for algo
in algorithms:
482 if not isinstance(algo, GaudiConfig2.Configurable):
483 raise TypeError(f
"Attempt to add wrong type: {type(algo).__name__} as event algorithm")
485 if algo.__component_type__ !=
"Algorithm":
486 raise TypeError(f
"Attempt to add an {algo.__component_type__} as event algorithm")
489 context = createContextForDeduplication(
"Merging with existing Event Algorithm", algo.name, self.
_componentsContext)
495 existingAlgInDest = findAlgorithm(seq, algo.name)
496 if not existingAlgInDest:
502 if len(algorithms)>1:
503 self.
_msg.warning(
"Called addEvenAlgo with a list of algorithms and primary==True. "
504 "Designating the first algorithm as primary component")
506 self.
_msg.warning(
"addEventAlgo: Overwriting primary component of this CA. Was %s/%s, now %s/%s",
508 algorithms[0].__cpp_type__, algorithms[0].name)
513 if "trackEventAlgo" in ComponentAccumulator.debugMode:
514 for algo
in algorithms:
970 # Set ROOT batch mode
971 from PyUtils.Helpers import ROOTSetup
972 ROOTSetup(batch = not self.interactive)
974 # Create the Gaudi object early.
975 # Without this here, pyroot can sometimes get confused
976 # and report spurious type mismatch errors about this object.
980 appPropsToSet, mspPropsToSet, bshPropsToSet = self.gatherProps()
982 self._wasMerged = True
983 from Gaudi.Main import BootstrapHelper
985 bsh = BootstrapHelper()
986 app = bsh.createApplicationMgr()
988 for k, v in appPropsToSet.items():
989 self._msg.debug("Setting property %s : %s", k, v)
990 app.setProperty(k, v)
994 msp = app.getService("MessageSvc")
995 for k, v in mspPropsToSet.items():
996 self._msg.debug("Setting property %s : %s", k, v)
997 bsh.setProperty(msp, k.encode(), v.encode())
999 # Feed the jobO service with the remaining options
1000 for comp, name, value in bshPropsToSet:
1001 self._msg.debug("Adding %s.%s = %s", comp, name, value)
1002 app.setOption(f"{comp}.{name}", value)
1007 def gatherProps(self):
1008 appPropsToSet = {k: str(v) for k, v in self._theAppProps.items()}
1013 for svc in self._services:
1015 svc.getFullJobOptName(),
1017 if svc.getFullJobOptName() in self._servicesToCreate:
1018 svcToCreate.append(svc.getFullJobOptName())
1020 # order basic services
1021 for bs in reversed(_basicServicesToCreateOrder):
1022 if bs in svcToCreate:
1023 svcToCreate.insert(0, svcToCreate.pop( svcToCreate.index(bs) ) )
1025 extSvc.append("PyAthena::PyComponentMgr/PyComponentMgr")
1027 appPropsToSet["ExtSvc"] = str(extSvc)
1028 appPropsToSet["CreateSvc"] = str(svcToCreate)
1030 def getCompsToBeAdded(comp, namePrefix=""):
1031 name = namePrefix + comp.getName()
1032 for k, v in comp._properties.items():
1033 # Handle special cases of properties:
1034 # 1.PrivateToolHandles
1035 if isinstance(v, GaudiConfig2.Configurable):
1036 # Add the name of the tool as property to the parent
1037 bshPropsToSet.append((name, k, v.getFullJobOptName()))
1038 # Recursively add properties of this tool to the JobOptionSvc
1039 getCompsToBeAdded(v, namePrefix=name + ".")
1040 # 2. PrivateToolHandleArray
1041 elif isinstance(v, GaudiHandles.PrivateToolHandleArray):
1042 # Add names of tools as properties to the parent
1043 bshPropsToSet.append(
1044 (name, k, str([v1.getFullJobOptName() for v1 in v]),)
1046 # Recursively add properties of tools to JobOptionsSvc
1048 getCompsToBeAdded(v1, namePrefix=name + ".")
1050 # For a list of DataHandle, we need to stringify
1051 # each element individually. Otherwise, we get the repr
1052 # version of the elements, which Gaudi JO will choke on.
1053 if isinstance(v, list) and v and isinstance(v[0], DataHandle):
1054 v = [str(x) for x in v]
1055 # For sequences, need to convert the list of algs to names
1056 elif isSequence(comp) and k == "Members":
1057 v = [alg.getFullJobOptName() for alg in comp.Members]
1058 vstr = "" if v is None else str(v)
1059 bshPropsToSet.append((name, k, vstr))
1062 from AthenaPython import PyAthenaComps
1063 PyAlg = PyAthenaComps.Alg
1064 PySvc = PyAthenaComps.Svc
1070 for svc in self._services:
1071 if svc.getName() != "MessageSvc": # MessageSvc will exist already! Needs special treatment
1072 getCompsToBeAdded(svc)
1073 if isinstance(svc, PySvc):
1076 mspPropsToSet.update((k,str(v)) for k,v in svc._properties.items())
1078 # Algorithms and Sequences
1079 for alg in iterSequences(self._sequence):
1080 getCompsToBeAdded(alg)
1081 if isinstance(alg, PyAlg):
1086 for alg in self._conditionsAlgs:
1087 getCompsToBeAdded(alg)
1088 condalgseq.append(alg.getFullJobOptName())
1089 if isinstance(alg, PyAlg):
1091 bshPropsToSet.append(("AthCondSeq", "Members", str(condalgseq)))
1094 for pt in self._publicTools:
1095 getCompsToBeAdded(pt, namePrefix="ToolSvc.")
1098 for aud in self._auditors:
1099 getCompsToBeAdded(aud)
1101 return appPropsToSet, mspPropsToSet, bshPropsToSet
1103 def run(self,maxEvents=None):
1104 from os import environ
1105 outpklfile = environ.get("PICKLECAFILE", None)
1106 if outpklfile is not None:
1107 if outpklfile: # non-empty string
1108 self._msg.info("Storing configuration in pickle file %s",outpklfile)
1109 with open(outpklfile, "wb") as f:
1111 else: # empty string, just exit
1113 self._msg.info("Exiting after configuration stage")
1114 from Gaudi.Main import BootstrapHelper
1115 return BootstrapHelper.StatusCode(True)
1117 # Make sure python output is flushed before triggering output from Gaudi.
1118 # Otherwise, observed output ordering may differ between py2/py3.
1122 #Set TDAQ_ERS_NO_SIGNAL_HANDLERS to avoid interference with
1123 #TDAQ signal handling
1124 environ['TDAQ_ERS_NO_SIGNAL_HANDLERS']='1'
1125 from AthenaCommon.Debugging import allowPtrace, hookDebugger
1128 checkSequenceConsistency(self._sequence)
1130 app = self.createApp()
1131 self.__verifyFinalSequencesStructure()
1133 #Determine maxEvents
1134 if maxEvents is None:
1135 if "EvtMax" in self._theAppProps:
1136 maxEvents=self._theAppProps["EvtMax"]
1140 if self.interactive == 'init':
1141 printInteractiveMsg_init()
1142 from sys import exit # noqa: F401
1143 startInteractive(locals())
1145 #At this point, we don't need the internal structures of this CA any more, clean them up
1148 self._msg.info(f"Athena job with pid {os.getpid()}")
1150 if (self._debugStage.value == "init"):
1152 sc = app.initialize()
1153 if not sc.isSuccess():
1154 self._msg.error("Failed to initialize AppMgr")
1158 if not sc.isSuccess():
1159 self._msg.error("Failed to start AppMgr")
1162 if (self._debugStage.value=="exec"):
1166 if self.interactive == 'run':
1167 printInteractiveMsg_run()
1168 from AthenaPython.PyAthena import py_svc
1169 sg=py_svc("StoreGateSvc/StoreGateSvc")
1170 startInteractive(locals())
1172 sc = app.run(maxEvents)
1173 if not sc.isSuccess():
1174 self._msg.error("Failure running application")
1178 if not scStop.isSuccess():
1179 self._msg.error("Failed to stop AppMgr")
1182 if (self._debugStage.value == "fini"):
1185 scFin=app.finalize()
1186 if not scFin.isSuccess():
1187 self._msg.error("Failed to finalize AppMgr")
1190 sc1 = app.terminate()
1193 def foreach_component(self, path):
1194 """Utility to set properties of components using wildcards.
1197 ca.foreach_component("*/HLTTop/*/*Hypo*").OutputLevel = VERBOSE
1199 The components name and location in the CF tree are translated into a UNIX-like path
1200 and are matched using the `fnmatch` library. If the property is set successfully
1201 an INFO message is printed else a WARNING.
1203 The convention for paths of nested components is as follows:
1204 Sequence : only the name is used in the path
1205 Algorithm : "type/name" is used
1206 Private Tool : ToolHandle property name plus "type/name" is used
1207 Public Tool : located under "ToolSvc/" and "type/name" is used
1208 Service : located under "SvcMgr/" and "type/name" is used
1210 from AthenaConfiguration.PropSetterProxy import PropSetterProxy
1211 return PropSetterProxy(self, path)