ATLAS Offline Software
Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
python.ComponentAccumulator.ComponentAccumulator Class Reference
Inheritance diagram for python.ComponentAccumulator.ComponentAccumulator:
Collaboration diagram for python.ComponentAccumulator.ComponentAccumulator:

Public Member Functions

def __init__ (self, sequence='AthAlgSeq')
 
def setAsTopLevel (self)
 
def empty (self)
 
def __del__ (self)
 
def __getstate__ (self)
 
def __setstate__ (self, state)
 
def printCondAlgs (self, summariseProps=False, onlyComponents=[], printDefaults=False, printComponentsOnly=False)
 
def printConfig (self, withDetails=False, summariseProps=False, onlyComponents=[], printDefaults=False, printComponentsOnly=False, printSequenceTreeOnly=False, prefix=None)
 
def getIO (self)
 
def addSequence (self, newseq, primary=False, parentName=None)
 
def getSequence (self, sequenceName=None)
 
def setPrivateTools (self, privTool)
 
def popPrivateTools (self, quiet=False)
 
def popToolsAndMerge (self, other)
 
def getCurrentPerfmonDomain (self)
 
def flagPerfmonDomain (self, name)
 
def getInvertedPerfmonDomains (self)
 
def getAlgPerfmonDomain (self, name)
 
def addAlgToPerfmonDomains (self, name, domain, overwrite=False)
 
def printPerfmonDomains (self)
 
def addEventAlgo (self, algorithms, sequenceName=None, primary=False, domain=None)
 
def getEventAlgo (self, name=None)
 
def getEventAlgos (self, seqName=None)
 
def addCondAlgo (self, algo, primary=False, domain=None)
 
def getCondAlgos (self)
 
def getCondAlgo (self, name)
 
def addService (self, newSvc, primary=False, create=False)
 
def addAuditor (self, auditor)
 
def addPublicTool (self, newTool, primary=False)
 
def getPrimary (self)
 
def getPrimaryAndMerge (self, other)
 
def getPublicTools (self)
 
def getPublicTool (self, name=None)
 
def getServices (self)
 
def getService (self, name=None)
 
def getAuditor (self, name)
 
def dropEventAlgo (self, name, sequence="AthAlgSeq")
 
def popEventAlgo (self, name, sequence="AthAlgSeq")
 
def dropCondAlgo (self, name)
 
def dropService (self, name)
 
def dropPublicTool (self, name)
 
def dropAuditor (self, name)
 
def getAppProps (self)
 
def setAppProperty (self, key, value, overwrite=False)
 
def setDebugStage (self, stage)
 
def merge (self, other, sequenceName=None)
 
def wasMerged (self)
 
def store (self, outfile, withDefaultHandles=False)
 
def createApp (self)
 
def gatherProps (self)
 
def run (self, maxEvents=None)
 
def foreach_component (self, path)
 

Public Attributes

 interactive
 

Static Public Attributes

 debugMode
 

Private Member Functions

def _inspect (self)
 
def _cleanup (self)
 
def _cacheEvict (self)
 
def __getOne (self, allcomps, name=None, typename="???")
 
def __verifyFinalSequencesStructure (self)
 
def _allComponents (self)
 

Private Attributes

 _msg
 
 _sequence
 
 _allSequences
 
 _algorithms
 
 _conditionsAlgs
 
 _services
 
 _servicesToCreate
 
 _auditors
 
 _privateTools
 
 _primaryComp
 
 _currentDomain
 
 _domainsRegistry
 
 _theAppProps
 
 _publicTools
 
 _wasMerged
 
 _isMergable
 
 _lastAddedComponent
 
 _creationCallStack
 
 _componentsContext
 
 _debugStage
 

Static Private Attributes

 _checkUnmerged
 

Detailed Description

Definition at line 89 of file ComponentAccumulator.py.

Constructor & Destructor Documentation

◆ __init__()

def python.ComponentAccumulator.ComponentAccumulator.__init__ (   self,
  sequence = 'AthAlgSeq' 
)

Definition at line 96 of file ComponentAccumulator.py.

96  def __init__(self,sequence='AthAlgSeq'):
97  # Ensure that we are not operating in the legacy Athena Configurable mode
98  # where only a single global instance exists
100  raise ConfigurationError(
101  """
102  ComponentAccumulator initialised with legacy (global) Configurable behavior!
103  CA Deduplication is impossible in this mode.
104  Create the CA using the AthenaCommon.Configurable.ConfigurableCABehavior context manager.
105  """
106  )
107  self._msg=logging.getLogger('ComponentAccumulator')
108  if isinstance(sequence, str):
109  kwargs={'IgnoreFilterPassed' : True,
110  'StopOverride' : True }
111  if sequence == 'AthAlgSeq' :
112  kwargs.setdefault('ProcessDynamicDataDependencies',True)
113  kwargs.setdefault('ExtraDataForDynamicConsumers',[])
114 
115  # (Nested) default sequence of event processing algorithms per sequence + their private tools
116  sequence = CompFactory.AthSequencer(sequence, **kwargs)
117 
118  self._sequence = sequence
119  self._allSequences = [self._sequence]
120  self._algorithms = {} #Dictionary of algorithm instances keyed by name
121  self._conditionsAlgs = [] #Unordered list of conditions algorithms + their private tools
122  self._services = [] #List of service, not yet sure if the order matters here in the MT age
123  self._servicesToCreate = []
124  self._auditors = [] #List of auditors
125  self._privateTools = None #A placeholder to carry a private tool(s) not yet attached to its parent
126  self._primaryComp = None #A placeholder to designate the primary service
127  self._currentDomain = None #Currently marked PerfMon domain
128  self._domainsRegistry = {} #PerfMon domains registry
129 
130  self._theAppProps = dict() #Properties of the ApplicationMgr
131 
132  #Backward compatibility hack: Allow also public tools:
133  self._publicTools = []
134 
135  #To check if this accumulator was merged:
136  self._wasMerged = False
137  self._isMergable = True
138  self._lastAddedComponent = "Unknown"
139  self._creationCallStack = Context.hint if "trackCA" not in ComponentAccumulator.debugMode else shortCallStack()
140  self._componentsContext = dict()
141  self._debugStage = DbgStage()
142  self.interactive = ""
143 

◆ __del__()

def python.ComponentAccumulator.ComponentAccumulator.__del__ (   self)

Definition at line 187 of file ComponentAccumulator.py.

187  def __del__(self):
188  if self._checkUnmerged and not getattr(self,'_wasMerged',True) and not self.empty():
189  log = logging.getLogger("ComponentAccumulator")
190  log.error("ComponentAccumulator was never merged. %s\n", self._inspect())
191  import traceback
192  traceback.print_stack()
193  if getattr(self,'_privateTools',None) is not None:
194  log = logging.getLogger("ComponentAccumulator")
195  log.error("Deleting a ComponentAccumulator with dangling private tool(s): %s",
196  " ".join([t.name for t in self._privateTools]) if isinstance(self._privateTools, Sequence) else self._privateTools.name)
197 

Member Function Documentation

◆ __getOne()

def python.ComponentAccumulator.ComponentAccumulator.__getOne (   self,
  allcomps,
  name = None,
  typename = "???" 
)
private

Definition at line 670 of file ComponentAccumulator.py.

670  def __getOne(self, allcomps, name=None, typename="???"):
671  selcomps = allcomps if name is None else [ t for t in allcomps if t.name == name ]
672  if len( selcomps ) == 0:
673  raise ConfigurationError(f"Requested component of name {name} but is missing" )
674 
675  if len( selcomps ) == 1:
676  return selcomps[0]
677  nmstr = f'with name {name} ' if name else ''
678  raise ConfigurationError("Number of {} available {}{} which is != 1 expected by this API".format(typename, nmstr, len(selcomps)) )
679 

◆ __getstate__()

def python.ComponentAccumulator.ComponentAccumulator.__getstate__ (   self)

Definition at line 203 of file ComponentAccumulator.py.

203  def __getstate__(self):
204  state = self.__dict__.copy()
205  # Remove the unpicklable entries.
206  del state['_msg']
207  return state
208 

◆ __setstate__()

def python.ComponentAccumulator.ComponentAccumulator.__setstate__ (   self,
  state 
)

Definition at line 209 of file ComponentAccumulator.py.

209  def __setstate__(self,state):
210  self.__dict__.update(state)
211  #Re-enstate logger
212  self._msg=logging.getLogger('ComponentAccumulator')
213 
214 

◆ __verifyFinalSequencesStructure()

def python.ComponentAccumulator.ComponentAccumulator.__verifyFinalSequencesStructure (   self)
private

Definition at line 944 of file ComponentAccumulator.py.

944  def __verifyFinalSequencesStructure(self):
945  if len(self._allSequences) != 1:
946  raiseWithCurrentContext(ConfigurationError('It is not allowed for the storable CA to have more than one top sequence, now it has: {}'
947  .format(','.join([ s.name for s in self._allSequences]))))
948 
949 

◆ _allComponents()

def python.ComponentAccumulator.ComponentAccumulator._allComponents (   self)
private
returns iterable over all components 

Definition at line 957 of file ComponentAccumulator.py.

957  def _allComponents(self):
958  """ returns iterable over all components """
959  import itertools
960  return itertools.chain(self._publicTools,
961  self._privateTools if self._privateTools else [],
962  self._algorithms.values(),
963  self._conditionsAlgs)
964 
965 

