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 # Create the Gaudi object early.
971 # Without this here, pyroot can sometimes get confused
972 # and report spurious type mismatch errors about this object.
974 ROOT.gROOT.SetBatch(True)
977 appPropsToSet, mspPropsToSet, bshPropsToSet = self.gatherProps()
979 self._wasMerged = True
980 from Gaudi.Main import BootstrapHelper
982 bsh = BootstrapHelper()
983 app = bsh.createApplicationMgr()
985 for k, v in appPropsToSet.items():
986 self._msg.debug("Setting property %s : %s", k, v)
987 app.setProperty(k, v)
991 msp = app.getService("MessageSvc")
992 for k, v in mspPropsToSet.items():
993 self._msg.debug("Setting property %s : %s", k, v)
994 bsh.setProperty(msp, k.encode(), v.encode())
996 # Feed the jobO service with the remaining options
997 for comp, name, value in bshPropsToSet:
998 self._msg.debug("Adding %s.%s = %s", comp, name, value)
999 app.setOption(f"{comp}.{name}", value)
1004 def gatherProps(self):
1005 appPropsToSet = {k: str(v) for k, v in self._theAppProps.items()}
1010 for svc in self._services:
1012 svc.getFullJobOptName(),
1014 if svc.getFullJobOptName() in self._servicesToCreate:
1015 svcToCreate.append(svc.getFullJobOptName())
1017 # order basic services
1018 for bs in reversed(_basicServicesToCreateOrder):
1019 if bs in svcToCreate:
1020 svcToCreate.insert(0, svcToCreate.pop( svcToCreate.index(bs) ) )
1022 extSvc.append("PyAthena::PyComponentMgr/PyComponentMgr")
1024 appPropsToSet["ExtSvc"] = str(extSvc)
1025 appPropsToSet["CreateSvc"] = str(svcToCreate)
1027 def getCompsToBeAdded(comp, namePrefix=""):
1028 name = namePrefix + comp.getName()
1029 for k, v in comp._properties.items():
1030 # Handle special cases of properties:
1031 # 1.PrivateToolHandles
1032 if isinstance(v, GaudiConfig2.Configurable):
1033 # Add the name of the tool as property to the parent
1034 bshPropsToSet.append((name, k, v.getFullJobOptName()))
1035 # Recursively add properties of this tool to the JobOptionSvc
1036 getCompsToBeAdded(v, namePrefix=name + ".")
1037 # 2. PrivateToolHandleArray
1038 elif isinstance(v, GaudiHandles.PrivateToolHandleArray):
1039 # Add names of tools as properties to the parent
1040 bshPropsToSet.append(
1041 (name, k, str([v1.getFullJobOptName() for v1 in v]),)
1043 # Recursively add properties of tools to JobOptionsSvc
1045 getCompsToBeAdded(v1, namePrefix=name + ".")
1047 # For a list of DataHandle, we need to stringify
1048 # each element individually. Otherwise, we get the repr
1049 # version of the elements, which Gaudi JO will choke on.
1050 if isinstance(v, list) and v and isinstance(v[0], DataHandle):
1051 v = [str(x) for x in v]
1052 # For sequences, need to convert the list of algs to names
1053 elif isSequence(comp) and k == "Members":
1054 v = [alg.getFullJobOptName() for alg in comp.Members]
1055 vstr = "" if v is None else str(v)
1056 bshPropsToSet.append((name, k, vstr))
1059 from AthenaPython import PyAthenaComps
1060 PyAlg = PyAthenaComps.Alg
1061 PySvc = PyAthenaComps.Svc
1067 for svc in self._services:
1068 if svc.getName() != "MessageSvc": # MessageSvc will exist already! Needs special treatment
1069 getCompsToBeAdded(svc)
1070 if isinstance(svc, PySvc):
1073 mspPropsToSet.update((k,str(v)) for k,v in svc._properties.items())
1075 # Algorithms and Sequences
1076 for alg in iterSequences(self._sequence):
1077 getCompsToBeAdded(alg)
1078 if isinstance(alg, PyAlg):
1083 for alg in self._conditionsAlgs:
1084 getCompsToBeAdded(alg)
1085 condalgseq.append(alg.getFullJobOptName())
1086 if isinstance(alg, PyAlg):
1088 bshPropsToSet.append(("AthCondSeq", "Members", str(condalgseq)))
1091 for pt in self._publicTools:
1092 getCompsToBeAdded(pt, namePrefix="ToolSvc.")
1095 for aud in self._auditors:
1096 getCompsToBeAdded(aud)
1098 return appPropsToSet, mspPropsToSet, bshPropsToSet
1100 def run(self,maxEvents=None):
1101 from os import environ
1102 outpklfile = environ.get("PICKLECAFILE", None)
1103 if outpklfile is not None:
1104 if outpklfile: # non-empty string
1105 self._msg.info("Storing configuration in pickle file %s",outpklfile)
1106 with open(outpklfile, "wb") as f:
1108 else: # empty string, just exit
1110 self._msg.info("Exiting after configuration stage")
1111 from Gaudi.Main import BootstrapHelper
1112 return BootstrapHelper.StatusCode(True)
1114 # Make sure python output is flushed before triggering output from Gaudi.
1115 # Otherwise, observed output ordering may differ between py2/py3.
1119 #Set TDAQ_ERS_NO_SIGNAL_HANDLERS to avoid interference with
1120 #TDAQ signal handling
1121 environ['TDAQ_ERS_NO_SIGNAL_HANDLERS']='1'
1122 from AthenaCommon.Debugging import allowPtrace, hookDebugger
1125 checkSequenceConsistency(self._sequence)
1127 app = self.createApp()
1128 self.__verifyFinalSequencesStructure()
1130 #Determine maxEvents
1131 if maxEvents is None:
1132 if "EvtMax" in self._theAppProps:
1133 maxEvents=self._theAppProps["EvtMax"]
1137 if self.interactive == 'init':
1138 printInteractiveMsg_init()
1139 from sys import exit # noqa: F401
1140 startInteractive(locals())
1142 #At this point, we don't need the internal structures of this CA any more, clean them up
1145 self._msg.info(f"Athena job with pid {os.getpid()}")
1147 if (self._debugStage.value == "init"):
1149 sc = app.initialize()
1150 if not sc.isSuccess():
1151 self._msg.error("Failed to initialize AppMgr")
1155 if not sc.isSuccess():
1156 self._msg.error("Failed to start AppMgr")
1159 if (self._debugStage.value=="exec"):
1163 if self.interactive == 'run':
1164 printInteractiveMsg_run()
1165 from AthenaPython.PyAthena import py_svc
1166 sg=py_svc("StoreGateSvc/StoreGateSvc")
1167 startInteractive(locals())
1169 sc = app.run(maxEvents)
1170 if not sc.isSuccess():
1171 self._msg.error("Failure running application")
1175 if not scStop.isSuccess():
1176 self._msg.error("Failed to stop AppMgr")
1179 if (self._debugStage.value == "fini"):
1182 scFin=app.finalize()
1183 if not scFin.isSuccess():
1184 self._msg.error("Failed to finalize AppMgr")
1187 sc1 = app.terminate()
1190 def foreach_component(self, path):
1191 """Utility to set properties of components using wildcards.
1194 ca.foreach_component("*/HLTTop/*/*Hypo*").OutputLevel = VERBOSE
1196 The components name and location in the CF tree are translated into a UNIX-like path
1197 and are matched using the `fnmatch` library. If the property is set successfully
1198 an INFO message is printed else a WARNING.
1200 The convention for paths of nested components is as follows:
1201 Sequence : only the name is used in the path
1202 Algorithm : "type/name" is used
1203 Private Tool : ToolHandle property name plus "type/name" is used
1204 Public Tool : located under "ToolSvc/" and "type/name" is used
1205 Service : located under "SvcMgr/" and "type/name" is used
1207 from AthenaConfiguration.PropSetterProxy import PropSetterProxy
1208 return PropSetterProxy(self, path)