◆ _cacheEvict()

def python.ComponentAccumulator.ComponentAccumulator._cacheEvict (   self)
private
Called by AccumulatorCache when deleting item from cache

Definition at line 198 of file ComponentAccumulator.py.

198  def _cacheEvict(self):
199  """Called by AccumulatorCache when deleting item from cache"""
200  self.popPrivateTools(quiet=True)
201  self.wasMerged()
202 

◆ _cleanup()

def python.ComponentAccumulator.ComponentAccumulator._cleanup (   self)
private

Definition at line 165 of file ComponentAccumulator.py.

165  def _cleanup(self):
166  # Delete internal data structures, to be called after all properties are transferred to the C++ application
167  del self._sequence
168  del self._allSequences
169  del self._algorithms
170  del self._conditionsAlgs
171  del self._services
172  del self._publicTools
173  del self._auditors
174 
175  # Clear all AccumulatorCaches
176  from AthenaConfiguration.AccumulatorCache import AccumulatorDecorator
177  AccumulatorDecorator.clearCache()
178 
179  # Run garbage collector
180  import gc
181  gc.collect()
182 

◆ _inspect()

def python.ComponentAccumulator.ComponentAccumulator._inspect (   self)
private

Definition at line 147 of file ComponentAccumulator.py.

147  def _inspect(self): #Create a string some basic info about this CA, useful for debugging
148  summary = "This CA contains {0} service(s), {1} conditions algorithm(s), {2} event algorithm(s) and {3} public tool(s):\n"\
149  .format(len(self._services),len(self._conditionsAlgs),len(self._algorithms),len(self._publicTools))
150 
151  if self._privateTools:
152  if isinstance(self._privateTools, list):
153  summary += " Private AlgTool: " + self._privateTools[-1].getFullJobOptName() + "\n"
154  else:
155  summary += " Private AlgTool: " + self._privateTools.getFullJobOptName() + "\n"
156 
157  if self._primaryComp:
158  summary += " Primary Component: " + self._primaryComp.getFullJobOptName() + "\n"
159 
160  summary += " Sequence(s): " + ", ".join([s.name+(" (main)" if s == self._sequence else "") for s in self._allSequences]) + "\n"
161  summary += " Last component added: " + self._lastAddedComponent+"\n"
162  summary += " Created by: " + self._creationCallStack
163  return summary
164 

◆ addAlgToPerfmonDomains()

def python.ComponentAccumulator.ComponentAccumulator.addAlgToPerfmonDomains (   self,
  name,
  domain,
  overwrite = False 
)
Add the algorithm to the domains registry. 

Definition at line 452 of file ComponentAccumulator.py.

452  def addAlgToPerfmonDomains(self, name, domain, overwrite=False):
453  """ Add the algorithm to the domains registry. """
454  if name not in self._domainsRegistry:
455  if domain:
456  self._domainsRegistry[name] = domain
457  self._msg.debug(f"Added algorithm {name} to the PerfMon domain {domain}")
458  else:
459  if overwrite and domain:
460  self._msg.info(f"Reassigned algorithm {name} "
461  f"from {self._domainsRegistry[name]} "
462  f"to {domain} PerfMon domain")
463  self._domainsRegistry[name] = domain
464  else:
465  self._msg.debug(f"Algorithm {name} is already in the PerfMon "
466  "domain, if you want to reassign do overwrite=True")
467 

◆ addAuditor()

def python.ComponentAccumulator.ComponentAccumulator.addAuditor (   self,
  auditor 
)
Add Auditor to ComponentAccumulator and return the deduplicated instance.
This function will also create the required AuditorSvc.

Definition at line 611 of file ComponentAccumulator.py.

611  def addAuditor(self, auditor):
612  """Add Auditor to ComponentAccumulator and return the deduplicated instance.
613  This function will also create the required AuditorSvc."""
614  if not isinstance(auditor, GaudiConfig2.Configurable):
615  raise TypeError(f"Attempt to add wrong type: {type(auditor).__name__} as auditor")
616 
617  if auditor.__component_type__ != "Auditor":
618  raise TypeError(f"Attempt to add wrong type: {auditor.__component_type__} as auditor")
619 
620  context = createContextForDeduplication("Merging with existing auditors", auditor.name, self._componentsContext) # noqa : F841
621 
622  deduplicate(auditor, self._auditors) #may raise on conflict
623  newAuditor = self.addService(CompFactory.AuditorSvc(Auditors=[auditor.getFullJobOptName()]))
624  self._lastAddedComponent = auditor.name
625  return newAuditor
626 
627 

◆ addCondAlgo()

def python.ComponentAccumulator.ComponentAccumulator.addCondAlgo (   self,
  algo,
  primary = False,
  domain = None 
)
Add Conditions algorithm

Definition at line 546 of file ComponentAccumulator.py.

546  def addCondAlgo(self,algo,primary=False,domain=None):
547  """Add Conditions algorithm"""
548  if not isinstance(algo, GaudiConfig2.Configurable):
549  raise TypeError(f"Attempt to add wrong type: {type(algo).__name__} as conditions algorithm")
550 
551  if algo.__component_type__ != "Algorithm":
552  raise TypeError(f"Attempt to add wrong type: {algo.__component_type__} as conditions algorithm")
553 
554  context = createContextForDeduplication("Merging with existing Conditions Algorithm", algo.name, self._componentsContext) # noqa : F841
555 
556  deduplicate(algo, self._conditionsAlgs) #will raise on conflict
557  if primary:
558  if self._primaryComp:
559  self._msg.warning("addCondAlgo: Overwriting primary component of this CA. Was %s/%s, now %s/%s",
560  self._primaryComp.__cpp_type__, self._primaryComp.name,
561  algo.__cpp_type__, algo.name)
562  #keep a ref of the de-duplicated conditions algorithm as primary component
563  self._primaryComp = self.__getOne(self._conditionsAlgs, algo.name, "ConditionsAlgos")
564 
565  self._lastAddedComponent=algo.name
566  if "trackCondAlgo" in ComponentAccumulator.debugMode:
567  self._componentsContext[algo.name] = shortCallStack()
568 
569  # Assign the algorithm to a domain
570  self.addAlgToPerfmonDomains(algo.name, 'Conditions' if not domain else domain)
571 
572  return algo
573 

◆ addEventAlgo()

def python.ComponentAccumulator.ComponentAccumulator.addEventAlgo (   self,
  algorithms,
  sequenceName = None,
  primary = False,
  domain = None 
)

Definition at line 480 of file ComponentAccumulator.py.

480  def addEventAlgo(self, algorithms,sequenceName=None,primary=False,domain=None):
481  if not isinstance(algorithms, Sequence):
482  #Swallow both single algorithms as well as lists or tuples of algorithms
483  algorithms=[algorithms,]
484 
485  if sequenceName is None:
486  # If there is an AthAlgSeq add the event algorithm there by default
487  # See ATEAM-825 for a more detailed discussion for this choice
488  seq = findSubSequence(self._sequence, 'AthAlgSeq')
489  if seq is None:
490  seq = self._sequence
491  else:
492  seq = findSubSequence(self._sequence, sequenceName)
493  if seq is None:
494  self.printConfig()
495  raise ConfigurationError("Can not find sequence {}".format(sequenceName))
496 
497  for algo in algorithms:
498  if not isinstance(algo, GaudiConfig2.Configurable):
499  raise TypeError(f"Attempt to add wrong type: {type(algo).__name__} as event algorithm")
500 
501  if algo.__component_type__ != "Algorithm":
502  raise TypeError(f"Attempt to add an {algo.__component_type__} as event algorithm")
503 
504  if algo.name in self._algorithms:
505  context = createContextForDeduplication("Merging with existing Event Algorithm", algo.name, self._componentsContext) # noqa : F841
506  deduplicateOne(algo, self._algorithms[algo.name])
507  deduplicateOne(self._algorithms[algo.name], algo)
508  else:
509  self._algorithms[algo.name]=algo
510 
511  existingAlgInDest = findAlgorithm(seq, algo.name)
512  if not existingAlgInDest:
513  seq.Members.append(self._algorithms[algo.name])
514  # Assign the algorithm to a domain
515  self.addAlgToPerfmonDomains(algo.name, self._currentDomain if not domain else domain)
516 
517  if primary:
518  if len(algorithms)>1:
519  self._msg.warning("Called addEvenAlgo with a list of algorithms and primary==True. "
520  "Designating the first algorithm as primary component")
521  if self._primaryComp:
522  self._msg.warning("addEventAlgo: Overwriting primary component of this CA. Was %s/%s, now %s/%s",
523  self._primaryComp.__cpp_type__, self._primaryComp.name,
524  algorithms[0].__cpp_type__, algorithms[0].name)
525  #keep a ref of the algorithm as primary component
526  self._primaryComp = algorithms[0]
527  self._lastAddedComponent = algorithms[-1].name
528 
529  if "trackEventAlgo" in ComponentAccumulator.debugMode:
530  for algo in algorithms:
531  self._componentsContext[algo.name] = shortCallStack()
532 
533  return None
534 

◆ addPublicTool()

def python.ComponentAccumulator.ComponentAccumulator.addPublicTool (   self,
  newTool,
  primary = False 
)
Add public tool and return the deduplicated instance.

Definition at line 628 of file ComponentAccumulator.py.

628  def addPublicTool(self, newTool, primary=False):
629  """Add public tool and return the deduplicated instance."""
630  if not isinstance(newTool, GaudiConfig2.Configurable):
631  raise TypeError(f"Attempt to add wrong type: {type(newTool).__name__} as public AlgTool")
632 
633  if newTool.__component_type__ != "AlgTool":
634  raise TypeError(f"Attempt to add wrong type: {newTool.__component_type__} as public AlgTool")
635 
636  context = createContextForDeduplication("Merging with existing Public Tool", newTool.name, self._componentsContext) # noqa : F841
637 
638  deduplicate(newTool,self._publicTools)
639  if primary:
640  if self._primaryComp:
641  self._msg.warning("addPublicTool: Overwriting primary component of this CA. Was %s/%s, now %s/%s",
642  self._primaryComp.__cpp_type__, self._primaryComp.name,
643  newTool.__cpp_type__, newTool.name)
644  #keep a ref of the de-duplicated tool as primary component
645  self._primaryComp=self.__getOne( self._publicTools, newTool.name, "Public Tool")
646  self._lastAddedComponent=newTool.name
647  if "trackPublicTool" in ComponentAccumulator.debugMode:
648  self._componentsContext[newTool.name] = shortCallStack()
649  # return the new public tool
650  return self.__getOne(self._publicTools, newTool.name, "Public Tool")
651 
652 

◆ addSequence()

def python.ComponentAccumulator.ComponentAccumulator.addSequence (   self,
  newseq,
  primary = False,
  parentName = None 
)
Adds new sequence. If second argument is present then it is added under another sequence  

Definition at line 338 of file ComponentAccumulator.py.

338  def addSequence(self, newseq, primary=False, parentName = None ):
339  """ Adds new sequence. If second argument is present then it is added under another sequence """
340 
341  if not isSequence(newseq):
342  raise TypeError('{} is not a sequence'.format(newseq.name))
343 
344  if not isinstance(newseq, GaudiConfig2.Configurable):
345  raise ConfigurationError('{} is not the Conf2 Sequence, ComponentAccumulator handles only the former'.format(newseq.name))
346 
347  algorithmsInside = findAllAlgorithmsByName(newseq)
348  if len(algorithmsInside) != 0:
349  raise ConfigurationError('{} contains algorithms (or sub-sequences contain them). That is not supported. Construct ComponentAccumulator and merge it instead'.format(newseq.name))
350 
351 
352  if parentName is None:
353  parent=self._sequence
354  else:
355  parent = findSubSequence(self._sequence, parentName )
356  if parent is None:
357  raise ConfigurationError("Missing sequence {} to add new sequence to".format(parentName))
358 
359  parent.Members.append(newseq)
360  if "trackSequence" in ComponentAccumulator.debugMode:
361  self._componentsContext[newseq] = shortCallStack()
362 
363  if primary:
364  if self._primaryComp:
365  self._msg.warning("addEventAlgo: Overwriting primary component of this CA. Was %s/%s, now %s/%s",
366  self._primaryComp.__cpp_type__, self._primaryComp.name,
367  newseq.__cpp_type__, newseq.name)
368  #keep a ref of the sequence as primary component
369  self._primaryComp = newseq
370  return newseq
371 
372 

◆ addService()

def python.ComponentAccumulator.ComponentAccumulator.addService (   self,
  newSvc,
  primary = False,
  create = False 
)
Add service and return the deduplicated instance

Definition at line 582 of file ComponentAccumulator.py.

582  def addService(self, newSvc, primary=False, create=False):
583  """Add service and return the deduplicated instance"""
584  if not isinstance(newSvc, GaudiConfig2.Configurable):
585  raise TypeError(f"Attempt to add wrong type: {type(newSvc).__name__} as service")
586 
587  if newSvc.__component_type__ != "Service":
588  raise TypeError(f"Attempt to add wrong type: {newSvc.__component_type__} as service")
589 
590  context = createContextForDeduplication("Merging with existing Service", newSvc.name, self._componentsContext) # noqa : F841
591 
592  deduplicate(newSvc, self._services) #may raise on conflict
593  if primary:
594  if self._primaryComp:
595  self._msg.warning("addService: Overwriting primary component of this CA. Was %s/%s, now %s/%s",
596  self._primaryComp.__cpp_type__, self._primaryComp.name,
597  newSvc.__cpp_type__, newSvc.name)
598  #keep a ref of the de-duplicated service as primary component
599  self._primaryComp=self.__getOne( self._services, newSvc.name, "Services")
600  self._lastAddedComponent=newSvc.name
601 
602  if create:
603  sname = newSvc.getFullJobOptName()
604  if sname not in self._servicesToCreate:
605  self._servicesToCreate.append(sname)
606  if "trackService" in ComponentAccumulator.debugMode:
607  self._componentsContext[newSvc.name] = shortCallStack()
608  return self.__getOne( self._services, newSvc.name, "Services")
609 
610 

◆ createApp()

def python.ComponentAccumulator.ComponentAccumulator.createApp (   self)

Definition at line 985 of file ComponentAccumulator.py.

985  def createApp(self):
986  # Create the Gaudi object early.
987  # Without this here, pyroot can sometimes get confused
988  # and report spurious type mismatch errors about this object.
989  import ROOT
990  ROOT.gROOT.SetBatch(True)
991  ROOT.Gaudi
992 
993  appPropsToSet, mspPropsToSet, bshPropsToSet = self.gatherProps()
994 
995  self._wasMerged = True
996  from Gaudi.Main import BootstrapHelper
997 
998  bsh = BootstrapHelper()
999  app = bsh.createApplicationMgr()
1000 
1001  for k, v in appPropsToSet.items():
1002  self._msg.debug("Setting property %s : %s", k, v)
1003  app.setProperty(k, v)
1004 
1005  app.configure()
1006 
1007  msp = app.getService("MessageSvc")
1008  for k, v in mspPropsToSet.items():
1009  self._msg.debug("Setting property %s : %s", k, v)
1010  bsh.setProperty(msp, k.encode(), v.encode())
1011 
1012  # Feed the jobO service with the remaining options
1013  for comp, name, value in bshPropsToSet:
1014  self._msg.debug("Adding %s.%s = %s", comp, name, value)
1015  app.setOption(f"{comp}.{name}", value)
1016 
1017  sys.stdout.flush()
1018  return app
1019 

◆ dropAuditor()

def python.ComponentAccumulator.ComponentAccumulator.dropAuditor (   self,
  name 
)

Definition at line 761 of file ComponentAccumulator.py.

761  def dropAuditor(self,name):
762  lenBefore=len(self._auditors)
763  self._auditors = [a for a in self._auditors if a.getName()!=name]
764  lenAfter=len(self._auditors)
765  if lenAfter == lenBefore:
766  self._msg.warning("Auditor %s not found",name)
767  else:
768  self._msg.info("Removed auditor %s",name)
769  return
770 

◆ dropCondAlgo()

def python.ComponentAccumulator.ComponentAccumulator.dropCondAlgo (   self,
  name 
)

Definition at line 731 of file ComponentAccumulator.py.

731  def dropCondAlgo(self,name):
732  lenBefore=len(self._conditionsAlgs)
733  self._conditionsAlgs = [a for a in self._conditionsAlgs if a.getName()!=name]
734  lenAfter=len(self._conditionsAlgs)
735  if lenAfter == lenBefore:
736  self._msg.warning("Condition Algorithm %s not found",name)
737  else:
738  self._msg.info("Removed conditions Algorithm %s",name)
739  return
740 

◆ dropEventAlgo()

def python.ComponentAccumulator.ComponentAccumulator.dropEventAlgo (   self,
  name,
  sequence = "AthAlgSeq" 
)

Definition at line 701 of file ComponentAccumulator.py.

701  def dropEventAlgo(self,name,sequence="AthAlgSeq"):
702  s=self.getSequence(sequence)
703  lenBefore=len(s.Members)
704  s.Members = [a for a in s.Members if not a.getName()==name]
705  lenAfter=len(s.Members)
706  if lenAfter == lenBefore:
707  self._msg.warning("Algorithm %s not found in sequence %s",name,sequence)
708  else:
709  self._msg.info("Removed algorithm %s from sequence %s",name,sequence)
710  try:
711  del self._algorithms[name]
712  except KeyError:
713  self._msg.warning("Algorithm %s not found in self._sequence ???",name)
714  return
715 

◆ dropPublicTool()

def python.ComponentAccumulator.ComponentAccumulator.dropPublicTool (   self,
  name 
)

Definition at line 751 of file ComponentAccumulator.py.

751  def dropPublicTool(self,name):
752  lenBefore=len(self._publicTools)
753  self._publicTools = [p for p in self._publicTools if p.getName()!=name]
754  lenAfter=len(self._publicTools)
755  if lenAfter == lenBefore:
756  self._msg.warning("Public tool %s not found",name)
757  else:
758  self._msg.info("Removed public tool %s",name)
759  return
760 

◆ dropService()

def python.ComponentAccumulator.ComponentAccumulator.dropService (   self,
  name 
)

Definition at line 741 of file ComponentAccumulator.py.

741  def dropService(self,name):
742  lenBefore=len(self._services)
743  self._services = [s for s in self._services if s.getName()!=name]
744  lenAfter=len(self._services)
745  if lenAfter == lenBefore:
746  self._msg.warning("Service %s not found",name)
747  else:
748  self._msg.info("Removed Service %s",name)
749  return
750 

◆ empty()

def python.ComponentAccumulator.ComponentAccumulator.empty (   self)

Definition at line 183 of file ComponentAccumulator.py.

183  def empty(self):
184  return (len(self._sequence.Members)+len(self._conditionsAlgs)+len(self._services)+
185  len(self._publicTools)+len(self._theAppProps) == 0)
186 

◆ flagPerfmonDomain()

def python.ComponentAccumulator.ComponentAccumulator.flagPerfmonDomain (   self,
  name 
)
Mark the beginning of a new PerfMon domain. 

Definition at line 430 of file ComponentAccumulator.py.

430  def flagPerfmonDomain(self, name):
431  """ Mark the beginning of a new PerfMon domain. """
432  self._msg.debug(f"Toggling the current algorithm domain to {name}")
433  self._currentDomain = name
434 

◆ foreach_component()

def python.ComponentAccumulator.ComponentAccumulator.foreach_component (   self,
  path 
)
Utility to set properties of components using wildcards

Example:
forcomps(ca, "*/HLTTop/*/*Hypo*").OutputLevel=VERBOSE

The components name & locations in the CF tree are translated into the unix like path.
Components of matching path are taken under consideration in setting the property.
If the property is set successfully an INFO message is printed. Else, a warning is printed.

The convention for path of nested components is as follows:
Sequencer - only the name is used in the path
Algorithm - full name - type/instance_name (aka full name) is used
PrivateTools - the name of the property + the type/instance_name are added
PublicTools - are located under ToolSvc/ and type/instance_name is used
Services - located under SvcMgr/ and type/instance_name is used

Definition at line 1199 of file ComponentAccumulator.py.

1199  def foreach_component(self, path):
1200  """ Utility to set properties of components using wildcards
1201 
1202  Example:
1203  forcomps(ca, "*/HLTTop/*/*Hypo*").OutputLevel=VERBOSE
1204 
1205  The components name & locations in the CF tree are translated into the unix like path.
1206  Components of matching path are taken under consideration in setting the property.
1207  If the property is set successfully an INFO message is printed. Else, a warning is printed.
1208 
1209  The convention for path of nested components is as follows:
1210  Sequencer - only the name is used in the path
1211  Algorithm - full name - type/instance_name (aka full name) is used
1212  PrivateTools - the name of the property + the type/instance_name are added
1213  PublicTools - are located under ToolSvc/ and type/instance_name is used
1214  Services - located under SvcMgr/ and type/instance_name is used
1215  """
1216  from AthenaConfiguration.PropSetterProxy import PropSetterProxy
1217  return PropSetterProxy(self, path)
1218 
1219 

◆ gatherProps()

def python.ComponentAccumulator.ComponentAccumulator.gatherProps (   self)

Definition at line 1020 of file ComponentAccumulator.py.

1020  def gatherProps(self):
1021  appPropsToSet = {k: str(v) for k, v in self._theAppProps.items()}
1022  mspPropsToSet = {}
1023  bshPropsToSet = []
1024  svcToCreate = []
1025  extSvc = []
1026  for svc in self._services:
1027  extSvc += [
1028  svc.getFullJobOptName(),
1029  ]
1030  if svc.getFullJobOptName() in self._servicesToCreate:
1031  svcToCreate.append(svc.getFullJobOptName())
1032 
1033  # order basic services
1034  for bs in reversed(_basicServicesToCreateOrder):
1035  if bs in svcToCreate:
1036  svcToCreate.insert(0, svcToCreate.pop( svcToCreate.index(bs) ) )
1037 
1038  extSvc.append("PyAthena::PyComponentMgr/PyComponentMgr")
1039 
1040  appPropsToSet["ExtSvc"] = str(extSvc)
1041  appPropsToSet["CreateSvc"] = str(svcToCreate)
1042 
1043  def getCompsToBeAdded(comp, namePrefix=""):
1044  name = namePrefix + comp.getName()
1045  for k, v in comp._properties.items():
1046  # Handle special cases of properties:
1047  # 1.PrivateToolHandles
1048  if isinstance(v, GaudiConfig2.Configurable):
1049  # Add the name of the tool as property to the parent
1050  bshPropsToSet.append((name, k, v.getFullJobOptName()))
1051  # Recursively add properties of this tool to the JobOptionSvc
1052  getCompsToBeAdded(v, namePrefix=name + ".")
1053  # 2. PrivateToolHandleArray
1054  elif isinstance(v, GaudiHandles.PrivateToolHandleArray):
1055  # Add names of tools as properties to the parent
1056  bshPropsToSet.append(
1057  (name, k, str([v1.getFullJobOptName() for v1 in v]),)
1058  )
1059  # Recursively add properties of tools to JobOptionsSvc
1060  for v1 in v:
1061  getCompsToBeAdded(v1, namePrefix=name + ".")
1062  else:
1063  # For a list of DataHandle, we need to stringify
1064  # each element individually. Otherwise, we get the repr
1065  # version of the elements, which Gaudi JO will choke on.
1066  if isinstance(v, list) and v and isinstance(v[0], DataHandle):
1067  v = [str(x) for x in v]
1068  # For sequences, need to convert the list of algs to names
1069  elif isSequence(comp) and k == "Members":
1070  v = [alg.getFullJobOptName() for alg in comp.Members]
1071  vstr = "" if v is None else str(v)
1072  bshPropsToSet.append((name, k, vstr))
1073 
1074  try:
1075  from AthenaPython import PyAthenaComps
1076  PyAlg = PyAthenaComps.Alg
1077  PySvc = PyAthenaComps.Svc
1078  except ImportError:
1079  PyAlg = type(None)
1080  PySvc = type(None)
1081 
1082  # Services
1083  for svc in self._services:
1084  if svc.getName() != "MessageSvc": # MessageSvc will exist already! Needs special treatment
1085  getCompsToBeAdded(svc)
1086  if isinstance(svc, PySvc):
1087  svc.setup()
1088  else:
1089  mspPropsToSet.update((k,str(v)) for k,v in svc._properties.items())
1090 
1091  # Algorithms and Sequences
1092  for alg in iterSequences(self._sequence):
1093  getCompsToBeAdded(alg)
1094  if isinstance(alg, PyAlg):
1095  alg.setup()
1096 
1097  # Cond Algs
1098  condalgseq = []
1099  for alg in self._conditionsAlgs:
1100  getCompsToBeAdded(alg)
1101  condalgseq.append(alg.getFullJobOptName())
1102  if isinstance(alg, PyAlg):
1103  alg.setup()
1104  bshPropsToSet.append(("AthCondSeq", "Members", str(condalgseq)))
1105 
1106  # Public Tools
1107  for pt in self._publicTools:
1108  getCompsToBeAdded(pt, namePrefix="ToolSvc.")
1109 
1110  # Auditors
1111  for aud in self._auditors:
1112  getCompsToBeAdded(aud)
1113 
1114  return appPropsToSet, mspPropsToSet, bshPropsToSet
1115 

◆ getAlgPerfmonDomain()

def python.ComponentAccumulator.ComponentAccumulator.getAlgPerfmonDomain (   self,
  name 
)
Return the PerfMon domain of the given algorithm 

Definition at line 444 of file ComponentAccumulator.py.

444  def getAlgPerfmonDomain(self, name):
445  """ Return the PerfMon domain of the given algorithm """
446  if name in self._domainsRegistry:
447  return self._domainsRegistry[name]
448  else:
449  self._msg.info(f"Algorithm {name} is not in PerfMon domains registry")
450  return None
451 

◆ getAppProps()

def python.ComponentAccumulator.ComponentAccumulator.getAppProps (   self)

Definition at line 771 of file ComponentAccumulator.py.

771  def getAppProps(self):
772  return self._theAppProps
773 

◆ getAuditor()

def python.ComponentAccumulator.ComponentAccumulator.getAuditor (   self,
  name 
)
Retuns a single auditor, exception if not found

Definition at line 697 of file ComponentAccumulator.py.

697  def getAuditor(self,name):
698  """Retuns a single auditor, exception if not found"""
699  return self.__getOne(self._auditors,name,"Auditors")
700 

◆ getCondAlgo()

def python.ComponentAccumulator.ComponentAccumulator.getCondAlgo (   self,
  name 
)
Get conditions algorithm by name

Definition at line 578 of file ComponentAccumulator.py.

578  def getCondAlgo(self, name):
579  """Get conditions algorithm by name"""
580  return self.__getOne( self._conditionsAlgs, name, "conditions algorithms")
581 

◆ getCondAlgos()

def python.ComponentAccumulator.ComponentAccumulator.getCondAlgos (   self)
Get all conditions algorithms

Definition at line 574 of file ComponentAccumulator.py.

574  def getCondAlgos(self):
575  """Get all conditions algorithms"""
576  return self._conditionsAlgs
577 

◆ getCurrentPerfmonDomain()

def python.ComponentAccumulator.ComponentAccumulator.getCurrentPerfmonDomain (   self)
Get the current PerfMon domain. 

Definition at line 426 of file ComponentAccumulator.py.

426  def getCurrentPerfmonDomain(self):
427  """ Get the current PerfMon domain. """
428  return self._currentDomain
429 

◆ getEventAlgo()

def python.ComponentAccumulator.ComponentAccumulator.getEventAlgo (   self,
  name = None 
)
Get algorithm with `name`

Definition at line 535 of file ComponentAccumulator.py.

535  def getEventAlgo(self, name=None):
536  """Get algorithm with `name`"""
537  if name not in self._algorithms:
538  raise ConfigurationError("Can not find an algorithm of name {} ".format(name))
539  return self._algorithms[name]
540 

◆ getEventAlgos()

def python.ComponentAccumulator.ComponentAccumulator.getEventAlgos (   self,
  seqName = None 
)
Get all algorithms within sequence

Definition at line 541 of file ComponentAccumulator.py.

541  def getEventAlgos(self, seqName=None):
542  """Get all algorithms within sequence"""
543  seq = self._sequence if seqName is None else findSubSequence(self._sequence, seqName )
544  return [s for s in iterSequences(seq) if not isSequence(s)]
545 

◆ getInvertedPerfmonDomains()

def python.ComponentAccumulator.ComponentAccumulator.getInvertedPerfmonDomains (   self)
The actual registry keeps "alg":"domain".
This function inverts the registry to get "domain":["algs"].

Definition at line 435 of file ComponentAccumulator.py.

435  def getInvertedPerfmonDomains(self):
436  """ The actual registry keeps "alg":"domain".
437  This function inverts the registry to get "domain":["algs"].
438  """
439  result = {}
440  for i, v in self._domainsRegistry.items():
441  result[v] = [i] if v not in result.keys() else result[v] + [i]
442  return result
443 

◆ getIO()

def python.ComponentAccumulator.ComponentAccumulator.getIO (   self)
Returns information about inputs needed and outputs produced by this CA

It is a list of dictionaries containing the: type, key, R / W, the component and name of the property via which it is set

Definition at line 296 of file ComponentAccumulator.py.

296  def getIO(self):
297  """
298  Returns information about inputs needed and outputs produced by this CA
299 
300  It is a list of dictionaries containing the: type, key, R / W, the component and name of the property via which it is set
301  """
302  def __getHandles(comp):
303  io = []
304  for i in comp.ExtraInputs:
305  io.append({"type": i.split("#")[0],
306  "key": i.split("#")[1],
307  "comp": comp.getFullJobOptName(),
308  "mode": "R",
309  "prop": "ExtraInputs"})
310  for i in comp.ExtraOutputs:
311  io.append({"type": i.split("#")[0],
312  "key": i.split("#")[1],
313  "comp": comp.getFullJobOptName(),
314  "mode": "W",
315  "prop": "ExtraOutputs"})
316 
317  for prop, descr in comp._descriptors.items():
318  if isinstance(descr.default, DataHandle):
319  io.append( {"type": descr.default.type(),
320  "key": comp._properties[prop] if prop in comp._properties else descr.default.path(),
321  "comp": comp.getFullJobOptName(),
322  "mode": descr.default.mode(),
323  "prop": prop })
324  # TODO we should consider instantiating c++ defaults and fetching corresponsing props
325  if "PrivateToolHandle" == descr.cpp_type and prop in comp._properties:
326  io.extend( __getHandles(comp._properties[prop]) )
327  if "PrivateToolHandleArray" == descr.cpp_type and prop in comp._properties:
328  for tool in getattr(comp, prop):
329  io.extend( __getHandles(tool))
330  return io
331 
332  ret = []
333  for comp in self._allComponents():
334  ret.extend(__getHandles(comp))
335  return ret
336 
337 

◆ getPrimary()

def python.ComponentAccumulator.ComponentAccumulator.getPrimary (   self)
Get designated primary component

Definition at line 653 of file ComponentAccumulator.py.

653  def getPrimary(self):
654  """Get designated primary component"""
655  if self._privateTools:
656  return self.popPrivateTools()
657  elif self._primaryComp:
658  return self._primaryComp
659  else:
660  raise ConfigurationError("Called getPrimary() but no primary component nor private AlgTool is known.\n{}".format(self._inspect()))
661 

◆ getPrimaryAndMerge()

def python.ComponentAccumulator.ComponentAccumulator.getPrimaryAndMerge (   self,
  other 
)
Merging in the other accumulator and getting the primary component

Definition at line 662 of file ComponentAccumulator.py.

662  def getPrimaryAndMerge(self, other):
663  """ Merging in the other accumulator and getting the primary component"""
664  if other is None:
665  raise RuntimeError("merge called on object of type None: did you forget to return a CA from a config function?")
666  comp = other.getPrimary()
667  self.merge(other)
668  return comp
669 

◆ getPublicTool()

def python.ComponentAccumulator.ComponentAccumulator.getPublicTool (   self,
  name = None 
)
Returns single public tool, exception if either not found or to many found

Definition at line 683 of file ComponentAccumulator.py.

683  def getPublicTool(self, name=None):
684  """Returns single public tool, exception if either not found or to many found"""
685  return self.__getOne( self._publicTools, name, "PublicTools")
686 

◆ getPublicTools()

def python.ComponentAccumulator.ComponentAccumulator.getPublicTools (   self)

Definition at line 680 of file ComponentAccumulator.py.

680  def getPublicTools(self):
681  return self._publicTools
682 

◆ getSequence()

def python.ComponentAccumulator.ComponentAccumulator.getSequence (   self,
  sequenceName = None 
)

Definition at line 373 of file ComponentAccumulator.py.

373  def getSequence(self,sequenceName=None):
374  if sequenceName is None:
375  return self._sequence
376  else:
377  return findSubSequence(self._sequence,sequenceName)
378 

◆ getService()

def python.ComponentAccumulator.ComponentAccumulator.getService (   self,
  name = None 
)
Returns single service, exception if either not found or to many found

Definition at line 690 of file ComponentAccumulator.py.

690  def getService(self, name=None):
691  """Returns single service, exception if either not found or to many found"""
692  if name is None:
693  return self._primarySvc
694  else:
695  return self.__getOne( self._services, name, "Services")
696 

◆ getServices()

def python.ComponentAccumulator.ComponentAccumulator.getServices (   self)

Definition at line 687 of file ComponentAccumulator.py.

687  def getServices(self):
688  return self._services
689 

◆ merge()

def python.ComponentAccumulator.ComponentAccumulator.merge (   self,
  other,
  sequenceName = None 
)
Merging in the other accumulator

Definition at line 794 of file ComponentAccumulator.py.

794  def merge(self,other, sequenceName=None):
795  """Merging in the other accumulator"""
796  if other is None:
797  raise RuntimeError("merge called on object of type None: "
798  "did you forget to return a CA from a config function?")
799 
800  if not isinstance(other,ComponentAccumulator):
801  raise TypeError(f"Attempt to merge wrong type {type(other).__name__}. "
802  "Only instances of ComponentAccumulator can be added")
803 
804  context = (Context.hint if not ComponentAccumulator.debugMode else # noqa: F841
805  Context("When merging the ComponentAccumulator:\n{} \nto:\n{}".format(other._inspect(), self._inspect())))
806 
807  if other._privateTools is not None:
808  if isinstance(other._privateTools, Sequence):
809  raiseWithCurrentContext(RuntimeError(
810  "merge called on ComponentAccumulator with a dangling (array of) private tools\n"))
811  else:
812  raiseWithCurrentContext(RuntimeError(
813  "merge called on ComponentAccumulator with a dangling private tool "
814  f"{other._privateTools.__cpp_type__}/{other._privateTools.name}"))
815 
816  if not other._isMergable:
817  raiseWithCurrentContext(ConfigurationError(
818  "Attempted to merge a top level ComponentAccumulator. Revert the order of merging\n"))
819 
820  def mergeSequences( dest, src ):
821 
822  # Ensure sequences of same name have same properties. This is called many times
823  # and is highly optimized. Make sure you profile before modifying this code.
824  if dest.name == src.name:
825  # Compare all set properties ignoring 'Members'
826  props = (dest._properties.keys() | src._properties.keys()) - {'Members'}
827  for seqProp in props:
828  try:
829  if dest._properties[seqProp] != src._properties[seqProp]:
830  raise RuntimeError(
831  f"Merging two sequences with name '{dest.name}' but property '{seqProp}' "
832  f"has different values: {getattr(dest, seqProp)} vs {getattr(src, seqProp)}")
833  except KeyError as e:
834  raise RuntimeError(
835  f"Merging two sequences with name '{dest.name}' but property '{e}' is not "
836  f"set in one of them")
837 
838  for childIdx, c in enumerate(src.Members):
839  if isSequence( c ):
840  sub = findSubSequence( dest, c.name ) #depth=1 ???
841  if sub:
842  mergeSequences(sub, c )
843  else:
844  self._msg.debug(" Merging sequence %s to a destination sequence %s", c.name, dest.name )
845  algorithmsByName = findAllAlgorithmsByName(c) # dictionary: algName (alg, parentSeq, indexInParentSeq)
846  for name, existingAlgs in algorithmsByName.items():
847  # all algorithms from incoming CA are already deduplicated, so we can only handle the fist one
848  algInstance, _, _ = existingAlgs[0]
849  if name not in self._algorithms:
850  self._algorithms[name] = algInstance
851  else:
852  dedupContext1 = createContextForDeduplication("While merging sequences adding incoming algorithm", c.name, other._componentsContext) # noqa : F841
853  dedupContext2 = createContextForDeduplication("While merging sequences adding to existing algorithm", c.name, self._componentsContext) # noqa : F841
854  deduplicateOne(self._algorithms[name], algInstance)
855  deduplicateOne(algInstance, self._algorithms[name])
856  for _, parent, idx in existingAlgs: # put the deduplicated algo back into original sequences
857  parent.Members[idx] = self._algorithms[name]
858  # Add the algorithm to the PerfMon domains
859  self.addAlgToPerfmonDomains(name, other._domainsRegistry[name] if name in other._domainsRegistry else self._currentDomain)
860  dest.Members.append(c)
861 
862  else: # an algorithm
863  if c.name in self._algorithms:
864  dedupContext1 = createContextForDeduplication("While merging sequences adding incoming algorithm", c.name, other._componentsContext) # noqa : F841
865  dedupContext2 = createContextForDeduplication("While merging sequences adding to existing algorithm", c.name, self._componentsContext) # noqa : F841
866 
867  deduplicateOne(self._algorithms[c.name], c)
868  deduplicateOne(c, self._algorithms[c.name])
869  src.Members[childIdx] = self._algorithms[c.name]
870  else:
871  self._algorithms[c.name] = c
872 
873  existingAlgInDest = findAlgorithm( dest, c.name, depth=1 )
874  if not existingAlgInDest:
875  self._msg.debug(" Adding algorithm %s to a sequence %s", c.name, dest.name )
876  dest.Members.append(c)
877 
878  # Add the algorithm to the PerfMon domains
879  self.addAlgToPerfmonDomains(c.name, other._domainsRegistry[c.name] if c.name in other._domainsRegistry else self._currentDomain)
880 
881  # Merge sequences:
882  # mergeSequences(destSeq, other._sequence)
883  # if sequenceName is provided it means we should be ignoring the actual MAIN seq name there and use the sequenceName
884  # that means the first search in the destination sequence needs to be cheated
885  # the sequenceName argument is only relevant for the MAIN sequence,
886  # secondary top sequences are treated as if the sequenceName argument would not be provided
887 
888  for otherSeq in other._allSequences:
889  found=False
890  for ourSeq in self._allSequences:
891  destSeqName = otherSeq.name
892  if sequenceName and otherSeq == other._sequence: # if sequence moving is requested (sequenceName != None) it concerns only the main sequence
893  destSeqName = sequenceName
894  self._msg.verbose(" Will move sequence %s to %s", otherSeq.name, destSeqName )
895 
896  ourSeq = findSubSequence(ourSeq, destSeqName) # try to add sequence to the main structure first, to each seq in parent?
897  if ourSeq:
898  mergeSequences(ourSeq, otherSeq)
899  found=True
900  self._msg.verbose(" Succeeded to merge sequence %s to %s", otherSeq.name, ourSeq.name )
901  else:
902  self._msg.verbose(" Failed to merge sequence %s to any existing one, destination CA will have several top/dangling sequences", otherSeq.name )
903  if not found: # just copy the sequence as a dangling one
904  self._allSequences.append( otherSeq )
905  mergeSequences( self._allSequences[-1], otherSeq )
906 
907 
908 
909 
910 
911  # Additional checking and updating other accumulator's algorithms list
912  for name in other._algorithms:
913  if name not in self._algorithms:
914  raiseWithCurrentContext(ConfigurationError('Error in merging. Algorithm {} missing in destination accumulator\n'.format(name)))
915  other._algorithms[name] = self._algorithms[name]
916 
917  #self._conditionsAlgs+=other._conditionsAlgs
918  for condAlg in other._conditionsAlgs:
919  addContext = createContextForDeduplication("Merging incoming Conditions Algorithm", condAlg.name, other._componentsContext) # noqa : F841
920  self.addCondAlgo(condAlg) #Profit from deduplicaton here
921 
922  for svc in other._services:
923  addContext = createContextForDeduplication("Merging incoming Service", svc.name, other._componentsContext) # noqa : F841
924  self.addService(svc, create = svc.getFullJobOptName() in other._servicesToCreate) #Profit from deduplicaton here
925 
926  for pt in other._publicTools:
927  addContext = createContextForDeduplication("Merging incoming Public Tool", pt.name, other._componentsContext) # noqa : F841
928  self.addPublicTool(pt) #Profit from deduplicaton here
929 
930 
931  for aud in other._auditors:
932  addContext = createContextForDeduplication("Merging incoming Auditor", aud.name, other._componentsContext) # noqa : F841
933  self.addAuditor(aud) #Profit from deduplicaton here
934 
935  #Merge AppMgr properties:
936  for (k,v) in other._theAppProps.items():
937  self.setAppProperty(k,v) #Will warn about overrides
938  pass
939  other._wasMerged=True
940 
941  self._lastAddedComponent = other._lastAddedComponent #+ ' (Merged)'
942  self._componentsContext.update(other._componentsContext) # update the context so it contains an information about the new components (and refreshed old components)
943 

◆ popEventAlgo()

def python.ComponentAccumulator.ComponentAccumulator.popEventAlgo (   self,
  name,
  sequence = "AthAlgSeq" 
)

Definition at line 716 of file ComponentAccumulator.py.

716  def popEventAlgo(self,name,sequence="AthAlgSeq"):
717  s=self.getSequence(sequence)
718  lenBefore=len(s.Members)
719  s.Members = [a for a in s.Members if not a.getName()==name]
720  lenAfter=len(s.Members)
721  if lenAfter == lenBefore:
722  self._msg.warning("Algorithm %s not found in sequence %s",name,sequence)
723  else:
724  self._msg.info("Removed algorithm %s from sequence %s",name,sequence)
725  try:
726  return self._algorithms.pop(name)
727  except KeyError:
728  self._msg.warning("Algorithm %s not found in self._sequence ??? Returning 'None'",name)
729  return None
730 

◆ popPrivateTools()

def python.ComponentAccumulator.ComponentAccumulator.popPrivateTools (   self,
  quiet = False 
)
Get the (list of) private AlgTools from this ComponentAccumulator.
The CA will not keep any reference to the AlgTool. Throw an exception if
no tools are available unless quiet=True.

Definition at line 404 of file ComponentAccumulator.py.

404  def popPrivateTools(self, quiet=False):
405  """Get the (list of) private AlgTools from this ComponentAccumulator.
406  The CA will not keep any reference to the AlgTool. Throw an exception if
407  no tools are available unless quiet=True.
408  """
409  tool = self._privateTools
410  if not quiet and tool is None:
411  raise ConfigurationError("Private tool(s) requested, but none are present")
412  self._privateTools=None
413  return tool
414 

◆ popToolsAndMerge()

def python.ComponentAccumulator.ComponentAccumulator.popToolsAndMerge (   self,
  other 
)
Merging in the other accumulator and getting the (list of) private AlgTools
from this ComponentAccumulator.

Definition at line 415 of file ComponentAccumulator.py.

415  def popToolsAndMerge(self, other):
416  """ Merging in the other accumulator and getting the (list of) private AlgTools
417  from this ComponentAccumulator.
418  """
419  if other is None:
420  raise RuntimeError("popToolsAndMerge called on object of type None: "
421  "did you forget to return a CA from a config function?")
422  tool = other.popPrivateTools()
423  self.merge(other)
424  return tool
425 

◆ printCondAlgs()

def python.ComponentAccumulator.ComponentAccumulator.printCondAlgs (   self,
  summariseProps = False,
  onlyComponents = [],
  printDefaults = False,
  printComponentsOnly = False 
)

Definition at line 215 of file ComponentAccumulator.py.

215  def printCondAlgs(self, summariseProps=False, onlyComponents=[], printDefaults=False, printComponentsOnly=False):
216  self._msg.info( "Condition Algorithms" )
217  for (c, flag) in filterComponents (self._conditionsAlgs, onlyComponents):
218  self._msg.info( " \\__ %s (cond alg)%s", c.name, self._componentsContext.get(c.name,""))
219  if summariseProps and flag:
220  printProperties(self._msg, c, 1, printDefaults, printComponentsOnly)
221  return
222 
223 

◆ printConfig()

def python.ComponentAccumulator.ComponentAccumulator.printConfig (   self,
  withDetails = False,
  summariseProps = False,
  onlyComponents = [],
  printDefaults = False,
  printComponentsOnly = False,
  printSequenceTreeOnly = False,
  prefix = None 
)

Definition at line 228 of file ComponentAccumulator.py.

228  def printConfig(self, withDetails=False, summariseProps=False,
229  onlyComponents = [], printDefaults=False, printComponentsOnly=False, printSequenceTreeOnly=False, prefix=None):
230  msg = logging.getLogger(prefix) if prefix else self._msg
231 
232  msg.info( "Event Algorithm Sequences" )
233 
234  def printSeqAndAlgs(seq, nestLevel = 0,
235  onlyComponents = []):
236  def __prop(name):
237  if name in seq._properties:
238  return seq._properties[name]
239  return seq._descriptors[name].default
240  if withDetails:
241  msg.info( "%s\\__ %s (seq: %s %s)", " "*nestLevel, seq.name,
242  "SEQ" if __prop("Sequential") else "PAR",
243  "OR" if __prop("ModeOR") else "AND" + self._componentsContext.get(seq.name, "") )
244  else:
245  msg.info( "%s\\__ %s", " "*nestLevel, seq.name)
246 
247  nestLevel += 3
248  for (c, flag) in filterComponents(seq.Members, onlyComponents):
249  if isSequence(c):
250  printSeqAndAlgs(c, nestLevel, onlyComponents = onlyComponents )
251  else:
252  if withDetails:
253  msg.info( "%s\\__ %s (alg) %s", " "*nestLevel, c.getFullJobOptName(), self._componentsContext.get(c.name, ""))
254  else:
255  msg.info( "%s\\__ %s", " "*nestLevel, c.name )
256  if summariseProps and flag:
257  printProperties(msg, c, nestLevel, printDefaults, printComponentsOnly)
258 
259 
260  for n,s in enumerate(self._allSequences):
261  msg.info( "Top sequence %d", n )
262  printSeqAndAlgs(s, onlyComponents = onlyComponents)
263 
264  if printSequenceTreeOnly:
265  return
266 
267  self.printCondAlgs (summariseProps = summariseProps,
268  onlyComponents = onlyComponents)
269  msg.info( "Services" )
270  msg.info( [ s[0].name + (" (created) " if s[0].name in self._servicesToCreate else "")
271  for s in filterComponents (self._services, onlyComponents) ] )
272  msg.info( "Public Tools" )
273  msg.info( "[" )
274  for (t, flag) in filterComponents (self._publicTools, onlyComponents):
275  msg.info( " %s,", t.getFullJobOptName() + self._componentsContext.get(t.name,""))
276  # Not nested, for now
277  if summariseProps and flag:
278  printProperties(msg, t, printDefaults, printComponentsOnly)
279  msg.info( "]" )
280  msg.info( "Private Tools")
281  msg.info( "[" )
282  if self._privateTools:
283  for tool in self._privateTools if isinstance(self._privateTools, Sequence) else [self._privateTools]:
284  msg.info( " %s,", tool.getFullJobOptName() + self._componentsContext.get(tool.name,""))
285  if summariseProps:
286  printProperties(msg, tool, printDefaults, printComponentsOnly)
287  msg.info( "]" )
288  if self._auditors:
289  msg.info( "Auditors" )
290  msg.info( [ a[0].name for a in filterComponents(self._auditors, onlyComponents) ] )
291 
292  msg.info( "theApp properties" )
293  for k, v in self._theAppProps.items():
294  msg.info(" %s : %s", k, v)
295 

◆ printPerfmonDomains()

def python.ComponentAccumulator.ComponentAccumulator.printPerfmonDomains (   self)
Print the PerfMon domains. 

Definition at line 468 of file ComponentAccumulator.py.

468  def printPerfmonDomains(self):
469  """ Print the PerfMon domains. """
470  invertedDomains = self.getInvertedPerfmonDomains()
471  self._msg.info(":: This CA contains the following PerfMon domains ::")
472  self._msg.info(f":: There are a total of {len(self._domainsRegistry)} "
473  f"registered algorithms in {len(invertedDomains)} domains ::")
474  for domain, algs in invertedDomains.items():
475  self._msg.info(f"+ Domain : {domain}")
476  for alg in algs:
477  self._msg.info("\\_ %s", alg)
478  self._msg.info(":: End of PerfMon domains ::")
479 

◆ run()

def python.ComponentAccumulator.ComponentAccumulator.run (   self,
  maxEvents = None 
)

Definition at line 1116 of file ComponentAccumulator.py.

1116  def run(self,maxEvents=None):
1117  from os import environ
1118  outpklfile = environ.get("PICKLECAFILE", None)
1119  if outpklfile is not None:
1120  if outpklfile: # non-empty string
1121  self._msg.info("Storing configuration in pickle file %s",outpklfile)
1122  with open(outpklfile, "wb") as f:
1123  self.store(f)
1124  else: # empty string, just exit
1125  self.wasMerged()
1126  self._msg.info("Exiting after configuration stage")
1127  from Gaudi.Main import BootstrapHelper
1128  return BootstrapHelper.StatusCode(True)
1129 
1130  # Make sure python output is flushed before triggering output from Gaudi.
1131  # Otherwise, observed output ordering may differ between py2/py3.
1132  sys.stdout.flush()
1133 
1134 
1135  #Set TDAQ_ERS_NO_SIGNAL_HANDLERS to avoid interference with
1136  #TDAQ signal handling
1137  environ['TDAQ_ERS_NO_SIGNAL_HANDLERS']='1'
1138  from AthenaCommon.Debugging import allowPtrace, hookDebugger
1139  allowPtrace()
1140 
1141  checkSequenceConsistency(self._sequence)
1142 
1143  app = self.createApp()
1144  self.__verifyFinalSequencesStructure()
1145 
1146  #Determine maxEvents
1147  if maxEvents is None:
1148  if "EvtMax" in self._theAppProps:
1149  maxEvents=self._theAppProps["EvtMax"]
1150  else:
1151  maxEvents=-1
1152 
1153  if self.interactive == 'init':
1155  from sys import exit # noqa: F401
1156  startInteractive(locals())
1157 
1158  #At this point, we don't need the internal structures of this CA any more, clean them up
1159  self._cleanup()
1160 
1161  self._msg.info(f"Athena job with pid {os.getpid()}")
1162 
1163  if (self._debugStage.value == "init"):
1164  hookDebugger()
1165  sc = app.initialize()
1166  if not sc.isSuccess():
1167  self._msg.error("Failed to initialize AppMgr")
1168  return sc
1169 
1170  sc = app.start()
1171  if not sc.isSuccess():
1172  self._msg.error("Failed to start AppMgr")
1173  return sc
1174 
1175  if (self._debugStage.value=="exec"):
1176  hookDebugger()
1177 
1178 
1179  if self.interactive == 'run':
1181  from AthenaPython.PyAthena import py_svc
1182  sg=py_svc("StoreGateSvc/StoreGateSvc")
1183  startInteractive(locals())
1184  else:
1185  sc = app.run(maxEvents)
1186  if not sc.isSuccess():
1187  self._msg.error("Failure running application")
1188  return sc
1189 
1190  app.stop().ignore()
1191 
1192  if (self._debugStage.value == "fini"):
1193  hookDebugger()
1194  app.finalize().ignore()
1195 
1196  sc1 = app.terminate()
1197  return sc1
1198 

◆ setAppProperty()

def python.ComponentAccumulator.ComponentAccumulator.setAppProperty (   self,
  key,
  value,
  overwrite = False 
)

Definition at line 774 of file ComponentAccumulator.py.

774  def setAppProperty(self,key,value,overwrite=False):
775  if (overwrite or key not in (self._theAppProps)):
776  self._theAppProps[key]=value
777  else:
778  if self._theAppProps[key] == value:
779  self._msg.debug("ApplicationMgr property '%s' already set to '%s'.", key, value)
780  elif isinstance(self._theAppProps[key], Sequence) and not isinstance(self._theAppProps[key],str):
781  value=self._theAppProps[key] + [el for el in value if el not in self._theAppProps[key]]
782  self._msg.info("ApplicationMgr property '%s' already set to '%s'. Overwriting with %s", key, self._theAppProps[key], value)
783  self._theAppProps[key]=value
784  else:
785  raise DeduplicationFailed("AppMgr property {} set twice: {} and {}".format(key, self._theAppProps[key], value))
786 
787 

◆ setAsTopLevel()

def python.ComponentAccumulator.ComponentAccumulator.setAsTopLevel (   self)

Definition at line 144 of file ComponentAccumulator.py.

144  def setAsTopLevel(self):
145  self._isMergable = False
146 

◆ setDebugStage()

def python.ComponentAccumulator.ComponentAccumulator.setDebugStage (   self,
  stage 
)

Definition at line 788 of file ComponentAccumulator.py.

788  def setDebugStage(self,stage):
789  if stage not in DbgStage.allowed_values:
790  raise RuntimeError("Allowed arguments for setDebugStage are [{}]".format(",".join(DbgStage.allowed_values)))
791  self._debugStage.value = stage
792 
793 

◆ setPrivateTools()

def python.ComponentAccumulator.ComponentAccumulator.setPrivateTools (   self,
  privTool 
)
Use this method to carry private AlgTool(s) to the caller when returning this ComponentAccumulator.
The method accepts either a single private AlgTool or a list of private AlgTools (typically assigned to ToolHandleArray)

Definition at line 379 of file ComponentAccumulator.py.

379  def setPrivateTools(self,privTool):
380  """Use this method to carry private AlgTool(s) to the caller when returning this ComponentAccumulator.
381  The method accepts either a single private AlgTool or a list of private AlgTools (typically assigned to ToolHandleArray)
382  """
383  if self._privateTools is not None:
384  raise ConfigurationError("This ComponentAccumulator holds already a (list of) private tool(s). "
385  "Only one (list of) private tool(s) is allowed")
386 
387  if isinstance(privTool, Sequence):
388  for t in privTool:
389  if t.__component_type__ != 'AlgTool':
390  raise ConfigurationError("ComponentAccumulator.setPrivateTools accepts only ConfigurableAlgTools "
391  f"or lists of ConfigurableAlgTools. Encountered {type(t)} in a list")
392  else:
393  if privTool.__component_type__ != "AlgTool":
394  raise ConfigurationError("ComponentAccumulator.setPrivateTools accepts only ConfigurableAlgTools "
395  f"or lists of ConfigurableAlgTools. Encountered {type(privTool)}")
396 
397  self._privateTools=privTool
398  if "trackPrivateTool" in ComponentAccumulator.debugMode:
399  for tool in self._privateTools if isinstance(privTool, Sequence) else [self._privateTools]:
400  self._componentsContext[tool.name] = shortCallStack()
401 
402  return
403 

◆ store()

def python.ComponentAccumulator.ComponentAccumulator.store (   self,
  outfile,
  withDefaultHandles = False 
)
Saves CA in pickle form

when withDefaultHandles is True, also the handles that are not set are saved

Definition at line 966 of file ComponentAccumulator.py.

966  def store(self,outfile, withDefaultHandles=False):
967  """
968  Saves CA in pickle form
969 
970  when withDefaultHandles is True, also the handles that are not set are saved
971  """
972 
973  checkSequenceConsistency(self._sequence)
974 
975  self.wasMerged()
976  if withDefaultHandles:
977  from AthenaConfiguration.Utils import loadDefaultComps, exposeHandles
978  loadDefaultComps(self._allComponents())
979  exposeHandles(self._allComponents())
980  import pickle
981  pickle.dump(self,outfile)
982  return
983 
984 

◆ wasMerged()

def python.ComponentAccumulator.ComponentAccumulator.wasMerged (   self)
Declares CA as merged

This is temporarily needed by HLT and should not be used elsewhere

Definition at line 950 of file ComponentAccumulator.py.

950  def wasMerged(self):
951  """ Declares CA as merged
952 
953  This is temporarily needed by HLT and should not be used elsewhere
954  """
955  self._wasMerged=True
956 

Member Data Documentation

◆ _algorithms

python.ComponentAccumulator.ComponentAccumulator._algorithms
private

Definition at line 120 of file ComponentAccumulator.py.

◆ _allSequences

python.ComponentAccumulator.ComponentAccumulator._allSequences
private

Definition at line 119 of file ComponentAccumulator.py.

◆ _auditors

python.ComponentAccumulator.ComponentAccumulator._auditors
private

Definition at line 124 of file ComponentAccumulator.py.

◆ _checkUnmerged

python.ComponentAccumulator.ComponentAccumulator._checkUnmerged
staticprivate

Definition at line 94 of file ComponentAccumulator.py.

◆ _componentsContext

python.ComponentAccumulator.ComponentAccumulator._componentsContext
private

Definition at line 140 of file ComponentAccumulator.py.

◆ _conditionsAlgs

python.ComponentAccumulator.ComponentAccumulator._conditionsAlgs
private

Definition at line 121 of file ComponentAccumulator.py.

◆ _creationCallStack

python.ComponentAccumulator.ComponentAccumulator._creationCallStack
private

Definition at line 139 of file ComponentAccumulator.py.

◆ _currentDomain

python.ComponentAccumulator.ComponentAccumulator._currentDomain
private

Definition at line 127 of file ComponentAccumulator.py.

◆ _debugStage

python.ComponentAccumulator.ComponentAccumulator._debugStage
private

Definition at line 141 of file ComponentAccumulator.py.

◆ _domainsRegistry

python.ComponentAccumulator.ComponentAccumulator._domainsRegistry
private

Definition at line 128 of file ComponentAccumulator.py.

◆ _isMergable

python.ComponentAccumulator.ComponentAccumulator._isMergable
private

Definition at line 137 of file ComponentAccumulator.py.

◆ _lastAddedComponent

python.ComponentAccumulator.ComponentAccumulator._lastAddedComponent
private

Definition at line 138 of file ComponentAccumulator.py.

◆ _msg

python.ComponentAccumulator.ComponentAccumulator._msg
private

Definition at line 107 of file ComponentAccumulator.py.

◆ _primaryComp

python.ComponentAccumulator.ComponentAccumulator._primaryComp
private

Definition at line 126 of file ComponentAccumulator.py.

◆ _privateTools

python.ComponentAccumulator.ComponentAccumulator._privateTools
private

Definition at line 125 of file ComponentAccumulator.py.

◆ _publicTools

python.ComponentAccumulator.ComponentAccumulator._publicTools
private

Definition at line 133 of file ComponentAccumulator.py.

◆ _sequence

python.ComponentAccumulator.ComponentAccumulator._sequence
private

Definition at line 118 of file ComponentAccumulator.py.

◆ _services

python.ComponentAccumulator.ComponentAccumulator._services
private

Definition at line 122 of file ComponentAccumulator.py.

◆ _servicesToCreate

python.ComponentAccumulator.ComponentAccumulator._servicesToCreate
private

Definition at line 123 of file ComponentAccumulator.py.

◆ _theAppProps

python.ComponentAccumulator.ComponentAccumulator._theAppProps
private

Definition at line 130 of file ComponentAccumulator.py.

◆ _wasMerged

python.ComponentAccumulator.ComponentAccumulator._wasMerged
private

Definition at line 136 of file ComponentAccumulator.py.

◆ debugMode

python.ComponentAccumulator.ComponentAccumulator.debugMode
static

Definition at line 93 of file ComponentAccumulator.py.

◆ interactive

python.ComponentAccumulator.ComponentAccumulator.interactive

Definition at line 142 of file ComponentAccumulator.py.


The documentation for this class was generated from the following file:
grepfile.info
info
Definition: grepfile.py:38
store
StoreGateSvc * store
Definition: fbtTestBasics.cxx:71
python.DebuggingContext.raiseWithCurrentContext
def raiseWithCurrentContext(exception)
Definition: DebuggingContext.py:44
vtune_athena.format
format
Definition: vtune_athena.py:14
python.CFElements.findAllAlgorithmsByName
def findAllAlgorithmsByName(sequence, namesToLookFor=None)
Definition: CFElements.py:167
run
int run(int argc, char *argv[])
Definition: ttree2hdf5.cxx:28
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.DebuggingContext.createContextForDeduplication
def createContextForDeduplication(message, compName, destContext)
Definition: DebuggingContext.py:40
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:805
DiTauMassTools::ignore
void ignore(T &&)
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:58
python.Bindings.py_svc
def py_svc(svcName, createIf=True, iface=None)
Definition: Control/AthenaPython/python/Bindings.py:98
python.Debugging.allowPtrace
def allowPtrace()
Definition: Debugging.py:65
python.CFElements.checkSequenceConsistency
def checkSequenceConsistency(seq)
Definition: CFElements.py:69
python.Debugging.hookDebugger
def hookDebugger(debugger='gdb')
Definition: Debugging.py:22
python.Utils.exposeHandles
def exposeHandles(allcomps)
Definition: Control/AthenaConfiguration/python/Utils.py:32
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
debug
const bool debug
Definition: MakeUncertaintyPlots.cxx:53
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
python.JetAnalysisCommon.isComponentAccumulatorCfg
isComponentAccumulatorCfg
Definition: JetAnalysisCommon.py:263
python.processes.powheg.ZZ.ZZ.__init__
def __init__(self, base_directory, **kwargs)
Constructor: all process options are set here.
Definition: ZZ.py:18
python.ComponentAccumulator.startInteractive
def startInteractive(localVarDic)
Definition: ComponentAccumulator.py:1220
Trk::open
@ open
Definition: BinningType.h:40
python.AthDsoLogger.__del__
def __del__(self)
Definition: AthDsoLogger.py:82
python.Deduplication.deduplicateOne
def deduplicateOne(newComp, oldComp)
Definition: Deduplication.py:45
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
python.TriggerHandler.verbose
verbose
Definition: TriggerHandler.py:297
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.utility.LHE.merge
def merge(input_file_pattern, output_file)
Merge many input LHE files into a single output file.
Definition: LHE.py:29
python.ComponentAccumulator.printInteractiveMsg_run
def printInteractiveMsg_run()
Definition: ComponentAccumulator.py:1246
str
Definition: BTagTrackIpAccessor.cxx:11
python.CFElements.isSequence
def isSequence(obj)
Definition: CFElements.py:96
calibdata.copy
bool copy
Definition: calibdata.py:27
python.CFElements.findSubSequence
def findSubSequence(start, nameToLookFor)
Definition: CFElements.py:100
python.CFElements.findAlgorithm
def findAlgorithm(startSequence, nameToLookFor, depth=1000000)
Definition: CFElements.py:145
python.ComponentAccumulator.printInteractiveMsg_init
def printInteractiveMsg_init()
Definition: ComponentAccumulator.py:1237
python.DebuggingContext.shortCallStack
def shortCallStack()
Definition: DebuggingContext.py:29
python.Utils.loadDefaultComps
def loadDefaultComps(allcomps)
Definition: Control/AthenaConfiguration/python/Utils.py:6
python.Deduplication.deduplicate
def deduplicate(newComp, compList)
Definition: Deduplication.py:15
error
Definition: IImpactPoint3dEstimator.h:70
python.ComponentAccumulator.printProperties
def printProperties(msg, c, nestLevel=0, printDefaults=False, onlyComponentsOnly=False)
Definition: ComponentAccumulator.py:37
WriteBchToCool.update
update
Definition: WriteBchToCool.py:67
python.ComponentAccumulator.filterComponents
def filterComponents(comps, onlyComponents=[])
Definition: ComponentAccumulator.py:79
python.CFElements.iterSequences
def iterSequences(start)
Definition: CFElements.py:206